mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-11-05 19:04:13 +00:00
adjustments: manual v2
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
152
docs/developer/pt/13_workflows_transacionais_avancados.md
Normal file
152
docs/developer/pt/13_workflows_transacionais_avancados.md
Normal 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`.
|
||||
122
docs/developer/pt/14_routing_parametros_e_estado_avancados.md
Normal file
122
docs/developer/pt/14_routing_parametros_e_estado_avancados.md
Normal 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`.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user