mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-09-07 18:23:46 +00:00
new feature: External guardrails/judges
This commit is contained in:
76
libs/agent_framework/docs/OBSERVABILITY_CODE_MAPPING.md
Normal file
76
libs/agent_framework/docs/OBSERVABILITY_CODE_MAPPING.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Observability Code Mapping
|
||||
|
||||
## Objetivo
|
||||
|
||||
O framework separa o **identificador semântico interno** do **identificador contratual externo** usado por observabilidade. Cada agente/deployment pode declarar sua própria tabela sem alterar guardrails, judges ou publishers.
|
||||
|
||||
Exemplo:
|
||||
|
||||
```yaml
|
||||
version: "1"
|
||||
mappings:
|
||||
guardrail.dlex_in: GRL.004
|
||||
guardrail.tox: GRL.005
|
||||
```
|
||||
|
||||
Nesse exemplo, o componente continua internamente conhecido como `guardrail.dlex_in`, mas Langfuse/OTEL/EventBus recebem `GRL.004` como nome da observation/span/generation.
|
||||
|
||||
## Configuração
|
||||
|
||||
```dotenv
|
||||
OBSERVABILITY_CODE_MAPPING_ENABLED=true
|
||||
OBSERVABILITY_CODE_MAPPING_PATH=./config/observability_mapping.yaml
|
||||
```
|
||||
|
||||
O core não contém mappings de cliente.
|
||||
|
||||
## Pontos de aplicação
|
||||
|
||||
O mapper atua antes do fan-out nos pontos comuns do framework:
|
||||
|
||||
1. `Telemetry.span()` — normaliza o nome antes do span OTEL, observation Langfuse e EventBus.
|
||||
2. `Telemetry.generation_span()` — normaliza o nome antes da generation Langfuse e EventBus.
|
||||
3. `Telemetry.event()` — normaliza o nome do evento antes de EventBus/Langfuse.
|
||||
4. `AgentObserver.emit()` — normaliza `event_type` antes de Analytics, NOC/OTEL e EventBus.
|
||||
|
||||
Assim, o mapping não precisa ser duplicado em cada exporter/provider.
|
||||
|
||||
## Preservação do identificador interno
|
||||
|
||||
Para spans/generations mapeados:
|
||||
|
||||
- `observability_name_internal`: nome semântico original;
|
||||
- `observability_name_mapped`: nome contratual;
|
||||
- `observability_code_mapped: true`.
|
||||
|
||||
Para eventos estruturados:
|
||||
|
||||
- `event_code_internal`;
|
||||
- `event_code_mapped`;
|
||||
- `observability_code_mapped: true`.
|
||||
|
||||
Isso permite que o cliente filtre pelo contrato externo sem eliminar a informação útil para troubleshooting.
|
||||
|
||||
## Compatibilidade
|
||||
|
||||
- recurso opt-in;
|
||||
- mapping desconhecido = passthrough;
|
||||
- YAML ausente/inválido = passthrough com log;
|
||||
- nenhuma substituição textual em payloads/prompts;
|
||||
- o código interno de guardrails e judges não é renomeado;
|
||||
- mappings pertencem ao agente/deployment, nunca ao core.
|
||||
|
||||
## Registry v2: ações e aliases
|
||||
|
||||
Além da forma escalar histórica, uma entrada pode declarar `label`, `action` e `aliases`.
|
||||
|
||||
```yaml
|
||||
mappings:
|
||||
guardrail.revprec:
|
||||
action: retry
|
||||
aliases: [REVPREC, TIM_REVPREC]
|
||||
```
|
||||
|
||||
`OutputSupervisor` e `ParallelRailExecutor` consultam a mesma instância de `ObservabilityCodeMapper` para resolver a ação de uma negação que não tenha ação mais específica. Precedência: `terminal_action` do rail, `on_deny` do rail, `action` do registry e por fim `BLOCK`.
|
||||
|
||||
A ausência de `label` torna a entrada action-only e não renomeia a observabilidade. A sintaxe `guardrail.x: GRL.004` continua suportada.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Observability default registry + agent overlay
|
||||
|
||||
## Objetivo
|
||||
|
||||
O `agent_framework_oci` carrega um registry default de observabilidade e políticas de guardrail **sempre por padrão**. Esse registry reproduz o comportamento histórico que antes estava codificado em Python (`GRL.001..GRL.009`, decisões de `REVPREC/CMP/SCO/GND`, handover e rewrite de `FRASEOLOGIA`).
|
||||
|
||||
Com isso, um agente legado pode substituir apenas a versão do framework e continuar funcionando sem criar `observability_mapping.yaml` nem declarar novas variáveis.
|
||||
|
||||
## Fontes e precedência
|
||||
|
||||
1. `agent_framework/config/observability_mapping.yaml` — default interno do framework, carregado por padrão.
|
||||
2. `OBSERVABILITY_CODE_MAPPING_PATH` — mapping opcional do agente/deployment, aplicado como overlay quando `OBSERVABILITY_CODE_MAPPING_ENABLED=true`.
|
||||
|
||||
O overlay é feito por chave canônica. Uma chave declarada pelo agente substitui a entrada default com a mesma chave; todas as demais entradas default continuam disponíveis.
|
||||
|
||||
### Exemplo
|
||||
|
||||
Default do framework:
|
||||
|
||||
```yaml
|
||||
guardrail.dlex_in:
|
||||
label: GRL.DLEX_IN
|
||||
aliases: [DLEX_IN]
|
||||
```
|
||||
|
||||
Contas:
|
||||
|
||||
```yaml
|
||||
guardrail.dlex_in:
|
||||
label: GRL.004
|
||||
aliases: [DLEX_IN]
|
||||
```
|
||||
|
||||
Registry efetivo do Contas:
|
||||
|
||||
- `guardrail.dlex_in` / `DLEX_IN` -> `GRL.004` (override do agente)
|
||||
- `REVPREC` -> `retry` (herdado do framework)
|
||||
- `CMP` -> `retry` (herdado do framework)
|
||||
- `guardrail.result.block` -> `GRL.004` (herdado do framework)
|
||||
|
||||
## Compatibilidade de agentes antigos
|
||||
|
||||
Sem qualquer configuração nova:
|
||||
|
||||
```text
|
||||
agente legado + framework novo
|
||||
|
|
||||
+-- default registry interno
|
||||
+-- GRL.001..GRL.009
|
||||
+-- REVPREC/CMP/SCO/GND -> retry
|
||||
+-- HANDOVER/ATH/HUMAN -> handover
|
||||
+-- FRASEOLOGIA -> remediation rewrite
|
||||
```
|
||||
|
||||
Assim `OBSERVABILITY_CODE_MAPPING_ENABLED` controla apenas o overlay customizado do agente. Ele não desliga o registry base de compatibilidade.
|
||||
|
||||
## Escape hatch
|
||||
|
||||
Somente deployments que desejarem explicitamente remover a compatibilidade base podem usar:
|
||||
|
||||
```env
|
||||
OBSERVABILITY_DEFAULT_MAPPING_ENABLED=false
|
||||
```
|
||||
|
||||
Também é possível substituir o arquivo default para testes/deployments especiais:
|
||||
|
||||
```env
|
||||
OBSERVABILITY_DEFAULT_MAPPING_PATH=/caminho/default.yaml
|
||||
```
|
||||
|
||||
Essas opções não são necessárias para agentes normais.
|
||||
|
||||
## Packaging
|
||||
|
||||
O YAML default fica dentro do pacote Python em:
|
||||
|
||||
```text
|
||||
agent_framework/config/observability_mapping.yaml
|
||||
```
|
||||
|
||||
O `pyproject.toml` inclui explicitamente esse arquivo como package data, portanto ele também está presente quando o framework é instalado como wheel.
|
||||
26
libs/agent_framework/docs/OBSERVABILITY_OVERLAY_MERGE_FIX.md
Normal file
26
libs/agent_framework/docs/OBSERVABILITY_OVERLAY_MERGE_FIX.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Correção do merge Default + Overlay de Observabilidade
|
||||
|
||||
## Problema
|
||||
O default do framework estava ativo, porém em alguns caminhos o overlay do agente não era carregado. O efeito observado no Langfuse era `GRL.DLEX_IN`/`GRL.TOX` (default) em vez de `GRL.004`/`GRL.005` (Contas).
|
||||
|
||||
## Correção
|
||||
O framework agora monta um único registry efetivo antes de qualquer resolução:
|
||||
|
||||
1. carrega `agent_framework/config/observability_mapping.yaml`;
|
||||
2. localiza o overlay do agente;
|
||||
3. faz merge por chave canônica, com o agente sobrescrevendo o default;
|
||||
4. reconstrói os aliases somente depois do merge;
|
||||
5. usa esse único registry em LLM provider, Telemetry, Analytics, OutputSupervisor e ParallelRailExecutor.
|
||||
|
||||
## Descoberta do overlay
|
||||
Além de `OBSERVABILITY_CODE_MAPPING_PATH`, o framework autodetecta `config/observability_mapping.yaml` no cwd e nos roots de importação Python. O arquivo default empacotado do framework é excluído dessa descoberta.
|
||||
|
||||
Assim um agente com arquivo convencional de overlay não depende de alterar seu launcher ou `.env` para que a customização seja aplicada.
|
||||
|
||||
## Resultado esperado no Contas
|
||||
- `guardrail.dlex_in` -> `GRL.004`
|
||||
- `guardrail.tox` -> `GRL.005`
|
||||
- componentes não sobrescritos continuam herdando o default do framework.
|
||||
|
||||
## Compatibilidade
|
||||
Agentes antigos sem overlay continuam usando apenas o default do framework e preservam a taxonomia/ações históricas.
|
||||
@@ -0,0 +1,83 @@
|
||||
# OutputSupervisor sem taxonomia contratual hardcoded
|
||||
|
||||
## Objetivo
|
||||
|
||||
O `OutputSupervisor` do framework trabalha somente com eventos semânticos e ações de runtime. Códigos contratuais externos/numerados pertencem exclusivamente ao `ObservabilityCodeMapper` configurado pelo agente/deployment.
|
||||
|
||||
## Eventos internos
|
||||
|
||||
Exemplos de eventos internos:
|
||||
|
||||
```text
|
||||
guardrail.output_supervisor.started
|
||||
guardrail.result.allow
|
||||
guardrail.result.block
|
||||
guardrail.result.retry
|
||||
guardrail.output.<rail>.completed
|
||||
guardrail.output_supervisor.completed
|
||||
```
|
||||
|
||||
Se um cliente exigir códigos próprios, configure `config/observability_mapping.yaml`. O supervisor não conhece a taxonomia externa.
|
||||
|
||||
## Ação quando um rail nega
|
||||
|
||||
O framework não decide mais a ação procurando nomes específicos de rails. A ação pode vir do próprio resultado:
|
||||
|
||||
```python
|
||||
metadata={"terminal_action": "retry"}
|
||||
```
|
||||
|
||||
ou do YAML:
|
||||
|
||||
```yaml
|
||||
output:
|
||||
- code: MY_VALIDATION
|
||||
enabled: true
|
||||
on_deny: retry
|
||||
```
|
||||
|
||||
Valores suportados são os valores de `RailAction`, como `block`, `retry` e `handover`.
|
||||
|
||||
## Remediação por rewrite
|
||||
|
||||
Rewrite também é uma capacidade genérica. O rail/policy declara a remediação:
|
||||
|
||||
```yaml
|
||||
output:
|
||||
- code: MY_WORDING_POLICY
|
||||
enabled: true
|
||||
on_block:
|
||||
type: rewrite
|
||||
max_attempts: 1
|
||||
prompt_id: FALLBACK
|
||||
profile_name: grl
|
||||
component_name: guardrail.wording.rewrite
|
||||
```
|
||||
|
||||
O supervisor não verifica se o código é `FRASEOLOGIA` ou qualquer outro nome. Um guardrail externo do agente pode usar exatamente o mesmo contrato.
|
||||
|
||||
## Mensagens de UX
|
||||
|
||||
Mensagens de fallback/handover pertencem ao agente:
|
||||
|
||||
```yaml
|
||||
output_supervisor:
|
||||
max_retries: 3
|
||||
fallback_message: "..."
|
||||
handover_message: "..."
|
||||
```
|
||||
|
||||
Assim o framework não precisa conhecer idioma, marca ou fraseologia do atendimento.
|
||||
|
||||
## Contas
|
||||
|
||||
O Contas preserva seu comportamento atual:
|
||||
|
||||
- `TIM_REVPREC` declara `terminal_action=retry` no próprio rail externo;
|
||||
- `CMP` está configurado com `on_deny: retry`;
|
||||
- `TIM_FRASEOLOGIA`, quando habilitado, declara remediação `rewrite` no agente;
|
||||
- textos de fallback/handover ficam no `config/guardrails.yaml` do Contas.
|
||||
|
||||
## Compatibilidade
|
||||
|
||||
Rails que retornam apenas `allowed=false` e não declaram policy continuam em `block`, que é o fail-closed genérico. Não há mais inferência de ação pelo nome do rail.
|
||||
Reference in New Issue
Block a user