adjustments: manual v2

This commit is contained in:
2026-09-12 08:04:25 -03:00
parent 2f9b053098
commit dd207b4078
21 changed files with 1174 additions and 76 deletions

View File

@@ -160,33 +160,23 @@ _, decisions = await pipeline.run_tool(
### SPI de guardrails e judges externos
> Conteúdo consolidado a partir de `docs/EXTERNAL_GUARDRAILS_JUDGES.md`.
Use extensões quando a política ou o critério de qualidade pertencer ao domínio do agente. Um guardrail implementa `evaluate(text, context) -> RailDecision` e pode atuar em `input`, `retrieval`, `tool` ou `output`. Um judge implementa `evaluate(question, answer, context) -> JudgeResult` e avalia a resposta sem reescrevê-la.
`agent_framework_oci` supports agent-owned guardrails and judges without importing domain code into the core.
O guia [Guardrails e judges externos](../../EXTERNAL_GUARDRAILS_JUDGES.md) contém a estrutura de diretórios, imports, classes completas para copiar, YAML, explicação de cada declaração, fail-open/fail-closed, observabilidade e teste executável.
```yaml
output:
- code: ACME_POLICY
type: external
class: app.extensions.guardrails:AcmePolicyRail
```
Pontos indispensáveis:
```yaml
judges:
- name: acme_quality
type: external
class: app.extensions.judges:AcmeQualityJudge
threshold: 0.7
```
- `type: external` e `class: pacote.modulo:Classe` ativam o import dinâmico;
- `kwargs` são argumentos do construtor; judges também podem receber `llm` e `settings` injetados;
- guardrails externos não recebem `llm` no construtor: o pipeline o disponibiliza no contexto somente quando criado com `llm=...`;
- métodos síncronos rodam em worker thread; métodos assíncronos rodam no event loop;
- judges são concorrentes e preservam a ordem declarada no YAML;
- exceções esperadas de judges externos devem ser tratadas pela implementação;
- códigos, regras e vocabulário de negócio ficam no pacote do agente, nunca importados pelo core.
Native entries remain unchanged. External synchronous `evaluate()` methods execute in worker threads via `asyncio.to_thread`; asynchronous methods execute concurrently on the framework event loop. Judges run concurrently with `asyncio.gather`, preserving YAML result order. Agent plugins should reuse the LLM supplied by the framework rather than instantiate a separate provider.
> **Limitação atual:** o `agent_template_backend` instancia um par global de pipelines no startup. Os campos `guardrails_config_path` e `judges_config_path` do registro não selecionam automaticamente configurações por requisição. Extensões dependentes de LLM também exigem que a composição passe `llm` e `settings` aos pipelines, conforme o guia completo.
The core must not reference a concrete agent package, company, product, telecom identifier or domain-specific policy. Domain-specific variants belong to the agent and should receive distinct public codes/names.
### Compatibility rule
Domain policies must not be replaced by cosmetically generic text inside the core while losing the original policy. The generic core implementation and the agent-specific implementation may coexist; the embedding agent explicitly selects its own code/name in YAML.
Legacy business validators should migrate to the agent domain. A temporary compatibility shim is acceptable for old imports, but new application code must import the agent-owned implementation.
Valide o exemplo publicado com `pytest -q tests/test_external_guardrails_judges_documentation.py`.
### Execução obrigatória de judges em transações

View File

@@ -0,0 +1,152 @@
### Workflows transacionais avançados
### Objetivo
Este capítulo ensina a transformar uma tool sensível em uma transação determinística, com coleta de parâmetros, pré-validação, confirmação, workflow versionado, pausa/retomada, idempotência e recuperação. A regra de negócio e as actions ficam no agente; o motor de execução fica no framework.
### Fluxo real
1. `routing.yaml` escolhe o agente e restringe as tools candidatas.
2. `tools.yaml` descreve argumentos, prompts e resposta.
3. `mcp_parameter_mapping.yaml` resolve identidade, defaults e extrações.
4. `tool_policies.yaml` classifica a operação e exige confirmação.
5. A pré-validação opcional verifica se a operação pode prosseguir sem causar efeito.
6. Após confirmação inequívoca, a execução é direta ou encaminhada ao `WorkflowToolExecutor`.
7. O `WorkflowRuntime` carrega a versão ativa, executa actions, persiste pausa e devolve `COMPLETED`, `PAUSED` ou `FAILED`.
8. A chave idempotente impede a repetição do efeito externo.
### Catálogo e política são contratos diferentes
```yaml
# config/tools.yaml
tools:
solicitar_devolucao:
description: Abre uma devolução de pedido.
mcp_server: retail
enabled: true
tool_type: action
confirmation_required: true
requires: [order_id, reason]
args_schema:
order_id:
type: string
label: o número do pedido
user_prompt: Informe o número do pedido.
reason:
type: string
label: o motivo da devolução
user_prompt: Qual é o motivo da devolução?
```
```yaml
# config/tool_policies.yaml
version: 1
defaults:
operation_type: read_only
require_confirmation: false
tool_policies:
solicitar_devolucao:
operation_type: transactional
require_confirmation: true
requires: [order_id, reason]
pre_validation:
enabled: true
tool: validar_devolucao
fail_open: false
execution:
mode: workflow
workflow: devolucao_pedido
version: active
```
`tools.yaml` é o catálogo público. `tool_policies.yaml` governa efeitos. Não confie somente em `confirmation_required` do catálogo: a política efetiva deve declarar `operation_type` e `require_confirmation`. `pre_validation.tool` deve ser read-only e nunca executar a transação antecipadamente. Para segurança, use `fail_open: false`.
### Definição versionada do workflow
```yaml workflow-definition-example
name: devolucao_pedido
version: 1
start: validar_pedido
nodes:
- id: validar_pedido
action: validar_pedido
input:
order_id: $.input.order_id
- id: registrar_devolucao
action: registrar_devolucao
retry: 1
input:
order_id: $.input.order_id
reason: $.input.reason
edges:
- from: validar_pedido
to: registrar_devolucao
when:
path: $.nodes.validar_pedido.valid
equals: true
- from: validar_pedido
to: END
when:
path: $.nodes.validar_pedido.valid
equals: false
- from: registrar_devolucao
to: END
```
Salve como `workflows/devolucao_pedido.v1.yaml`. O arquivo `devolucao_pedido.active.yaml` deve apontar para uma definição válida da versão ativa. IDs de nós não podem repetir; `start`, destinos e `resume_from` precisam existir. `retry` aceita de 0 a 10. Paths `$.input.*` leem a entrada e `$.nodes.<id>.*` leem resultados anteriores.
### Actions pertencentes ao agente
```python workflow-actions-example
from agent_framework.workflows import workflow_action
@workflow_action("validar_pedido")
async def validar_pedido(params: dict, state: dict) -> dict:
return {"valid": bool(params.get("order_id"))}
@workflow_action("registrar_devolucao")
async def registrar_devolucao(params: dict, state: dict) -> dict:
order_id = str(params["order_id"])
return {"protocol": f"DEV-{order_id}", "status": "REQUESTED"}
```
O nome do decorator deve ser igual a `node.action`. A assinatura obrigatória é `(params: dict, state: dict) -> dict`. O módulo precisa ser importado no startup para registrar decorators. Actions devem devolver dados serializáveis; não devolva cliente HTTP, conexão, exception ou coroutine.
### Idempotência do efeito externo
```python idempotency-example
async def execute_once(store, customer_key: str, order_id: str, invoke):
key = store.canonical_key(customer_key, order_id, "solicitar_devolucao", "v1")
previous = await store.get(key)
if previous is not None:
return previous
result = await invoke()
await store.set(key, result)
return result
```
Crie uma única instância no startup com `create_idempotency_store(settings, namespace="return-request", require_durable=True)` e injete-a nas actions. Use componentes de negócio estáveis na chave; nunca use apenas timestamp. `IDEMPOTENCY_PROVIDER` tem precedência sobre checkpoint, session e cache. Em produção transacional, configure `IDEMPOTENCY_REQUIRE_DURABLE=true` e um provider `oracle`, `redis` ou `sqlite` apropriado. `memory` não protege entre pods ou reinícios. Grave o resultado somente depois de o efeito ter sido confirmado pelo sistema externo.
### Pausa, entrada esperada e retomada
Um nó pode declarar `pause.expected_input` com `key`, `allowed_values`, normalização, `reprompt` e classificador semântico. A confirmação explícita continua determinística; o classificador só trata respostas inconclusivas e deve retornar uma das opções permitidas. `contextual_reentry` libera o workflow e devolve a fala ao roteamento normal, sem confirmar fatos automaticamente.
Ao retomar, use o mesmo `execution_id`. Uma nova execução cria outra transação. O checkpoint deve conter somente dados serializáveis e suficientes para reconstruir a pausa. Respostas duplicadas precisam consultar idempotência antes de repetir qualquer efeito.
### Intent shift e limpeza
Quando o usuário abandona a transação, limpe `pending_tool_call`, argumentos coletados, confirmação e estado transacional relacionado. Não reutilize parâmetros de uma transação encerrada. Uma pergunta contextual durante a pausa pode ser respondida e retornar ao workflow; uma mudança real de intenção encerra ou suspende explicitamente o fluxo conforme a política do agente.
### Recuperação e post-finalization replay
- `PAUSED`: persistir `execution_id`, prompt e contrato da entrada esperada.
- `FAILED`: manter detalhes técnicos na telemetria e uma mensagem segura ao usuário.
- timeout após envio: consultar idempotência ou status externo antes de reenviar.
- replay depois de `COMPLETED`: devolver o resultado persistido; nunca executar novamente.
- versão nova: execuções em andamento continuam com sua versão; `active` vale para novas execuções.
### Como testar
Teste grafo inválido, caminho válido/inválido, retry, pause/resume, resposta não reconhecida, intent shift, duplicidade, falha do provider de idempotência e replay após finalização. O contrato copiável deste capítulo é validado por `tests/test_advanced_developer_documentation.py`.

View File

@@ -0,0 +1,122 @@
### Routing, parâmetros e estado avançados
### Precedência de decisão
O desenvolvedor não deve tratar `routing.yaml` como uma lista de palavras. A decisão combina estado pendente, regras determinísticas e fallback semântico. A ordem segura é:
1. bloqueio ou finalização explícita;
2. transação/coleção pendente por `state_policies`;
3. confirmação determinística;
4. intenção determinística por keywords/examples/priority;
5. fallback LLM, quando habilitado;
6. `fallback_agent` ou handoff.
O estado pendente tem precedência para que “sim”, “não” ou um parâmetro isolado não sejam roteados para outro agente.
### Contrato comentado do `routing.yaml`
```yaml routing-advanced-example
router:
mode: router
fallback_agent: billing_agent
confidence_threshold: 0.65
allow_handoff: true
transaction_confirmation:
semantic_fallback:
enabled: true
allowed_values: [SIM, NAO, CONTINUAR]
confirm_values: [SIM]
reject_values: [NAO]
continue_values: [CONTINUAR]
include_relevant_context: true
profile_name: router
prompt: |
Classifique somente como {{ allowed_values }}.
Pergunta pendente: {{ pending_prompt }}
Histórico relevante: {{ relevant_conversation_context }}
Resposta atual: {{ user_input }}
state_policies:
- state: COLLECTING_FINANCIAL_PARAMETERS
agent: financeiro_agent
description: Mantém respostas curtas na coleta financeira.
- state: WAITING_FINANCIAL_CONFIRMATION
agent: financeiro_agent
description: Mantém a confirmação no fluxo financeiro.
intents:
- name: financial_analysis
domain: financial
agent: financeiro_agent
description: Consulta saldo, posição e movimentações.
priority: 10
mcp_tools: [consultar_saldo, consultar_movimentacoes]
keywords: [saldo, extrato, movimentação]
examples:
- Qual é meu saldo?
- Mostre minhas movimentações.
```
`priority` desempata intenções; menor valor tem precedência no template atual. `mcp_tools` restringe capacidades candidatas, mas não autoriza efeito sensível. `confidence_threshold` define quando aceitar o resultado semântico. `allow_handoff` permite troca explícita de agente. `domain` é metadado de escopo e não substitui `agent`.
O prompt semântico deve conter `allowed_values` e instruir o modelo a não executar ações nem inventar fatos. `include_relevant_context` inclui somente contexto limitado relacionado à pausa. Se a saída não corresponder a uma opção permitida, mantenha a transação pendente.
### Identidade antes da extração
`identity.yaml` resolve chaves canônicas (`customer_key`, `contract_key`, `interaction_key`, `account_key`, `resource_key`, `session_key`) a partir do payload, do `business_context` ou do contexto anterior. A validação de `required` deve ocorrer antes de chamar MCP. Nunca use `session_id` como identidade de cliente.
### Mapeamento e extração
```yaml parameter-mapping-example
mcp_parameter_mapping:
defaults:
use_mock: false
tools:
consultar_movimentacoes:
map:
customer_key: customer_id
account_key: account_id
session_key: session_id
defaults:
limit: 20
extract:
month:
from: message
type: int
strategy: month_name_pt
description: Converta o mês mencionado em número de 1 a 12.
transaction_id:
from: message
type: string
strategy: hybrid
pattern: '(?i)\\b(?:transação|transaction)\\s*[:#-]?\\s*([A-Z0-9-]+)\\b'
group: 1
description: Extraia somente um identificador explicitamente informado.
```
Precedência recomendada para argumentos: valor já confirmado na transação, argumento explícito atual, identidade canônica mapeada, extração determinística, extração LLM/híbrida e default. Um valor novo explícito pode corrigir o anterior; um valor inferido nunca deve sobrescrever um valor confirmado.
`strategy: hybrid` tenta a parte determinística e usa LLM quando necessário. `pattern` e `group` devem ser testados com casos positivos e negativos. `description` é instrução operacional do extrator, não documentação decorativa. `type` deve falhar de forma controlada se a conversão não for segura.
### Reconciliação temporal
A reconciliação temporal é fallback da coleta tradicional. Quando ainda faltarem campos, percorra mensagens relevantes da mais recente para a mais antiga e associe valores somente aos campos descritos no `args_schema`/mapeamento. Ela não deve:
- reabrir transação encerrada;
- misturar agentes, tenants ou sessões;
- recuperar valor invalidado pelo usuário;
- trocar correspondência exata por aproximação perigosa;
- substituir parâmetro já confirmado.
Registre a origem (`current_message`, `business_context`, `history`, `default`), a mensagem correlacionada e a confiança, sem persistir conteúdo sensível desnecessário.
### Estados dinâmicos
Para um agente novo, declare os estados de coleta e confirmação em `AgentState` somente quando eles carregarem campos adicionais; caso contrário, use as chaves transacionais genéricas. Registre ambos em `state_policies`, implemente a limpeza em sucesso/cancelamento/intent shift e inclua os estados nos testes de roteamento. Estado novo sem política correspondente costuma causar perda de stickiness.
### Router versus supervisor
No modo `router`, uma decisão escolhe um agente. No modo `supervisor`, o supervisor pode coordenar vários agentes e consolidar resultados. Não habilite supervisor apenas para melhorar classificação: ele muda custo, latência, estado e observabilidade. Um subagente deve receber contexto mínimo, ferramentas autorizadas e namespace `tenant_id:agent_id:session_id`; nunca compartilhe memória bruta entre agentes.
### Testes obrigatórios
Teste sobreposição de keywords, empate de prioridade, abaixo do threshold, agente fallback, estado pendente, confirmação curta, resposta ambígua, correção de parâmetro, extração regex/LLM, histórico temporal e isolamento entre agentes. Os YAMLs deste capítulo são analisados por `tests/test_advanced_developer_documentation.py`.

View File

@@ -0,0 +1,87 @@
### Apresentação, recuperação e observabilidade
### Renderers de resposta
Quando uma tool retorna dados estruturados confiáveis, `response.mode: renderer` produz uma resposta determinística e evita que o LLM altere valores, protocolos ou status.
```yaml
tools:
consultar_saldo:
description: Consulta saldo da conta.
mcp_server: financial
enabled: true
response:
mode: renderer
renderer: financial.balance
```
```python renderer-example
from typing import Any
from agent_framework.presentation import register_tool_response_renderer
def render_balance(*, tool_name: str, result: dict[str, Any],
state: dict[str, Any], agent_label: str) -> str | None:
account = result.get("account_masked")
balance = result.get("balance")
currency = result.get("currency", "BRL")
if account is None or balance is None:
return None
return f"[{agent_label}] Conta {account}: saldo {currency} {float(balance):.2f}."
def register_financial_renderers() -> None:
register_tool_response_renderer("financial.balance", render_balance)
```
Importe e execute `register_financial_renderers()` uma vez no startup. A assinatura é keyword-only e deve aceitar `tool_name`, `result`, `state` e `agent_label`. Retorne `None` quando faltarem campos obrigatórios para permitir o fallback previsto pelo runtime. Nunca interpolar o payload inteiro: selecione campos permitidos, mascare identidade e formate valores explicitamente.
### Output Supervisor
O Output Supervisor valida a resposta candidata antes da saída final. Ele pode permitir, sanitizar, solicitar retry, bloquear, entregar a humano ou observar. `OUTPUT_SUPERVISOR_MAX_RETRIES` deve ter limite pequeno; cada retry precisa de orientação objetiva e a resposta reescrita deve passar novamente pelos controles. Não use retry para erro permanente de autorização ou indisponibilidade.
### Recuperação de workflow
Classifique falhas em: validação, dependência temporária, dependência permanente, persistência e erro de programação. O usuário recebe mensagem segura; a telemetria recebe classe, fase, tentativa, workflow/version/execution ID e correlação. Para efeitos externos:
- antes do envio, um retry controlado é aceitável;
- depois de envio com resultado incerto, consulte status/idempotência;
- após confirmação externa, persista o resultado antes de responder;
- uma nova mensagem do usuário não deve apagar evidência de uma execução incerta.
Checkpoints resilientes podem repetir operações de armazenamento, validar integridade, compactar histórico e recuperar o último checkpoint válido. Isso não torna automaticamente uma action externa idempotente.
### Interrupção de voz e replay
No barge-in, preserve o texto confirmado, marque a resposta interrompida e não reapresente áudio obsoleto. O replay deve usar identificadores de interação/mensagem e a mesma sessão escopada. Se uma transação estava pendente, a fala interrompida não conta como confirmação. Ao retomar, revalide estado, confirmação e idempotência.
### Eventos IC, NOC e GRL
- IC: comportamento funcional, decisão, tool, cache e workflow;
- NOC: disponibilidade, timeout, dependência e latência operacional;
- GRL: decisão e ação de guardrail/supervisor.
Use o `AgentObserver`/adapter do template em vez de chamar diretamente um backend de telemetria. Inclua `tenant_id`, `agent_id`, `session_id`, `transaction_id`/`execution_id`, componente e duração quando disponíveis. Nunca inclua credenciais, prompt integral, PII ou payload financeiro bruto.
### Mapeamento e compatibilidade
Quando consumidores históricos exigirem códigos diferentes, use um registry/overlay como `observability_mapping.yaml`: evento semântico interno → label externo. O default é compartilhado e o overlay pertence ao agente. Não hardcode labels históricas no executor nem renomeie o evento interno de forma que perca semântica.
### Pub/Sub e sequência
Publicação deve ocorrer após a decisão funcional e não pode alterar seu resultado. Configure provider, tópicos/streams, filtros e política de falha. Quando o consumidor exigir ordem, publique `sequence`, chave de partição estável e correlação; múltiplos pods não garantem ordem global. Defina TTL/retenção e comportamento para duplicatas. Eventos filtrados no Pub/Sub continuam disponíveis nos outros destinos de observabilidade.
### Checklist operacional
- renderer não expõe payload bruto;
- resposta sanitizada é revalidada;
- retries têm limite e distinguem erro transitório;
- efeitos incertos consultam idempotência/status;
- evento contém correlação e não contém segredo;
- labels externas são mapeadas por configuração;
- sequência e chave de partição são testadas com múltiplos consumidores;
- interrupção de voz não confirma nem repete transação.
O exemplo de renderer é compilado e executado por `tests/test_advanced_developer_documentation.py`.

View File

@@ -0,0 +1,93 @@
### Multiagente, composição e ciclo de vida
### O que constitui um agente isolado
Um `agent_id` não é apenas um label. O isolamento real precisa abranger prompt, routing, tools, MCP servers, guardrails, judges, memória, checkpoints, cache, telemetria e identidade. A chave operacional recomendada é `tenant_id:agent_id:session_id`.
```yaml agents-registry-example
default_agent_id: financial
agents:
- agent_id: financial
name: Agente Financeiro
description: Consultas e operações financeiras.
prompt_policy_path: ./config/agents/financial/prompt_policy.yaml
routing_config_path: ./config/agents/financial/routing.yaml
guardrails_config_path: ./config/agents/financial/guardrails.yaml
judges_config_path: ./config/agents/financial/judges.yaml
mcp_servers_config_path: ./config/agents/financial/mcp_servers.yaml
tools_config_path: ./config/agents/financial/tools.yaml
metadata:
domain: financial
system_prefix: |
Execute somente políticas e recursos do agent_id financial.
```
Todos os caminhos devem existir e ser validados no startup. O prefixo ajuda o LLM, mas não é barreira de segurança. Autorização de tools, namespaces de persistência e seleção de pipelines devem ser impostas pelo código.
### Limitação real do template atual
O registry aceita esses caminhos, mas o `AgentWorkflow` corrente ainda constrói um único router, um único conjunto de tools/RAG e um par global de guardrails/judges. Portanto, copiar o YAML acima não cria isolamento completo por requisição. Até existir uma factory/cache por perfil, use uma configuração global por deployment ou implemente a seleção explícita antes de invocar o grafo.
Uma composição correta mantém, por `agent_id`, os objetos imutáveis/caros em cache e injeta dependências na execução:
```python agent-runtime-bundle-example
from dataclasses import dataclass
from typing import Any
@dataclass(frozen=True)
class AgentRuntimeBundle:
router: Any
tool_router: Any
rag_service: Any
guardrails: Any
judges: Any
def select_bundle(registry: dict[str, AgentRuntimeBundle], agent_id: str) -> AgentRuntimeBundle:
if agent_id not in registry:
raise KeyError(f"agent_id não registrado: {agent_id}")
return registry[agent_id]
```
Não construa LLM, conexão, router ou pipeline a cada mensagem. Não use fallback silencioso para o bundle de outro agente; falhe de forma explícita ou use somente o `default_agent_id` autorizado na borda.
### Subagentes e supervisor
Subagente é uma capacidade delimitada, não apenas uma função Python. Declare objetivo, entradas, saídas, tools autorizadas, orçamento/timeout e condições de retorno. O supervisor recebe resultados estruturados e consolida; ele não deve compartilhar todo o histórico por padrão. Uma delegação deve carregar correlação e profundidade máxima para evitar ciclos.
Use router quando uma única especialidade resolve o turno. Use supervisor quando a tarefa realmente exigir decomposição ou combinação de duas ou mais capacidades. Para handoff, transfira propriedade da conversa; para subagente, mantenha o supervisor como proprietário da resposta final.
### Composição de LLM por domínio
Use `llm_profiles.yaml` e o cliente criado pelo framework. Componentes recebem `profile_name` ou o LLM compartilhado; não criam SDK/provedor com credenciais próprias. Isso preserva autenticação, rate limits, retries, cache e telemetria. Fallback entre profiles precisa ser explícito e observável; nunca converta falha de configuração em resposta aparentemente válida.
### RAG e memória por agente
`RAG_PROVIDER=kbdb` seleciona KBDB apenas quando o `RagService` daquela execução usa as settings corretas. A intenção simples também deve acionar RAG quando a política do agente exigir conhecimento. Separe coleção/namespace por tenant e agente. Memória de longo prazo guarda fatos permitidos e resumidos; checkpoint guarda execução. Nenhum dos dois deve misturar identidade de outro agente.
### Autenticação e autorização
Autenticação prova o principal; autorização decide agente, tenant, rota e tool. Basic, API key, bearer, JWT, introspection e trusted proxy são providers possíveis, mas produção deve usar segredo com hash/rotação e TLS. Headers de trusted proxy só são confiáveis quando a borda autenticada remove valores enviados pelo cliente.
### Inicialização e readiness
No startup: validar registry e caminhos; criar providers; registrar actions/renderers; carregar workflows; construir bundles; verificar conexões essenciais. `/ready` deve falhar quando uma dependência obrigatória não estiver utilizável; `/health` indica processo vivo. Configuração inválida deve falhar cedo, antes da primeira conversa.
### Ciclo de desenvolvimento e certificação
1. Copiar o template canônico sem copiar `.venv` ou caches.
2. Criar agente, estado somente se necessário, configurações e recursos de domínio.
3. Registrar nó/rota e decidir router ou supervisor.
4. Implementar tools, mappings, políticas, actions e renderers.
5. Configurar guardrails, judges, RAG, memória e observabilidade.
6. Testar unidade, loader/config, grafo, regressão conversacional e falhas.
7. Executar avaliação offline, carga e readiness.
8. Publicar com versão, compatibilidade e rollback documentados.
### Definition of done
Um agente não está pronto apenas porque responde ao happy path. Ele precisa provar isolamento, confirmação antes de efeito, idempotência, recuperação, grounding, bloqueio/sanitização, telemetria correlacionada, ausência de vazamento, comportamento sob dependência indisponível e compatibilidade PT/EN dos manuais.
Os contratos deste capítulo são validados por `tests/test_advanced_developer_documentation.py`.

View File

@@ -126,11 +126,35 @@ Se algo não está funcionando, use **Buscar pelo problema** abaixo.
**Use quando:** mensagens de bloqueio são genéricas, `COER` deveria pedir esclarecimento ou o metadata de um turno bloqueado contém routing/tools antigos.
### [13 — Workflows Transacionais Avançados](./13_workflows_transacionais_avancados.md)
**O que é:** implementação de pré-validação, workflow versionado, actions, pausa/retomada, idempotência, replay e recuperação.
**Use quando:** uma tool sensível precisa executar um processo determinístico e recuperável.
### [14 — Routing, Parâmetros e Estado Avançados](./14_routing_parametros_e_estado_avancados.md)
**O que é:** precedência do router, confirmação semântica, extração híbrida, reconciliação temporal, estados dinâmicos e subagentes.
**Use quando:** routing, coleta ou retomada funcionam no happy path, mas falham em conversas reais.
### [15 — Apresentação, Recuperação e Observabilidade](./15_apresentacao_recuperacao_e_observabilidade.md)
**O que é:** renderers, Output Supervisor, recuperação, voice replay, eventos, mappings e Pub/Sub ordenado.
**Use quando:** a resposta altera evidências, um efeito pode repetir ou a telemetria não permite reconstruir o fluxo.
### [16 — Multiagente, Composição e Ciclo de Vida](./16_multiagente_composicao_e_ciclo_de_vida.md)
**O que é:** isolamento efetivo, bundles por agente, supervisor/subagentes, LLM/RAG/memória e readiness.
**Use quando:** vários agentes compartilham o deployment ou uma nova capacidade precisa chegar à produção.
### Tutorial principal
[`README.md`](../../../README.md) continua sendo a referência para o passo a passo completo:
`arquitetura → configuração → criação do agente → registro → estado → routing → tools → MCP → identidade → execução → testes → gateways → memória → RAG`.
`arquitetura → configuração → criação do agente → registro → estado → routing → tools → MCP → identidade → workflows → idempotência → execução → testes → gateways → memória → RAG → operação`.
### Manutenção