From edf46f9429678f8db0f409e383e8267d45a76fd1 Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Wed, 16 Sep 2026 08:57:20 -0300 Subject: [PATCH] manual agent_template_backend --- MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md | 1887 +++++++++++++++++++++ MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md | 1884 ++++++++++++++++++++ README.md | 2 +- README_en.md | 2 +- 4 files changed, 3773 insertions(+), 2 deletions(-) create mode 100644 MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md create mode 100644 MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md diff --git a/MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md b/MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md new file mode 100644 index 00000000..9baebc48 --- /dev/null +++ b/MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md @@ -0,0 +1,1887 @@ +# Manual Detalhado de Regras do `agent_template_backend` + + +## Prefácio técnico — como funciona o motor de decisão do `agent_template_backend` + +O `agent_template_backend` é um **template corporativo de referência** para construir agentes sobre o Agent Framework OCI. Ele não concentra decisão em um único `if`, prompt ou router. O comportamento final resulta da cooperação entre configuração declarativa, estado LangGraph, runtime transacional, MCP Tool Router, RAG, memória, guardrails, judges, Output Supervisor, workflows e persistência. + +Uma mensagem pode: + +- ser sanitizada/bloqueada antes do roteamento; +- pertencer a uma transação já aberta; +- preencher um parâmetro pendente; +- confirmar/rejeitar uma action; +- interromper a operação anterior por intent shift; +- continuar com o agente atual por route stickiness; +- conter várias intents independentes; +- retomar um workflow pausado; +- selecionar uma ou várias tools candidatas; +- passar por pre-validation; +- trocar de trajetória de execução por policy; +- executar tool diretamente ou workflow determinístico; +- usar MCP como evidência operacional; +- usar RAG como conhecimento documental; +- usar memória resumida/long-term memory como contexto; +- ser revisada por Output Supervisor, guardrails e judges; +- persistir estado/evidência para o turno seguinte. + +A pergunta correta ao diagnosticar o template não é apenas “qual intent foi encontrada?”, mas: + +> **Em qual estado a sessão estava, qual mecanismo tinha precedência, qual intent/route venceu, qual tool foi selecionada, quais parâmetros foram resolvidos, qual policy/pre-validation se aplicou, qual execução ocorreu e quais evidências sustentaram a resposta final?** + +## P.1. Visão geral do motor + +```mermaid +flowchart TD + U["Mensagem / GatewayRequest"] --> IGR["Input Guardrails"] + IGR --> LTM["Load Long-Term Memory"] + LTM --> RT["EnterpriseRouter / Supervisor"] + RT --> CP["Conversation policy / state precedence"] + CP --> AG["Agente de domínio"] + AG --> TP["Tool policy + parâmetros"] + TP --> PV["Pre-validation se configurada"] + PV --> CF["Confirmação se transacional"] + CF --> EX["MCP direto ou Workflow"] + EX --> RAG["RAG se necessário"] + RAG --> CMP["Composição da resposta"] + CMP --> OS["Output Supervisor"] + OS --> OGR["Output Guardrails"] + OGR --> J["Judges"] + J --> SR["Supervisor Review"] + SR --> MEM["Persistência / memória / checkpoint"] + MEM --> F["Resposta"] +``` + +Nem todo turno atravessa todas as camadas. Uma consulta de rastreamento pode terminar rapidamente em MCP + renderer; uma devolução exige coleta, confirmação e workflow. + +## P.2. Grafo corporativo real do template + +`app/workflows/agent_graph.py` monta um `FrameworkStateGraph(AgentState)` com os principais nós: + +```text +START + ↓ +input_guardrails + ↓ +load_long_term_memory + ↓ +routing_decision + ↓ +billing_agent | product_agent | orders_agent | support_agent + | handoff | human_handoff | end_session | supervisor_agent + ↓ +output_supervisor + ↓ +output_guardrails + ↓ +judge + ↓ +supervisor_review + ↓ +persist_long_term_memory + ↓ +persist + ↓ +END +``` + +O grafo é a espinha dorsal; as regras de domínio ficam em YAML/agentes/MCP/workflows. + +## P.3. Três famílias de estado + +### P.3.1. Estados declarados em `routing.yaml` + +O template declara: + +| Estado | Agente proprietário | +|---|---| +| `WAITING_BILLING_CONFIRMATION` | `billing_agent` | +| `WAITING_PRODUCT_CONFIRMATION` | `product_agent` | +| `WAITING_ORDER_CONFIRMATION` | `orders_agent` | +| `WAITING_SUPPORT_CONFIRMATION` | `support_agent` | +| `COLLECTING_BILLING_PARAMETERS` | `billing_agent` | +| `COLLECTING_PRODUCT_PARAMETERS` | `product_agent` | +| `COLLECTING_ORDER_PARAMETERS` | `orders_agent` | +| `COLLECTING_SUPPORT_PARAMETERS` | `support_agent` | + +Eles mantêm o próximo turno no agente proprietário durante coleta/confirmação. + +### P.3.2. Estados transacionais canônicos do runtime + +O runtime utiliza estados como: + +```text +COLLECTING_PARAMETERS +AWAITING_CONFIRMATION +CONFIRMED +EXECUTING +WORKFLOW_PAUSED +TOOL_RESULT_CLARIFICATION +COMPLETED +FAILED +CANCELLED +BLOCKED +OUT_OF_SCOPE +``` + +Esses estados controlam parâmetros, confirmação, execução e encerramento da transação. + +### P.3.3. Estados do engine de workflow + +Um workflow possui execução independente identificada por `execution_id`, com resultados como: + +```text +PAUSED / WAITING_INPUT +COMPLETED +FAILED +``` + +Os três grupos se relacionam, mas não devem ser tratados como uma única enumeração. + +## P.4. Máquina transacional conceitual + +```mermaid +stateDiagram-v2 + [*] --> COLLECTING_PARAMETERS: required fields faltantes + COLLECTING_PARAMETERS --> AWAITING_CONFIRMATION: parâmetros completos + validações OK + COLLECTING_PARAMETERS --> CANCELLED: intent shift / abandono + + AWAITING_CONFIRMATION --> EXECUTING: confirmação positiva + AWAITING_CONFIRMATION --> CANCELLED: confirmação negativa + AWAITING_CONFIRMATION --> AWAITING_CONFIRMATION: resposta inconclusiva + + EXECUTING --> COMPLETED: tool/workflow concluído + EXECUTING --> WORKFLOW_PAUSED: workflow pede nova entrada + EXECUTING --> FAILED: erro técnico + EXECUTING --> BLOCKED: política/guardrail + EXECUTING --> OUT_OF_SCOPE: regra de domínio rejeita + + WORKFLOW_PAUSED --> EXECUTING: resume válido + WORKFLOW_PAUSED --> COMPLETED: workflow termina +``` + +## P.5. Routing + +`config/routing.yaml` é a fonte declarativa para intents, prioridades, agentes, tools, keywords e exemplos. + +A ordem principal do `EnterpriseRouter` é: + +```text +estado/transação ativa +→ matching determinístico +→ LLM router quando habilitado +→ fallback +``` + +O matching determinístico privilegia a intenção com melhor combinação de prioridade/especificidade; **menor valor numérico de `priority` tem precedência**. + +Quando `ENABLE_LLM_ROUTER=true`, o LLM recebe o catálogo permitido e classifica dentro dele. O LLM não deve inventar novas tools/agentes. + +## P.6. Route stickiness + +`ENABLE_ROUTE_STICKINESS` ativa um classificador leve que decide continuidade semântica entre: + +```text +CONTINUE +ROUTE +HUMAN_HANDOFF +END_SESSION +``` + +Configuração relevante: + +```text +ROUTE_STICKINESS_LLM_PROFILE +ROUTE_STICKINESS_CONFIDENCE_THRESHOLD +ROUTE_STICKINESS_HISTORY_TURNS +ROUTE_STICKINESS_MAX_TOKENS +``` + +`CONTINUE` mantém o agente ativo; `ROUTE` volta ao EnterpriseRouter. Stickiness não autoriza transações e não substitui tool policy. + +## P.7. Intent shift + +Durante `COLLECTING_PARAMETERS` ou `AWAITING_CONFIRMATION`, o framework protege a transação atual contra mudanças acidentais. Entretanto, uma mudança explícita de assunto pode cancelar/limpar o latch transacional e devolver o turno ao routing normal. + +A fala atual também tem precedência para preencher campos pendentes. Uma resposta como `PED-1001` durante coleta de `order_id` não deve ser reinterpretada como uma nova intent. + +## P.8. Coleta de parâmetros + +A necessidade de parâmetros nasce da combinação: + +```text +tools.yaml args_schema ++ tool_policies.yaml requires ++ mcp_parameter_mapping.yaml ++ dados canônicos do state +``` + +Exemplo: + +```text +cancelar_pedido +requires: [order_id] +``` + +Sem `order_id`, o runtime entra em `COLLECTING_PARAMETERS`, usa `user_prompt`/schema para pedir o campo e preserva a propriedade do agente. + +## P.9. Reconciliação temporal + +O framework contém um reconciliador temporal em `runtime/transaction_parameters.py`. Ele é usado **depois** da tentativa tradicional do turno atual quando ainda restam campos necessários. + +Princípios: + +- a fala atual é a fonte mais nova e tem precedência; +- histórico serve para resolver referência, não para inventar fato operacional; +- campos podem ser preservados, resolvidos, limpos ou continuar não resolvidos; +- ambiguidade deve permanecer não resolvida; +- o resultado candidato ainda passa pelas validações/pre-validation de domínio. + +Isso permite relações coerentes entre turnos sem transformar histórico conversacional em evidência de backend. + +## P.10. Contextual reentry + +O `EnterpriseRouter` e o runtime suportam `contextual_reentry`: um turno curto pode reentrar em uma regra quando o contexto imediatamente anterior delimita o significado. + +O runtime mantém a fala atual separada de `relevant_conversation_context`; esse contexto é interpretativo e não substitui tool/MCP como autoridade operacional. + +## P.11. Multi-intent e `pending_topics` + +`MultiIntentPlanner` pode separar objetivos independentes: + +```text +"rastreia o pedido e depois cancela" +``` + +em tópicos distintos, sem desmontar parâmetros internos de uma única action. + +Quando uma ação precisa terminar antes da seguinte, o framework pode persistir as demais em `pending_topics`. `drain_pending_topics()` aparece diretamente no grafo do template. + +## P.12. Policies de tools + +`tools.yaml` descreve capabilities. `tool_policies.yaml` descreve **como** uma capability sensível pode executar. + +No template base: + +- `cancelar_pedido`: transactional + confirmation + `order_id` + pre-validation; +- `solicitar_troca`: transactional + confirmation; +- `solicitar_devolucao`: transactional + confirmation + `order_id/reason` + workflow. + +Esta separação evita colocar regra de execução sensível dentro do agente. + +## P.13. Pre-validation + +A pre-validation ocorre depois dos parâmetros obrigatórios e antes da confirmação. + +Fluxo: + +```text +parâmetros completos +→ validator MCP side-effect-free +→ eligible? + ├─ false: OUT_OF_SCOPE / termina latch + └─ true: AWAITING_CONFIRMATION +``` + +No template, `cancelar_pedido` usa `validar_cancelamento_pedido` com `fail_open=false`. + +## P.14. Confirmação transacional + +Tools com `require_confirmation=true` não executam automaticamente. + +O framework tenta interpretar confirmações explícitas deterministicamente e pode usar fallback semântico quando necessário. Uma resposta positiva promove a transação para execução; uma negativa cancela; uma resposta inconclusiva mantém a transação ativa. + +## P.15. Workflow transacional + +A policy pode definir: + +```yaml +execution: + mode: workflow + workflow: devolucao_pedido + version: active +``` + +Assim, após confirmação, a tool lógica é executada pelo `WorkflowToolExecutor`, que carrega o YAML versionado e executa o grafo determinístico. O domínio declara nós/actions; o framework cuida de runtime, checkpoint e trace. + +## P.16. Pause/Resume + +O engine de workflow suporta nós que pausam, `expected_input`, `resume_from` e retomada por `execution_id`. O workflow base de devolução não pausa; a capability é demonstrada isoladamente em `Tuning-Performance/Pause_Resume_Workflow`. + +Uma regra importante: o pause é compilado de modo a não reexecutar automaticamente a action com efeito colateral quando o usuário responde. + +## P.17. Guardrails + +No template global: + +**Input** +- `MSK` +- `VLOOP` + +**Output** +- `REVPREC` +- `PINJ` +- `DLEX_OUT` + +Os pipelines podem ser habilitados/desabilitados por `.env`. Guardrails avaliam permissão/segurança/coerência operacional; não devem substituir routing ou regra de domínio. + +## P.18. Output Supervisor + +O Output Supervisor fica entre agente e output guardrails. Ele pode revisar a resposta candidata, aplicar política de retry/sanitize/block/handover e impedir que uma resposta prematura afirme um efeito que não está sustentado por resultado operacional. + +`OUTPUT_SUPERVISOR_MAX_RETRIES` controla o limite de regenerações. + +## P.19. Judges + +`config/judges.yaml` habilita: + +| Judge | Threshold/política | +|---|---| +| `response_quality` | `0.7` | +| `groundedness` | `0.6` | +| `sentiment` | não falha por negativo | +| `tone` | `fail_closed=true` | + +Configuração global: + +```text +enabled=true +fail_closed=true +sample_rate=0.25 +always_run_for_transactional=true +``` + +Portanto, respostas transacionais são avaliadas mesmo quando a amostragem geral seria menor. + +## P.20. MCP, evidência operacional e renderers + +O template separa três responsabilidades: + +```text +routing → quais capabilities pertencem à intent +tool runtime → qual capability realmente deve executar +MCP server → fato operacional / integração +``` + +Algumas tools possuem `response.mode: renderer`, por exemplo `telecom.invoice`, `telecom.plan`, `retail.order` e `retail.delivery`. Nesses casos o resultado MCP pode ser apresentado de forma determinística sem obrigar uma composição LLM. + +## P.21. RAG + +`AgentRuntimeMixin._retrieve_rag_context()` usa o RAG oficial do framework. RAG serve para conhecimento documental; MCP serve para estado operacional. + +O runtime também suporta **Domain-Requested RAG**: uma tool pode retornar `requires_rag=true` e `rag_queries`, forçando recuperação mesmo quando normalmente o MCP seria considerado suficiente. + +## P.22. Composição LLM solicitada pelo domínio + +Uma tool/workflow pode retornar: + +```json +{ + "requires_llm_composition": true, + "response_instruction": "..." +} +``` + +O domínio não cria seu próprio gateway LLM. O AgentRuntime usa o provider oficial, preservando tracing, custos, profiles e guardrails. + +## P.23. Memória + +O template possui: + +- ConversationSummaryMemory; +- memória recente; +- Long-Term Memory opcional; +- checkpoint/persistência operacional. + +Memória ajuda a interpretar contexto, preferências e continuidade. **Não substitui Transaction Evidence nem MCP** para afirmar que uma operação ocorreu. + +## P.24. Transaction Evidence + +Resultados de transações concluídas podem ser persistidos como evidência operacional estruturada e correlacionados em turnos futuros. Isso evita que uma resposta mencione um protocolo/cancelamento anterior sem fornecer a mesma evidência aos judges/groundedness. + +## P.25. Idempotência + +Estado transacional, checkpoint e `execution_id` existem também para proteger contra retry/replay/reexecução. Uma confirmação repetida não deve criar duas transações somente porque o canal reenviou uma mensagem. + +## P.26. Interrupção de voz e replay + +O framework possui short-circuit de canal para idle nudge, fala não interrompível, pós-finalização e barge-in. Em vários casos ele simplesmente faz replay da última fala sem reabrir LangGraph, tools ou guardrails; quando necessário usa o profile `processing_interruption_classifier`. + +## P.27. Erro e recuperação de workflow + +`WorkflowRuntime` preserva o último snapshot válido e expõe `error`, trace parcial e `error_details` quando o provider disponibiliza `status_code`, `body` e `attempts`. O domínio pode distinguir falha técnica de regra de negócio sem acoplar o framework ao provider. + +## P.28. Observabilidade + +O template emite telemetria para: + +- Langfuse; +- OpenTelemetry; +- analytics/observer corporativo; +- eventos IC; +- NOC; +- GRL; +- workflow; +- guardrails; +- judges. + +A telemetria deve permitir reconstruir o caminho: + +```text +input → route → agent → tool → policy → workflow → output controls → persistence +``` + +## P.29. `agents.yaml`: isolamento lógico de aplicações/agentes + +`config/agents.yaml` registra dois `agent_id` de referência: + +- `telecom_contas`; +- `retail_orders`. + +Cada um pode apontar para prompt policy, routing, guardrails, judges, MCP servers e tools, além de `metadata.system_prefix`. O objetivo é evitar mistura de políticas/memória/checkpoints entre identidades lógicas diferentes. + +## P.30. Regra de ouro de troubleshooting + +Sempre investigue nesta ordem: + +```text +1. Qual agent_id está ativo? +2. Qual era o estado/checkpoint? +3. Havia transação ou workflow pausado? +4. Qual decisão de route/stickiness ocorreu? +5. Qual intent venceu e por quê? +6. Quais mcp_tools a intent autorizou? +7. Qual tool foi selecionada? +8. Quais parâmetros foram resolvidos? +9. Houve reconciliação temporal? +10. Houve pre-validation? +11. Houve confirmação? +12. Tool direta ou workflow? +13. Qual resultado MCP/workflow foi produzido? +14. A resposta usou renderer, RAG ou LLM? +15. Output Supervisor/guardrails alteraram algo? +16. Judges aprovaram? +17. O estado/evidência foi persistido? +``` + +Esse é o motor sobre o qual as cinco regras do template são construídas. + +## 1. Como ler este manual + +O manual usa o mesmo modelo do manual do Agente de Contas. Cada regra é explicada em seis níveis: + +1. **Regra/intenção** — o que significa e qual o limite. +2. **Routing** — `routing.yaml` atributo por atributo e como a intent é descoberta. +3. **Tools** — operação, argumentos, aliases, extração, policy, confirmação, pre-validation e retorno. +4. **Workflow** — quando existe, nós, actions, condições e término. +5. **Amarração** — arquivos Python/YAML/`.env` envolvidos. +6. **Diagnóstico** — por que uma decisão específica ocorre. + +Depois das regras há uma parte separada dedicada ao `Tuning-Performance`. + +## 2. Catálogo de agentes e isolamento por `agent_id` + +| agent_id | Nome | Domínio | Configurações específicas | +|---|---|---|---| +| `telecom_contas` | Agente Telecom Contas | `telecom` | prompt `./config/agents/telecom_contas/prompt_policy.yaml`; guardrails `./config/agents/telecom_contas/guardrails.yaml`; judges `./config/agents/telecom_contas/judges.yaml` | +| `retail_orders` | Agente Retail Pedidos | `retail` | prompt `./config/agents/retail_orders/prompt_policy.yaml`; guardrails `./config/agents/retail_orders/guardrails.yaml`; judges `./config/agents/retail_orders/judges.yaml` | + +O `default_agent_id` é `telecom_contas`. O `system_prefix` de cada registro orienta o runtime a não misturar políticas, memória/checkpoints ou decisões de outro `agent_id`. + +## 3. Amarração entre componentes + + +```mermaid +flowchart LR + U["GatewayRequest / mensagem"] --> G["app/main.py"] + G --> WF["app/workflows/agent_graph.py"] + WF --> R["config/routing.yaml"] + R --> A["app/agents/*_agent.py"] + A --> RT["AgentRuntimeMixin"] + RT --> T["config/tools.yaml"] + T --> P["config/tool_policies.yaml"] + T --> M["config/mcp_parameter_mapping.yaml"] + P --> MCP["MCP Tool Router / Gateway"] + M --> MCP + MCP --> S["mcp/servers/telecom ou retail"] + P --> DW["workflows/*.yaml quando execution=workflow"] + DW --> WA["app/workflow_actions/*.py"] + A --> RAG["RAG / memória / LLM"] + A --> OS["Output Supervisor"] + OS --> GR["Guardrails"] + GR --> J["Judges"] + J --> PS["Persistência / checkpoint / evidence"] +``` + +## 4. Inventário das regras + +| Intent | Regra | Agente | Prioridade | Tools | +|---|---|---|---:|---| +| `billing_invoice_explanation` | Faturamento / Explicação de Fatura | `billing_agent` | 10 | `consultar_fatura`, `consultar_pagamentos` | +| `product_services_information` | Produtos, Plano, Serviços e VAS | `product_agent` | 20 | `consultar_plano`, `listar_servicos` | +| `retail_order_cancel` | Cancelamento de Pedido | `orders_agent` | 20 | `consultar_pedido`, `cancelar_pedido` | +| `retail_order_tracking` | Consulta e Rastreamento de Pedido | `orders_agent` | 30 | `consultar_pedido`, `consultar_entrega` | +| `retail_support_exchange_return` | Troca, Devolução, Garantia e Suporte Retail | `support_agent` | 25 | `consultar_pedido`, `solicitar_troca`, `solicitar_devolucao` | + +# 5. Regra — Faturamento / Explicação de Fatura + +**Intent:** `billing_invoice_explanation` +**Domain:** `telecom` +**Agent:** `billing_agent` +**Priority:** `10` + +## O que esta regra significa + +Dúvidas sobre fatura, cobrança, vencimento, segunda via, contestação e valores. + +### Limite da regra + +É uma regra informativa/operacional de billing. Ela consulta evidência; não autoriza por si só uma ação financeira transacional. + +## `routing.yaml` atributo por atributo + +| Atributo | Valor nesta regra | Papel no motor | +|---|---|---| +| `name` | billing_invoice_explanation | Nome estável da intent. É o identificador que aparece em state/telemetria e liga a decisão às capabilities declaradas. | +| `domain` | telecom | Domínio lógico. Ajuda a limitar contexto, agentes e interpretação do catálogo. | +| `agent` | billing_agent | Agente que recebe o turno quando esta intent vence. | +| `description` | Dúvidas sobre fatura, cobrança, vencimento, segunda via, contestação e valores. | Descrição semântica usada por manutenção humana e pelo fallback LLM. | +| `priority` | 10 | Desempate entre intents concorrentes. No EnterpriseRouter, valores menores têm precedência. | +| `mcp_tools` | consultar_fatura
consultar_pagamentos | Lista de capabilities inicialmente autorizadas/esperadas para a intent. | +| `keywords` | fatura
conta
cobrança
boleto
vencimento
segunda via
contestar
valor alto
invoice | Gatilhos determinísticos usados antes do fallback semântico. | +| `examples` | Minha fatura veio alta.
Quero entender uma cobrança.
Preciso da segunda via da conta. | Exemplos oferecidos ao classificador LLM; não são regex nem regras executáveis. | + +## Como esta intent é encontrada + +1. O EnterpriseRouter verifica estado/transação ativa antes de tratar a frase como nova solicitação. +2. No matching determinístico, esta intent oferece keywords como `fatura`, `conta`, `cobrança`, `boleto`, `vencimento`, `segunda via`, `contestar`, `valor alto`, `invoice`. +3. Em colisões, `priority=10` participa do desempate; menor número tem precedência. +4. Se o fallback LLM for usado, a descrição e exemplos como `Minha fatura veio alta.`, `Quero entender uma cobrança.`, `Preciso da segunda via da conta.` ajudam a classificação. +5. Quando a intent vence, o state recebe route/agente e o conjunto inicial de tools `['consultar_fatura', 'consultar_pagamentos']`. + +## Agente proprietário e comportamento Python + +Arquivo: `app/agents/billing_agent.py`. +O `run()` segue um padrão comum: emite IC de início, coleta contexto MCP, verifica mensagens de clarificação/confirmação transacional, tenta resposta direta por MCP/renderer, consulta RAG quando necessário, prepara memória, monta `messages`, chama o LLM e devolve patch de estado. +Esse padrão vem de `app/agents/runtime.py::AgentRuntimeMixin`, evitando que cada agente reimplemente MCP, RAG, cache, memória, IC e lógica transacional. + +## Tools desta regra + +### Tool `consultar_fatura` + +**O que faz:** Consulta dados resumidos de fatura por msisdn/invoice_id. + +| Propriedade | Valor | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `fatura`, `conta`, `boleto` | +| apresentação | `mode=renderer`; renderer `telecom.invoice` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `msisdn` | `string` | contexto canônico `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | +| `invoice_id` | `string` | contexto canônico `contract_key` | Identificador da fatura que o cliente deseja consultar. | + +**Aliases MCP:** `customer_key → msisdn`, `contract_key → invoice_id`, `interaction_key → ura_call_id`, `session_key → session_id`. + +**Extração conversacional:** +- `mes_referencia`: strategy `month_name_pt`; Extrair mês citado na mensagem. janeiro=1, fevereiro=2, março=3, abril=4, maio=5, junho=6, julho=7, agosto=8, setembro=9, outubro=10, novembro=11, dezembro=12. + + +**O que retorna:** No MCP de exemplo retorna `invoice_id`, `msisdn`, `valor_total`, `vencimento`, `status` e uma lista `itens`; o envelope final é `{ok, result, metadata}`. + +### Tool `consultar_pagamentos` + +**O que faz:** Consulta histórico de pagamentos do cliente. + +| Propriedade | Valor | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `pagamento`, `pagamentos` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `msisdn` | `string` | contexto canônico `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | + +**Aliases MCP:** `customer_key → msisdn`, `interaction_key → ura_call_id`, `session_key → session_id`. + +**O que retorna:** Retorna `msisdn` e `pagamentos[]`, com data, valor e status dos pagamentos do mock. + +## Workflow + +Esta regra não possui workflow declarativo obrigatório no template base. A execução ocorre via MCP/runtime padrão; estados transacionais ainda podem existir para coleta/confirmar actions. + +## Amarração entre YAML e Python + +- `config/routing.yaml` → encontra `billing_invoice_explanation` e escolhe `billing_agent`. +- `config/tools.yaml` → descreve argumentos, servidor MCP, keywords de seleção e renderer. +- `config/tool_policies.yaml` → define read-only/transactional, confirmation, pre-validation e/ou workflow. +- `config/mcp_parameter_mapping.yaml` → traduz chaves canônicas e extrai campos da mensagem. +- `app/agents/billing_agent.py` → usa `AgentRuntimeMixin` para executar capabilities sem duplicar infraestrutura. +- `app/workflows/agent_graph.py` → conecta o agente ao fluxo corporativo e aos controles de saída. +- `mcp/servers/telecom_mcp_server/main.py` → implementação mock/contrato da tool `consultar_fatura`. +- `mcp/servers/telecom_mcp_server/main.py` → implementação mock/contrato da tool `consultar_pagamentos`. + +### `.env` e configuração relevante + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` e `ENABLE_LLM_ROUTER` controlam o catálogo/semântica de roteamento. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE` e `END_SESSION_MESSAGE` controlam continuidade/sessão. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH` e `MCP_TOOL_TIMEOUT_SECONDS` controlam tools. +- `MCP_GATEWAY_ENABLED` decide entre chamada via MCP Gateway dedicado e acesso direto aos MCP servers configurados. +- O servidor lógico `telecom` é resolvido por `config/mcp_servers.yaml`; no template base aponta para `http://localhost:8100/mcp` usando o contrato legacy HTTP. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, `ENABLE_OUTPUT_SUPERVISOR` afetam o ciclo antes/depois do agente. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` e `ENABLE_LONG_TERM_MEMORY` podem enriquecer o prompt/contexto sem substituir evidência MCP. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K` e `KBDB_*` controlam recuperação documental quando usada. + + +### Diagnóstico especial — por que duas tools aparecem na mesma intent + +A intent de faturamento autoriza `consultar_fatura` e `consultar_pagamentos` porque perguntas de conta/cobrança podem exigir evidência da fatura ou do histórico de pagamento. Isso **não significa que ambas precisam ser chamadas em todo turno**. + +`tools.yaml.selection_keywords`, o texto atual, os argumentos disponíveis e o runtime ajudam a escolher a capability adequada. Uma pergunta “quero segunda via/qual valor da fatura?” tende a usar `consultar_fatura`; uma pergunta específica sobre pagamento deve favorecer `consultar_pagamentos`. + +# 6. Regra — Produtos, Plano, Serviços e VAS + +**Intent:** `product_services_information` +**Domain:** `telecom` +**Agent:** `product_agent` +**Priority:** `20` + +## O que esta regra significa + +Dúvidas sobre plano, pacote, produto, serviço, VAS, internet, roaming e benefícios. + +### Limite da regra + +Serve para descobrir plano/serviços/VAS e explicar atributos. Não deve transformar uma pergunta sobre produto em oferta proativa ou action transacional. + +## `routing.yaml` atributo por atributo + +| Atributo | Valor nesta regra | Papel no motor | +|---|---|---| +| `name` | product_services_information | Nome estável da intent. É o identificador que aparece em state/telemetria e liga a decisão às capabilities declaradas. | +| `domain` | telecom | Domínio lógico. Ajuda a limitar contexto, agentes e interpretação do catálogo. | +| `agent` | product_agent | Agente que recebe o turno quando esta intent vence. | +| `description` | Dúvidas sobre plano, pacote, produto, serviço, VAS, internet, roaming e benefícios. | Descrição semântica usada por manutenção humana e pelo fallback LLM. | +| `priority` | 20 | Desempate entre intents concorrentes. No EnterpriseRouter, valores menores têm precedência. | +| `mcp_tools` | consultar_plano
listar_servicos | Lista de capabilities inicialmente autorizadas/esperadas para a intent. | +| `keywords` | plano
serviço
pacote
internet
roaming
vas
benefício
assinatura | Gatilhos determinísticos usados antes do fallback semântico. | +| `examples` | Quais serviços estão ativos no meu plano?
Quero saber sobre meu pacote de internet.
Tenho roaming internacional? | Exemplos oferecidos ao classificador LLM; não são regex nem regras executáveis. | + +## Como esta intent é encontrada + +1. O EnterpriseRouter verifica estado/transação ativa antes de tratar a frase como nova solicitação. +2. No matching determinístico, esta intent oferece keywords como `plano`, `serviço`, `pacote`, `internet`, `roaming`, `vas`, `benefício`, `assinatura`. +3. Em colisões, `priority=20` participa do desempate; menor número tem precedência. +4. Se o fallback LLM for usado, a descrição e exemplos como `Quais serviços estão ativos no meu plano?`, `Quero saber sobre meu pacote de internet.`, `Tenho roaming internacional?` ajudam a classificação. +5. Quando a intent vence, o state recebe route/agente e o conjunto inicial de tools `['consultar_plano', 'listar_servicos']`. + +## Agente proprietário e comportamento Python + +Arquivo: `app/agents/product_agent.py`. +O `run()` segue um padrão comum: emite IC de início, coleta contexto MCP, verifica mensagens de clarificação/confirmação transacional, tenta resposta direta por MCP/renderer, consulta RAG quando necessário, prepara memória, monta `messages`, chama o LLM e devolve patch de estado. +Esse padrão vem de `app/agents/runtime.py::AgentRuntimeMixin`, evitando que cada agente reimplemente MCP, RAG, cache, memória, IC e lógica transacional. + +## Tools desta regra + +### Tool `consultar_plano` + +**O que faz:** Consulta plano ativo e atributos comerciais. + +| Propriedade | Valor | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `plano` | +| apresentação | `mode=renderer`; renderer `telecom.plan` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `msisdn` | `string` | contexto canônico `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | +| `asset_id` | `string` | contexto canônico `resource_key`; contexto canônico `contract_key` | Identificador do plano ou ativo comercial associado ao cliente. | + +**Aliases MCP:** `customer_key → msisdn`, `resource_key → asset_id`, `contract_key → asset_id`, `session_key → session_id`. + +**O que retorna:** Retorna `msisdn`, `asset_id`, nome do plano, franquia de internet, atributo de roaming e status. + +### Tool `listar_servicos` + +**O que faz:** Lista serviços ativos e adicionais VAS. + +| Propriedade | Valor | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `serviços`, `servicos`, `vas` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `msisdn` | `string` | contexto canônico `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | + +**Aliases MCP:** `customer_key → msisdn`, `session_key → session_id`. + +**O que retorna:** Retorna `msisdn` e `servicos[]` com nome, status e valor. + +## Workflow + +Esta regra não possui workflow declarativo obrigatório no template base. A execução ocorre via MCP/runtime padrão; estados transacionais ainda podem existir para coleta/confirmar actions. + +## Amarração entre YAML e Python + +- `config/routing.yaml` → encontra `product_services_information` e escolhe `product_agent`. +- `config/tools.yaml` → descreve argumentos, servidor MCP, keywords de seleção e renderer. +- `config/tool_policies.yaml` → define read-only/transactional, confirmation, pre-validation e/ou workflow. +- `config/mcp_parameter_mapping.yaml` → traduz chaves canônicas e extrai campos da mensagem. +- `app/agents/product_agent.py` → usa `AgentRuntimeMixin` para executar capabilities sem duplicar infraestrutura. +- `app/workflows/agent_graph.py` → conecta o agente ao fluxo corporativo e aos controles de saída. +- `mcp/servers/telecom_mcp_server/main.py` → implementação mock/contrato da tool `consultar_plano`. +- `mcp/servers/telecom_mcp_server/main.py` → implementação mock/contrato da tool `listar_servicos`. + +### `.env` e configuração relevante + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` e `ENABLE_LLM_ROUTER` controlam o catálogo/semântica de roteamento. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE` e `END_SESSION_MESSAGE` controlam continuidade/sessão. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH` e `MCP_TOOL_TIMEOUT_SECONDS` controlam tools. +- `MCP_GATEWAY_ENABLED` decide entre chamada via MCP Gateway dedicado e acesso direto aos MCP servers configurados. +- O servidor lógico `telecom` é resolvido por `config/mcp_servers.yaml`; no template base aponta para `http://localhost:8100/mcp` usando o contrato legacy HTTP. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, `ENABLE_OUTPUT_SUPERVISOR` afetam o ciclo antes/depois do agente. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` e `ENABLE_LONG_TERM_MEMORY` podem enriquecer o prompt/contexto sem substituir evidência MCP. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K` e `KBDB_*` controlam recuperação documental quando usada. + +# 7. Regra — Cancelamento de Pedido + +**Intent:** `retail_order_cancel` +**Domain:** `retail` +**Agent:** `orders_agent` +**Priority:** `20` + +## O que esta regra significa + +Cancelamento explícito de pedido ou compra. + +### Limite da regra + +A intent representa desejo de cancelar. A execução depende de `order_id`, pre-validation e confirmação; um pedido não elegível é bloqueado antes da confirmação. + +## `routing.yaml` atributo por atributo + +| Atributo | Valor nesta regra | Papel no motor | +|---|---|---| +| `name` | retail_order_cancel | Nome estável da intent. É o identificador que aparece em state/telemetria e liga a decisão às capabilities declaradas. | +| `domain` | retail | Domínio lógico. Ajuda a limitar contexto, agentes e interpretação do catálogo. | +| `agent` | orders_agent | Agente que recebe o turno quando esta intent vence. | +| `description` | Cancelamento explícito de pedido ou compra. | Descrição semântica usada por manutenção humana e pelo fallback LLM. | +| `priority` | 20 | Desempate entre intents concorrentes. No EnterpriseRouter, valores menores têm precedência. | +| `mcp_tools` | consultar_pedido
cancelar_pedido | Lista de capabilities inicialmente autorizadas/esperadas para a intent. | +| `keywords` | cancelar pedido
cancelamento do pedido
cancelar a compra
cancelar compra | Gatilhos determinísticos usados antes do fallback semântico. | +| `examples` | Quero cancelar meu pedido.
Cancele o pedido.
Quero cancelar a compra. | Exemplos oferecidos ao classificador LLM; não são regex nem regras executáveis. | + +## Como esta intent é encontrada + +1. O EnterpriseRouter verifica estado/transação ativa antes de tratar a frase como nova solicitação. +2. No matching determinístico, esta intent oferece keywords como `cancelar pedido`, `cancelamento do pedido`, `cancelar a compra`, `cancelar compra`. +3. Em colisões, `priority=20` participa do desempate; menor número tem precedência. +4. Se o fallback LLM for usado, a descrição e exemplos como `Quero cancelar meu pedido.`, `Cancele o pedido.`, `Quero cancelar a compra.` ajudam a classificação. +5. Quando a intent vence, o state recebe route/agente e o conjunto inicial de tools `['consultar_pedido', 'cancelar_pedido']`. + +## Agente proprietário e comportamento Python + +Arquivo: `app/agents/orders_agent.py`. +O `run()` segue um padrão comum: emite IC de início, coleta contexto MCP, verifica mensagens de clarificação/confirmação transacional, tenta resposta direta por MCP/renderer, consulta RAG quando necessário, prepara memória, monta `messages`, chama o LLM e devolve patch de estado. +Esse padrão vem de `app/agents/runtime.py::AgentRuntimeMixin`, evitando que cada agente reimplemente MCP, RAG, cache, memória, IC e lógica transacional. + +## Tools desta regra + +### Tool `consultar_pedido` + +**O que faz:** Consulta pedido de varejo por order_id/customer_id. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| apresentação | `mode=renderer`; renderer `retail.order` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | contexto canônico `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**Aliases MCP:** `customer_key → customer_id`, `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna `order_id`, `customer_id`, `status`, `valor_total` e `itens[]`. No mock, `123` e `PED-ENTREGUE` aparecem como `ENTREGUE`; outros pedidos ficam `EM_TRANSPORTE`. + +### Tool `cancelar_pedido` + +**O que faz:** Simula o cancelamento de um pedido de varejo. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `transactional` | +| confirmação obrigatória | `true` | +| requires | `order_id` | +| selection_keywords | `cancelar pedido`, `cancelamento do pedido`, `cancelar compra`, `cancelar a compra` | +| pre-validation | `validar_cancelamento_pedido`; `fail_open=false` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido que o cliente deseja cancelar. | + +**Aliases MCP:** `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna protocolo, `order_id`, status `CANCELAMENTO_SOLICITADO` e orientação. Como é transacional, só deve executar após parâmetros, pre-validation e confirmação. + +### Tool interna usada pela policy + +### Tool `validar_cancelamento_pedido` + +**O que faz:** Pre-valida cancelamento do pedido sem executar efeitos transacionais. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `internal` | +| confirmação obrigatória | `false` | +| requires | `order_id` | +| selection_keywords | — | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | contexto canônico `resource_key` | Identificador do pedido a ser pre-validado para cancelamento. | +| `target_tool` | `string` | state/contexto, coleta de parâmetros ou chamada explícita | Nome interno da operação transacional que será pre-validada; normalmente preenchido pelo runtime e não solicitado ao usuário. | + +**Aliases MCP:** `resource_key → order_id`. + +**O que retorna:** Retorna `eligible`, `status`, `order_id`, `reason` quando bloqueado e metadata `side_effect_free`. É uma tool interna/read-only usada antes da confirmação. + +## Workflow + +Esta regra não possui workflow declarativo obrigatório no template base. A execução ocorre via MCP/runtime padrão; estados transacionais ainda podem existir para coleta/confirmar actions. + +## Amarração entre YAML e Python + +- `config/routing.yaml` → encontra `retail_order_cancel` e escolhe `orders_agent`. +- `config/tools.yaml` → descreve argumentos, servidor MCP, keywords de seleção e renderer. +- `config/tool_policies.yaml` → define read-only/transactional, confirmation, pre-validation e/ou workflow. +- `config/mcp_parameter_mapping.yaml` → traduz chaves canônicas e extrai campos da mensagem. +- `app/agents/orders_agent.py` → usa `AgentRuntimeMixin` para executar capabilities sem duplicar infraestrutura. +- `app/workflows/agent_graph.py` → conecta o agente ao fluxo corporativo e aos controles de saída. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `cancelar_pedido`. + +### `.env` e configuração relevante + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` e `ENABLE_LLM_ROUTER` controlam o catálogo/semântica de roteamento. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE` e `END_SESSION_MESSAGE` controlam continuidade/sessão. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH` e `MCP_TOOL_TIMEOUT_SECONDS` controlam tools. +- `MCP_GATEWAY_ENABLED` decide entre chamada via MCP Gateway dedicado e acesso direto aos MCP servers configurados. +- O servidor lógico `retail` é resolvido por `config/mcp_servers.yaml`; no template base aponta para `http://localhost:8200/mcp` usando o contrato legacy HTTP. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, `ENABLE_OUTPUT_SUPERVISOR` afetam o ciclo antes/depois do agente. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` e `ENABLE_LONG_TERM_MEMORY` podem enriquecer o prompt/contexto sem substituir evidência MCP. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K` e `KBDB_*` controlam recuperação documental quando usada. + + +### Diagnóstico especial — por que `PED-ENTREGUE` não chega à confirmação + +A intent `retail_order_cancel` representa o **objetivo do cliente**: cancelar um pedido. Depois do routing, a policy de `cancelar_pedido` exige `order_id`, chama a pre-validation `validar_cancelamento_pedido` e só permite `AWAITING_CONFIRMATION` quando o validator devolve `eligible=true`. + +No MCP de exemplo: + +```text +PED-1001 +→ validar_cancelamento_pedido +→ eligible=true +→ AWAITING_CONFIRMATION +→ "sim" +→ cancelar_pedido +→ protocolo CANCEL-2026-001 +``` + +Já: + +```text +PED-ENTREGUE +→ validar_cancelamento_pedido +→ eligible=false / NOT_ELIGIBLE +→ OUT_OF_SCOPE +→ não pergunta confirmação +→ cancelar_pedido não executa +``` + +Isto ilustra a mesma regra arquitetural usada no agente de Contas: **intent não é autorização operacional**. A intent diz o que o cliente quer; a pre-validation de domínio determina se a operação pode prosseguir. + +# 8. Regra — Consulta e Rastreamento de Pedido + +**Intent:** `retail_order_tracking` +**Domain:** `retail` +**Agent:** `orders_agent` +**Priority:** `30` + +## O que esta regra significa + +Consulta de pedido, entrega, rastreamento, atraso e status de compra. + +### Limite da regra + +É read-only: consulta estado do pedido/entrega. Não deve alterar o pedido. + +## `routing.yaml` atributo por atributo + +| Atributo | Valor nesta regra | Papel no motor | +|---|---|---| +| `name` | retail_order_tracking | Nome estável da intent. É o identificador que aparece em state/telemetria e liga a decisão às capabilities declaradas. | +| `domain` | retail | Domínio lógico. Ajuda a limitar contexto, agentes e interpretação do catálogo. | +| `agent` | orders_agent | Agente que recebe o turno quando esta intent vence. | +| `description` | Consulta de pedido, entrega, rastreamento, atraso e status de compra. | Descrição semântica usada por manutenção humana e pelo fallback LLM. | +| `priority` | 30 | Desempate entre intents concorrentes. No EnterpriseRouter, valores menores têm precedência. | +| `mcp_tools` | consultar_pedido
consultar_entrega | Lista de capabilities inicialmente autorizadas/esperadas para a intent. | +| `keywords` | pedido
entrega
rastreio
rastreamento
encomenda
compra
atraso
correios | Gatilhos determinísticos usados antes do fallback semântico. | +| `examples` | Meu pedido não chegou.
Quero rastrear minha entrega.
Qual é o status da minha compra? | Exemplos oferecidos ao classificador LLM; não são regex nem regras executáveis. | + +## Como esta intent é encontrada + +1. O EnterpriseRouter verifica estado/transação ativa antes de tratar a frase como nova solicitação. +2. No matching determinístico, esta intent oferece keywords como `pedido`, `entrega`, `rastreio`, `rastreamento`, `encomenda`, `compra`, `atraso`, `correios`. +3. Em colisões, `priority=30` participa do desempate; menor número tem precedência. +4. Se o fallback LLM for usado, a descrição e exemplos como `Meu pedido não chegou.`, `Quero rastrear minha entrega.`, `Qual é o status da minha compra?` ajudam a classificação. +5. Quando a intent vence, o state recebe route/agente e o conjunto inicial de tools `['consultar_pedido', 'consultar_entrega']`. + +## Agente proprietário e comportamento Python + +Arquivo: `app/agents/orders_agent.py`. +O `run()` segue um padrão comum: emite IC de início, coleta contexto MCP, verifica mensagens de clarificação/confirmação transacional, tenta resposta direta por MCP/renderer, consulta RAG quando necessário, prepara memória, monta `messages`, chama o LLM e devolve patch de estado. +Esse padrão vem de `app/agents/runtime.py::AgentRuntimeMixin`, evitando que cada agente reimplemente MCP, RAG, cache, memória, IC e lógica transacional. + +## Tools desta regra + +### Tool `consultar_pedido` + +**O que faz:** Consulta pedido de varejo por order_id/customer_id. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| apresentação | `mode=renderer`; renderer `retail.order` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | contexto canônico `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**Aliases MCP:** `customer_key → customer_id`, `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna `order_id`, `customer_id`, `status`, `valor_total` e `itens[]`. No mock, `123` e `PED-ENTREGUE` aparecem como `ENTREGUE`; outros pedidos ficam `EM_TRANSPORTE`. + +### Tool `consultar_entrega` + +**O que faz:** Consulta entrega e rastreamento do pedido. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `entrega`, `rastreio`, `rastreamento`, `transportadora`, `previsão` | +| apresentação | `mode=renderer`; renderer `retail.delivery` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido cuja entrega ou rastreamento será consultado. | + +**Aliases MCP:** `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna `order_id`, transportadora, código de rastreio, previsão e eventos de movimentação. + +## Workflow + +Esta regra não possui workflow declarativo obrigatório no template base. A execução ocorre via MCP/runtime padrão; estados transacionais ainda podem existir para coleta/confirmar actions. + +## Amarração entre YAML e Python + +- `config/routing.yaml` → encontra `retail_order_tracking` e escolhe `orders_agent`. +- `config/tools.yaml` → descreve argumentos, servidor MCP, keywords de seleção e renderer. +- `config/tool_policies.yaml` → define read-only/transactional, confirmation, pre-validation e/ou workflow. +- `config/mcp_parameter_mapping.yaml` → traduz chaves canônicas e extrai campos da mensagem. +- `app/agents/orders_agent.py` → usa `AgentRuntimeMixin` para executar capabilities sem duplicar infraestrutura. +- `app/workflows/agent_graph.py` → conecta o agente ao fluxo corporativo e aos controles de saída. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `consultar_entrega`. + +### `.env` e configuração relevante + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` e `ENABLE_LLM_ROUTER` controlam o catálogo/semântica de roteamento. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE` e `END_SESSION_MESSAGE` controlam continuidade/sessão. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH` e `MCP_TOOL_TIMEOUT_SECONDS` controlam tools. +- `MCP_GATEWAY_ENABLED` decide entre chamada via MCP Gateway dedicado e acesso direto aos MCP servers configurados. +- O servidor lógico `retail` é resolvido por `config/mcp_servers.yaml`; no template base aponta para `http://localhost:8200/mcp` usando o contrato legacy HTTP. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, `ENABLE_OUTPUT_SUPERVISOR` afetam o ciclo antes/depois do agente. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` e `ENABLE_LONG_TERM_MEMORY` podem enriquecer o prompt/contexto sem substituir evidência MCP. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K` e `KBDB_*` controlam recuperação documental quando usada. + +# 9. Regra — Troca, Devolução, Garantia e Suporte Retail + +**Intent:** `retail_support_exchange_return` +**Domain:** `retail` +**Agent:** `support_agent` +**Priority:** `25` + +## O que esta regra significa + +Suporte, troca, devolução, garantia e problema com produto. + +### Limite da regra + +Agrupa suporte pós-venda. A intent pode escolher troca ou devolução como tool específica; as actions transacionais ainda exigem confirmação. + +## `routing.yaml` atributo por atributo + +| Atributo | Valor nesta regra | Papel no motor | +|---|---|---| +| `name` | retail_support_exchange_return | Nome estável da intent. É o identificador que aparece em state/telemetria e liga a decisão às capabilities declaradas. | +| `domain` | retail | Domínio lógico. Ajuda a limitar contexto, agentes e interpretação do catálogo. | +| `agent` | support_agent | Agente que recebe o turno quando esta intent vence. | +| `description` | Suporte, troca, devolução, garantia e problema com produto. | Descrição semântica usada por manutenção humana e pelo fallback LLM. | +| `priority` | 25 | Desempate entre intents concorrentes. No EnterpriseRouter, valores menores têm precedência. | +| `mcp_tools` | consultar_pedido
solicitar_troca
solicitar_devolucao | Lista de capabilities inicialmente autorizadas/esperadas para a intent. | +| `keywords` | solicitar devolução
devolver pedido
solicitar troca
troca
devolução
devolver
garantia
defeito
produto quebrado
suporte
arrependimento | Gatilhos determinísticos usados antes do fallback semântico. | +| `examples` | Quero trocar um produto.
Meu produto veio com defeito.
Como faço uma devolução? | Exemplos oferecidos ao classificador LLM; não são regex nem regras executáveis. | + +## Como esta intent é encontrada + +1. O EnterpriseRouter verifica estado/transação ativa antes de tratar a frase como nova solicitação. +2. No matching determinístico, esta intent oferece keywords como `solicitar devolução`, `devolver pedido`, `solicitar troca`, `troca`, `devolução`, `devolver`, `garantia`, `defeito`, `produto quebrado`, `suporte`. +3. Em colisões, `priority=25` participa do desempate; menor número tem precedência. +4. Se o fallback LLM for usado, a descrição e exemplos como `Quero trocar um produto.`, `Meu produto veio com defeito.`, `Como faço uma devolução?` ajudam a classificação. +5. Quando a intent vence, o state recebe route/agente e o conjunto inicial de tools `['consultar_pedido', 'solicitar_troca', 'solicitar_devolucao']`. + +## Agente proprietário e comportamento Python + +Arquivo: `app/agents/support_agent.py`. +O `run()` segue um padrão comum: emite IC de início, coleta contexto MCP, verifica mensagens de clarificação/confirmação transacional, tenta resposta direta por MCP/renderer, consulta RAG quando necessário, prepara memória, monta `messages`, chama o LLM e devolve patch de estado. +Esse padrão vem de `app/agents/runtime.py::AgentRuntimeMixin`, evitando que cada agente reimplemente MCP, RAG, cache, memória, IC e lógica transacional. + +## Tools desta regra + +### Tool `consultar_pedido` + +**O que faz:** Consulta pedido de varejo por order_id/customer_id. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `read_only` | +| confirmação obrigatória | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| apresentação | `mode=renderer`; renderer `retail.order` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | contexto canônico `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**Aliases MCP:** `customer_key → customer_id`, `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna `order_id`, `customer_id`, `status`, `valor_total` e `itens[]`. No mock, `123` e `PED-ENTREGUE` aparecem como `ENTREGUE`; outros pedidos ficam `EM_TRANSPORTE`. + +### Tool `solicitar_troca` + +**O que faz:** Simula abertura de solicitação de troca. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `transactional` | +| confirmação obrigatória | `true` | +| requires | `order_id`, `reason` | +| selection_keywords | `solicitar troca`, `trocar`, `troca`, `defeito`, `quebrado` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido para o qual o cliente deseja solicitar troca. | +| `reason` | `string` | default `Solicitação aberta pelo atendimento conversacional.` | Motivo informado pelo cliente para solicitar a troca do pedido. | + +**Aliases MCP:** `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** Retorna protocolo, `order_id`, status `ABERTO` e orientação para postagem/continuidade da troca. + +### Tool `solicitar_devolucao` + +**O que faz:** Simula abertura de solicitação de devolução. + +| Propriedade | Valor | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| tipo/operação | `transactional` | +| confirmação obrigatória | `true` | +| requires | `order_id`, `reason` | +| selection_keywords | `solicitar devolução`, `solicitar devolucao`, `devolver pedido`, `devolver`, `devolução`, `devolucao`, `arrependimento` | +| execution | `mode=workflow`; workflow `devolucao_pedido`; version `active` | + +**Dados necessários e origem** + +| Campo | Tipo | Como é obtido | Uso | +|---|---|---|---| +| `order_id` | `string` | extração `hybrid` de `message` | Identificador do pedido para o qual o cliente deseja solicitar devolução. | +| `reason` | `string` | default `Solicitação aberta pelo atendimento conversacional.` | Motivo informado pelo cliente para solicitar a devolução do pedido. | + +**Aliases MCP:** `session_key → session_id`. + +**Extração conversacional:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**O que retorna:** No MCP direto retorna protocolo/status/orientação; no template normal a policy escolhe `execution.mode: workflow`, portanto a execução final passa pelo workflow determinístico `devolucao_pedido`. + +**Execução especial:** esta tool está ligada a workflow determinístico pela policy; detalhes no capítulo de workflow abaixo. + +## Workflow(s) envolvidos + +### Workflow `devolucao_pedido.v1.yaml` + +**Contrato:** `name=devolucao_pedido`, `version=1`, `start=validar_pedido`. + +**Por que foi construído assim:** a devolução é uma ação transacional de múltiplos passos. O template separa a decisão conversacional da execução determinística: primeiro valida o pedido e só registra a devolução se a validação retornar `valid=true`. Isso impede o LLM de escolher livremente a sequência de efeitos. + +#### Nós + +| Nó | Action | Entrada | Papel | +|---|---|---|---| +| `validar_pedido` | `validar_pedido` | `order_id=$.input.order_id` | Ponto inicial de validação. | +| `registrar_devolucao` | `registrar_devolucao` | `order_id=$.input.order_id`, `reason=$.input.reason` | Executa o efeito/registro de devolução. Possui `retry=1`. | + +#### Condições e término + +| De | Para | Condição | Consequência | +|---|---|---|---| +| `validar_pedido` | `registrar_devolucao` | `{"path": "$.nodes.validar_pedido.valid", "equals": true}` | Avança para `registrar_devolucao`. | +| `validar_pedido` | `END` | `{"path": "$.nodes.validar_pedido.valid", "equals": false}` | Encerra o workflow. | +| `registrar_devolucao` | `END` | sempre | Encerra o workflow. | + +#### Actions Python + +- `app/workflow_actions/devolucao.py::validar_pedido`: valida `order_id` e devolve um contrato com `valid`. +- `app/workflow_actions/devolucao.py::registrar_devolucao`: registra o resultado determinístico da devolução e produz `protocol`, `order_id`, `status` e dados necessários ao retorno. + +#### Pause/Resume + +Este workflow base **não possui nó de pause**. A coleta de `order_id`/`reason` e a confirmação acontecem antes, no runtime transacional. Os exemplos de pause/resume ficam demonstrados separadamente em `Tuning-Performance/Pause_Resume_Workflow`. + +## Amarração entre YAML e Python + +- `config/routing.yaml` → encontra `retail_support_exchange_return` e escolhe `support_agent`. +- `config/tools.yaml` → descreve argumentos, servidor MCP, keywords de seleção e renderer. +- `config/tool_policies.yaml` → define read-only/transactional, confirmation, pre-validation e/ou workflow. +- `config/mcp_parameter_mapping.yaml` → traduz chaves canônicas e extrai campos da mensagem. +- `app/agents/support_agent.py` → usa `AgentRuntimeMixin` para executar capabilities sem duplicar infraestrutura. +- `app/workflows/agent_graph.py` → conecta o agente ao fluxo corporativo e aos controles de saída. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `solicitar_troca`. +- `mcp/servers/retail_mcp_server/main.py` → implementação mock/contrato da tool `solicitar_devolucao`. + +### `.env` e configuração relevante + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` e `ENABLE_LLM_ROUTER` controlam o catálogo/semântica de roteamento. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE` e `END_SESSION_MESSAGE` controlam continuidade/sessão. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH` e `MCP_TOOL_TIMEOUT_SECONDS` controlam tools. +- `MCP_GATEWAY_ENABLED` decide entre chamada via MCP Gateway dedicado e acesso direto aos MCP servers configurados. +- O servidor lógico `retail` é resolvido por `config/mcp_servers.yaml`; no template base aponta para `http://localhost:8200/mcp` usando o contrato legacy HTTP. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, `ENABLE_OUTPUT_SUPERVISOR` afetam o ciclo antes/depois do agente. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` e `ENABLE_LONG_TERM_MEMORY` podem enriquecer o prompt/contexto sem substituir evidência MCP. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K` e `KBDB_*` controlam recuperação documental quando usada. + + +### Diagnóstico especial — troca e devolução compartilham intent, mas não a mesma execução + +`retail_support_exchange_return` agrupa suporte pós-venda porque as frases têm grande sobreposição semântica. A decisão da **tool** ocorre dentro do conjunto permitido: + +- “trocar”, “troca”, “defeito”, “quebrado” → `solicitar_troca`; +- “devolver”, “devolução”, “arrependimento” → `solicitar_devolucao`; +- `consultar_pedido` pode ser usado para obter contexto do recurso. + +As duas actions são transacionais e exigem confirmação. A diferença principal é que `solicitar_devolucao` possui em `tool_policies.yaml`: + +```yaml +execution: + mode: workflow + workflow: devolucao_pedido + version: active +``` + +Portanto, depois da confirmação, a devolução não é apenas uma chamada direta: ela entra no workflow determinístico. Já a troca segue a execução transacional padrão da tool. + +# Regras e mecanismos transversais do template + + +## Seleção de tools dentro de uma intent + +`routing.yaml.mcp_tools` define o conjunto compatível com a intent. `tools.yaml.selection_keywords`, argumentos disponíveis, estado transacional e policies ajudam a determinar qual capability deve executar. O fato de duas tools estarem associadas à mesma intent não significa execução obrigatória de ambas. + +## Resposta direta por MCP versus LLM + +Os agentes chamam `build_direct_mcp_answer()`. Quando o resultado possui renderer/contrato determinístico suficiente, o runtime pode responder diretamente e marcar RAG como `skipped: direct_mcp_answer`. + +Quando não há resposta direta suficiente, o agente pode recuperar RAG, preparar memória e usar o LLM. + +## `prompt_policy.yaml` + +Define tom e vocabulário preferencial; também registra intents/agentes para composição de prompt. Não substitui `routing.yaml`. + +## Configurações por `agent_id` + +`config/agents//prompt_policy.yaml`, `guardrails.yaml` e `judges.yaml` permitem especializar cada identidade lógica. O registro fica em `config/agents.yaml`. + +## MCP transport + +`config/mcp_servers.yaml` documenta três estilos: + +- `http`: contrato legacy do framework; +- `fastmcp`: MCP Streamable HTTP oficial; +- `sse`: MCP SSE oficial. + +No template base, `telecom` e `retail` usam `http` local, mas o registry pode ser alterado sem reescrever agentes. + +## MCP Gateway + +Com `MCP_GATEWAY_ENABLED=true`, o backend delega chamadas ao MCP Gateway dedicado (`MCP_GATEWAY_URL`). Com `false`, usa diretamente os endpoints do registry. + +## Memória resumida + +`ENABLE_CONVERSATION_SUMMARY_MEMORY=true` permite preparar resumo + mensagens recentes antes de montar `messages`. O objetivo é reduzir contexto sem perder continuidade. + +## RAG + +O template pode usar memory/vector/graph stores e KBDB. RAG não substitui tool operacional. O `ProductAgent` emite IC detalhado mesmo quando a recuperação foi tentada e não produziu contexto. + +## Observabilidade + +O runtime pode publicar eventos para Langfuse, OTEL e analytics. O `AgentObserver` padroniza IC/NOC/GRL. O `TelemetryObserver` do template conecta eventos do workflow à infraestrutura de observabilidade. + +## Presentation + +`app/presentation/tool_renderers.py` desacopla payload MCP de resposta textual/visual. Renderers são úteis quando existe uma apresentação determinística que deve evitar custo/latência de LLM. + +## Workflow actions + +`app/workflow_actions/` contém effects/actions de domínio que são referenciados pelos YAMLs. O workflow define ordem/condição; a action implementa operação. + +## Diagnóstico de decisão inesperada + +1. Verifique `agent_id`. +2. Inspecione `transaction_status`, `next_state`, workflow pausado e checkpoint. +3. Veja `routing_decision` e método (`state`, keyword, LLM, stickiness). +4. Confirme intent, route e `mcp_tools`. +5. Veja qual tool foi realmente selecionada. +6. Compare `requires` com `resolved_arguments`/`missing_parameters`. +7. Procure reconciliação temporal/contextual reentry. +8. Veja `transaction_pre_validation`. +9. Confirme se houve `AWAITING_CONFIRMATION`. +10. Identifique execução direta versus workflow. +11. Inspecione `mcp_results`, `transaction_evidence`, RAG e renderer. +12. Verifique Output Supervisor, guardrails e judges. +13. Confirme persistência/pending topics no final do turno. + +# Parte II — `Tuning-Performance` + +`Tuning-Performance` não deve ser lido apenas como “otimização de velocidade”. A pasta funciona como um catálogo de **cenários isolados de capacidades do framework**, útil para benchmark, regressão e entendimento arquitetural. + +O template base já incorporou várias dessas capacidades. Alguns diretórios guardam uma cópia executável modificada; outros contêm somente documentação; `Normal` e `Long_Term_Memory` estão vazios neste pacote, portanto não representam uma variante executável adicional nesta versão. + +## Inventário do `Tuning-Performance` + +| Cenário | Conteúdo neste pacote | Objetivo | +|---|---|---| +| `Authentication` | README + variante executável do template | Autenticação transversal por providers/middleware e políticas de rota. | +| `Deterministic_Transactional_Workflow` | README + variante executável do template | Execução multi-etapas determinística após confirmação. | +| `Domain_Requested_LLM_Composition` | documentação/exemplo | Domínio solicita redação pelo LLM oficial sem criar gateway LLM próprio. | +| `Domain_Requested_RAG` | documentação/exemplo | Domínio solicita RAG do framework quando MCP não é suficiente. | +| `External_Guardrails_Judges` | README + variante executável do template | Extensões externas de guardrails/judges e medição de overhead. | +| `Long_Term_Memory` | documentação/exemplo | Diretório reservado; capability está no framework/template, sem variante local neste pacote. | +| `Normal` | documentação/exemplo | Baseline reservado; diretório vazio neste pacote. | +| `Offline_Workflow_Regression` | documentação/exemplo | Fallback determinístico opt-in para testes offline da DSL de workflow. | +| `Pause_Resume_Workflow` | README + variante executável do template | Pause/resume por execution_id e expected_input. | +| `Route_Stickness` | documentação/exemplo | Continuidade semântica, handoff, encerramento e policies MCP. | +| `Transaction_Evidence` | README + variante executável do template | Persistência/correlação de evidência operacional transacional. | +| `Transaction_Pre_Validation` | README + variante executável do template | Validator MCP side-effect-free antes da confirmação. | +| `Voice_Interruption_Replay` | documentação/exemplo | Short-circuit/replay para voz sem reexecutar o grafo indevidamente. | +| `Workflow_Error_Recovery` | documentação/exemplo | Snapshot parcial e error_details estruturado em falhas de workflow. | + +# T1. Tuning — `Authentication` + +**Objetivo:** Autenticação transversal por providers/middleware e políticas de rota. + +## O que este cenário demonstra + +> [!IMPORTANT] > **Template de referência — requer adequação antes do uso produtivo.** > Esta implementação demonstra pontos de extensão, providers, middleware e exemplos de configuração para autenticação. Ela não deve ser considerada uma solução pronta para produção nem substitui o desenho de segurança do projeto. Antes da implantação, a equipe responsável deve revisar, testar e adaptar o código às políticas corporativas, ao modelo de identidade, à topologia de rede, à gestão e rotação de segredos, aos requisitos regulatórios, à observabilidade, à alta disponibilidade e ao processo de resposta a incidentes do ambiente do cliente. Recomenda-se executar security review, threat modeling, testes de integração e testes de segurança antes da homologação e da produção. Implementação de referência para autenticação transversal no Agent Framework OCI. Inclui: - providers genéricos em `libs/agent_framework/security`; - instalação opcional por `install_authentication()`; - políticas por rota, método, roles e scopes; + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/Authentication/agent_template_backend_authentication`. + +**Arquivos alterados:** `requirements.txt`, `README.md`, `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Arquivos adicionados:** `docs/MANUAL_AUTENTICACAO.md`, `config/authentication.example.yaml`, `scripts/generate_secret_hash.py`. + + +## Motor e configuração + +A variante usa `install_authentication()`/providers de `libs/agent_framework/security` e adiciona `config/authentication.example.yaml`. O `.env.example` demonstra: + +```text +AGENT_AUTH_MODE=basic|api_key|bearer_static|jwt|oauth2_introspection|trusted_proxy +AGENT_AUTH_PUBLIC_PATHS +AGENT_AUTH_PUBLIC_PREFIXES +``` + +No exemplo Basic, a credencial é armazenada como hash (`AGENT_AUTH_BASIC_SECRET_HASH`) e o script `scripts/generate_secret_hash.py` ajuda a gerar o valor. + +A autenticação é **transversal**: ocorre na borda HTTP/middleware antes do motor conversacional. Ela não deve virar keyword de routing nem regra dentro do agente. + +## O que validar + +- rotas realmente públicas; +- fail-closed nas rotas protegidas; +- rotação/armazenamento de segredo; +- claims/roles/scopes por provider; +- bloqueio de acesso direto ao pod quando `trusted_proxy`; +- observabilidade sem registrar segredo/token. + +A própria documentação marca esta implementação como referência que requer security review antes de produção. + + +# T2. Tuning — `Deterministic_Transactional_Workflow` + +**Objetivo:** Execução multi-etapas determinística após confirmação. + +## O que este cenário demonstra + +Esta variante contém um `agent_template_backend` funcional que conecta o fluxo conversacional do framework ao motor determinístico de workflows transacionais. `Deterministic_Transactional_Workflow` é mais preciso que apenas `Transactional_Workflow`: a confirmação transacional já existia. O diferencial desta variante é executar uma sequência multi-etapas por um grafo determinístico, em vez de deixar o LLM escolher cada etapa. 1. O router seleciona `orders_agent`. 2. O runtime coleta `order_id` e `reason` por clarification. + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend`. + +**Arquivos alterados:** `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/agents/runtime.py`, `app/workflows/agent_graph.py`. + +**Arquivos adicionados:** `tests/test_transactional_workflow_template.py`. + + +## Fluxo + +```text +router +→ support_agent +→ coleta order_id + reason +→ AWAITING_CONFIRMATION +→ confirmação explícita +→ policy execution.mode=workflow +→ WorkflowToolExecutor +→ devolucao_pedido.active.yaml +→ devolucao_pedido.v1.yaml +→ validar_pedido +→ registrar_devolucao +→ protocolo + workflow_execution_id +``` + +O ganho principal não é “ter confirmação” — isso já existia. O diferencial é **tirar do LLM a escolha de sequência** após a confirmação. + +## O que medir + +- tempo de coleta/confirmation; +- latência do workflow; +- retries da action; +- idempotência/reexecução; +- consistência do `workflow_execution_id`; +- resposta quando `validar_pedido.valid=false`. + + +# T3. Tuning — `Domain_Requested_LLM_Composition` + +**Objetivo:** Domínio solicita redação pelo LLM oficial sem criar gateway LLM próprio. + +## O que este cenário demonstra + +Permitir que uma tool/workflow de domínio informe que o resultado operacional não deve ser devolvido diretamente ao usuário e precisa ser redigido pelo LLM oficial do agente, sem criar um gateway LLM dentro do domínio. A tool pode devolver, em qualquer nível do resultado: { "requires_llm_composition": true, "response_instruction": "Explique ao cliente a forma de devolução usando apenas os dados do workflow." } Também é aceito `response_instructions` como lista. O `AgentRuntimeMixin` percorre recursivamente o resultado MCP. Quando a flag está ativa, `build_direct_mcp_answer()` retorna `None`; a resposta segue pelo LLM configurado no framework e recebe as evidências MCP no contexto normal do agente. + + +## Contrato + +A tool/workflow pode retornar: + +```json +{ + "requires_llm_composition": true, + "response_instruction": "Explique usando somente as evidências do workflow." +} +``` + +ou `response_instructions` como lista. + +`AgentRuntimeMixin` detecta a flag recursivamente. Quando ativa, `build_direct_mcp_answer()` não encerra o turno; o resultado MCP entra como evidência na composição pelo LLM oficial. + +## Regra arquitetural + +O domínio pode pedir **redação**, mas não deve usar este mecanismo para decidir se a transação ocorre, inventar valores/protocolos ou criar provider LLM privado. Provider, profile, tracing, credenciais e custos continuam no framework. + + +# T4. Tuning — `Domain_Requested_RAG` + +**Objetivo:** Domínio solicita RAG do framework quando MCP não é suficiente. + +## O que este cenário demonstra + +Permitir que uma tool/workflow de domínio declare que o resultado MCP **não é suficiente** para produzir a resposta final e que o agente deve recuperar conhecimento usando o `RagService` oficial do `agent_framework_oci`. O domínio não instancia banco vetorial, embeddings, LLM ou cliente RAG. Ele apenas devolve no resultado: { "requires_rag": true, "rag_queries": [ "Como cancelar o serviço Paramount+ no parceiro? Procedimento oficial de cancelamento." ] } + + +## Contrato + +```json +{ + "requires_rag": true, + "rag_queries": [ + "Pergunta documental 1", + "Pergunta documental 2" + ] +} +``` + +Fluxo: + +```text +tool/workflow +→ requires_rag +→ AgentRuntimeMixin +→ RagService do framework +→ vector/graph store +→ LLM com MCP evidence + RAG evidence +``` + +A flag pode sobrepor a otimização `SKIP_RAG_WHEN_MCP_SUFFICIENT`. O domínio não instancia embeddings/vector store; apenas declara a necessidade e as queries. + + +# T5. Tuning — `External_Guardrails_Judges` + +**Objetivo:** Extensões externas de guardrails/judges e medição de overhead. + +## O que este cenário demonstra + +Este cenário de tuning mede extensões de política do agente. Antes de interpretar os resultados, implemente e valide o contrato descrito no [guia completo](../../docs/EXTERNAL_GUARDRAILS_JUDGES.md). O cenário deve comparar, no mínimo, latência p50/p95/p99, taxa de allow/deny/sanitize, erros e timeouts, custo de judges com LLM e comportamento fail-open/fail-closed. Separe resultados por código/nome e estágio, sem registrar prompts, PII ou payloads financeiros. Cuidados de leitura: - `type: external` afeta apenas o componente declarado; - implementação síncrona usa worker thread e implementação `async` usa o event loop; - judges executam concorrentemente, então meça contenção do provedor e do pool; - compare a mesma carga com extensão desligada para obter o overhead incremental; - execute casos transacionais separadamente, pois `always_run_for_transactional` ignora a amostragem; + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/External_Guardrails_Judges/agent_template_backend`. + +**Arquivos alterados:** `README.md`, `llm_profiles.yaml`, `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/judges.yaml`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `config/guardrails.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Arquivos adicionados:** `app/extensions/example_judges.py`, `app/extensions/__init__.py`, `app/extensions/example_guardrails.py`. + + +## O que muda + +A variante adiciona extensões em `app/extensions/example_guardrails.py` e `app/extensions/example_judges.py` e altera configs para demonstrar `type: external`. + +## Benchmark correto + +Compare com a extensão desligada e separe: + +- p50/p95/p99; +- allow/deny/sanitize; +- timeout/erro; +- custo de judges com LLM; +- comportamento fail-open/fail-closed; +- transacionais, pois `always_run_for_transactional` pode ignorar amostragem. + +Implementações síncronas podem usar worker thread; `async` usa event loop. O tuning deve observar contenção do provider/pool e não registrar prompts/PII/payload financeiro. + + +# T6. Tuning — `Long_Term_Memory` + +**Objetivo:** Diretório reservado; capability está no framework/template, sem variante local neste pacote. + +## Situação neste pacote + +O diretório está vazio. A capability, porém, existe no framework e no template base por `ENABLE_LONG_TERM_MEMORY`, `LONG_TERM_MEMORY_PROVIDER`, `LONG_TERM_MEMORY_*` e nós `load_long_term_memory` / `persist_long_term_memory` do grafo. Portanto este capítulo documenta a capability a partir do template normal, não uma variante específica. + + +## Como funciona no template base + +O grafo chama `load_long_term_memory` antes do routing e `persist_long_term_memory` próximo ao final. O manager é criado por `create_long_term_memory_manager(settings, telemetry=telemetry)` e injetado nos agentes. + +Variáveis principais: + +```text +ENABLE_LONG_TERM_MEMORY +LONG_TERM_MEMORY_PROVIDER +LONG_TERM_MEMORY_SQLITE_PATH +LONG_TERM_MEMORY_TABLE +LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS +LONG_TERM_MEMORY_MIN_CONFIDENCE +LONG_TERM_MEMORY_AUTO_EXTRACT +LONG_TERM_MEMORY_INJECT_CONTEXT +``` + +**Não confundir com Transaction Evidence:** LTM é memória semântica/durável; transaction evidence é fato operacional estruturado associado a execução/recurso. + + +# T7. Tuning — `Normal` + +**Objetivo:** Baseline reservado; diretório vazio neste pacote. + +## Situação neste pacote + +O diretório está vazio. O baseline efetivo é `templates/agent_template_backend`, que é a referência usada em todas as comparações deste manual. + + +## Baseline usado neste manual + +O baseline é `templates/agent_template_backend`. Ao avaliar qualquer tuning, compare contra exatamente a mesma configuração de: + +- LLM/provider; +- persistência; +- MCP transport; +- guardrails/judges; +- RAG; +- carga; +- dados de teste. + +Sem baseline controlado, a diferença de latência não pode ser atribuída à capability estudada. + + +# T8. Tuning — `Offline_Workflow_Regression` + +**Objetivo:** Fallback determinístico opt-in para testes offline da DSL de workflow. + +## O que este cenário demonstra + +O backend de produção de `WorkflowRuntime` continua sendo **LangGraph**. A ausência do pacote `langgraph` em produção é erro de configuração. Para builders restritos/offline, o runtime aceita `allow_deterministic_fallback=True`. Esse modo é deliberadamente opt-in e existe somente para exercitar a DSL do framework (actions, edges, condições, pause/resume e trace) quando a dependência externa não pode ser instalada. Ele não é selecionado automaticamente. Exemplo de teste: runtime = WorkflowRuntime( repository, actions=registry, allow_deterministic_fallback=True, ) + + +## Comportamento + +Produção continua exigindo LangGraph. O fallback determinístico só existe quando `allow_deterministic_fallback=True`, para builders/testes offline. + +Ele exercita a DSL: + +- actions; +- edges; +- condições; +- pause/resume; +- trace. + +Não deve ser escolhido automaticamente em produção, porque isso esconderia ausência/configuração incorreta do backend LangGraph. + + +# T9. Tuning — `Pause_Resume_Workflow` + +**Objetivo:** Pause/resume por execution_id e expected_input. + +## O que este cenário demonstra + +Este exemplo demonstra uma capability genérica do `agent_framework_oci`: workflows determinísticos podem interromper a execução para obter uma resposta do cliente e retomar posteriormente pelo mesmo `execution_id`, sem que o domínio importe ou monte um `StateGraph`. A aplicação declara o workflow em YAML. `WorkflowRuntime` transforma a definição em LangGraph internamente, utiliza o checkpointer configurado pelo framework e expõe somente: - `arun(name, payload)` — inicia ou executa o workflow; - `aresume(name, execution_id, value)` — retoma o workflow pausado; - `WorkflowRunResult.status` — `PAUSED`, `COMPLETED` ou `FAILED`. O `pause` é compilado em um nó separado da action anterior. Isto impede que uma action com efeito colateral seja executada novamente quando o cliente responde. A partir da raiz do exemplo, com as dependências do framework instaladas: python -m app.demo + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/Pause_Resume_Workflow/agent_template_backend`. + +**Arquivos alterados:** `README.md`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`. + +**Arquivos adicionados:** `app/demo.py`, `tests/test_pause_resume.py`, `workflows/confirmacao.active.yaml`, `workflows/confirmacao.v1.yaml`. + + +## Estrutura + +A variante adiciona `workflows/confirmacao.v1.yaml`, `confirmacao.active.yaml`, `app/demo.py` e testes. + +`WorkflowRuntime.arun()` inicia; quando o nó declara pause, devolve `PAUSED`. `aresume(name, execution_id, value)` retoma a mesma execução. + +O YAML demonstra: + +- `expected_input`; +- normalização; +- valores permitidos; +- `resume_from`; +- reprompt; +- `semantic_classifier`; +- reentrada contextual por opção. + +A pausa é separada da action anterior para não repetir efeito colateral ao retomar. + + +# T10. Tuning — `Route_Stickness` + +**Objetivo:** Continuidade semântica, handoff, encerramento e policies MCP. + +## O que este cenário demonstra + +A documentação PT/EN consolida route stickiness, handoff humano, encerramento de sessão e políticas MCP. O classificador decide continuidade (`CONTINUE`/`ROUTE`) e ações globais de sessão (`HUMAN_HANDOFF`/`END_SESSION`) sem executar tool por conta própria. + + +## Ordem de decisão + +```text +sessão encerrada? → rejeita/replay conforme canal +route stickiness habilitada? + → CONTINUE → agente ativo + → ROUTE/baixa confiança/erro → EnterpriseRouter + → HUMAN_HANDOFF → nó global + → END_SESSION → nó global +``` + +Variáveis documentadas: + +```text +ENABLE_ROUTE_STICKINESS=true +ROUTE_STICKINESS_LLM_PROFILE=route_continuity +ROUTE_STICKINESS_CONFIDENCE_THRESHOLD=0.90 +ROUTE_STICKINESS_HISTORY_TURNS=2 +ROUTE_STICKINESS_MAX_TOKENS=80 +HUMAN_HANDOFF_MESSAGE=... +END_SESSION_MESSAGE=... +``` + +Stickiness não autoriza tool. Mesmo em `CONTINUE`, a chamada MCP passa pelas policies read-only/transacionais. + + +# T11. Tuning — `Transaction_Evidence` + +**Objetivo:** Persistência/correlação de evidência operacional transacional. + +## O que este cenário demonstra + +Esta variante demonstra a funcionalidade **Transaction Evidence** do `agent_framework_oci`. Ela preserva o resultado estruturado de transações executadas no estado/checkpoint do LangGraph e o reutiliza, quando relevante, em turnos posteriores como evidência operacional para composição de resposta e groundedness. > Transaction Evidence **não é Long Term Memory**. É estado operacional associado à > sessão/workflow e aos recursos envolvidos na transação. Sem esta funcionalidade, uma transação pode ocorrer corretamente em um turno: quero cancelar pedido + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/Transaction_Evidence/agent_template_backend`. + +**Arquivos alterados:** `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Arquivos adicionados:** nenhum. + + +## Problema resolvido + +Uma transação pode ocorrer em um turno e ser mencionada depois. Sem evidência persistida, groundedness pode considerar o fato “cancelamento/protocolo” não sustentado. + +O runtime grava `transaction_evidence` e correlaciona itens relevantes em `relevant_transaction_evidence`. + +Exemplo: + +```text +cancelar_pedido(PED-1001) +→ COMPLETED +→ protocolo +→ transaction_evidence +... +"quero meu pedido" +→ consultar_pedido +→ relevant_transaction_evidence do cancelamento +→ resposta + judges recebem a mesma evidência +``` + +Transaction Evidence é operacional, não memória semântica. + + +# T12. Tuning — `Transaction_Pre_Validation` + +**Objetivo:** Validator MCP side-effect-free antes da confirmação. + +## O que este cenário demonstra + +Esta variante demonstra a capability genérica de **pré-validação MCP antes da confirmação**. A regra de negócio continua no MCP. O framework apenas orquestra o contrato genérico: parâmetros completos ↓ MCP validator (read-only / side-effect-free) ↓ eligible? ├─ false → OUT_OF_SCOPE / NOT_ELIGIBLE → responde sem pedir confirmação + +## Delta em relação ao template base + +Variante analisada: `Tuning-Performance/Transaction_Pre_Validation/agent_template_backend`. + +**Arquivos alterados:** `.env.example`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Arquivos adicionados:** nenhum. + + +## Fluxo + +```text +parâmetros completos +→ validar_cancelamento_pedido +→ eligible? + ├─ false → OUT_OF_SCOPE / terminal / limpa latch + └─ true → AWAITING_CONFIRMATION + ↓ + sim + ↓ + cancelar_pedido +``` + +`fail_open=false` é apropriado para operação sensível. Rejeição não vira `transaction_evidence`, porque a operação de negócio não ocorreu. + +Eventos esperados incluem: + +```text +IC.TRANSACTION_PREVALIDATION_REQUESTED +IC.TRANSACTION_PREVALIDATION_PASSED +IC.TRANSACTION_PREVALIDATION_REJECTED +IC.TRANSACTION_CONFIRMATION_REQUIRED +``` + + +# T13. Tuning — `Voice_Interruption_Replay` + +**Objetivo:** Short-circuit/replay para voz sem reexecutar o grafo indevidamente. + +## O que este cenário demonstra + +Esta melhoria move para `agent_framework.channels.interruption` comportamentos que antes costumavam ser implementados dentro de agentes de voz específicos. Evitar que `idle_nudge`, barge-in e fala residual pós-finalização reabram desnecessariamente o LangGraph principal, executem tools novamente ou confundam uma resposta de continuidade com uma nova intenção. 1. **Sessão encerrada**: replay da última fala terminal (ou fallback), preservando `terminal_status`. Não chama LangGraph, tools ou guardrails. 2. **Idle nudge**: replay da última fala real do assistente. Não chama LangGraph, tools ou guardrails. 3. **Fala não interrompível**: replay literal. 4. **Fala interrompível com contexto anterior**: executa `processing_interruption_classifier` pelo `LLMProvider` do framework. - `1`: reprocessa o complemento; - `0`, erro ou resposta inválida: replay fail-safe. + + +## Ordem framework-native + +1. sessão encerrada → replay terminal; +2. idle nudge → replay da última fala real; +3. fala não interrompível → replay literal; +4. fala interrompível com contexto → `processing_interruption_classifier`; +5. sem contexto suficiente → processa normalmente. + +Quando há short-circuit, o metadata informa `replay=true`, `framework_short_circuit=true` e evita LangGraph/tools/guardrails. No caso do classificador, somente o LLM leve de classificação pode ser chamado. + + +# T14. Tuning — `Workflow_Error_Recovery` + +**Objetivo:** Snapshot parcial e error_details estruturado em falhas de workflow. + +## O que este cenário demonstra + +O `WorkflowRuntime` preserva o último snapshot válido do LangGraph e, nesta versão, também expõe `error_details` estruturado quando a exceção externa oferece campos como `status_code`, `body` e `attempts`. Isso permite que o domínio diferencie erro técnico de erro de negócio sem acoplar o framework ao provider. O framework continua responsável por runtime/checkpoint/trace; o domínio interpreta apenas o contrato do seu provider. Exemplo conceitual: result = await runtime.arun("workflow_transacional", payload) if result.status == "FAILED": print(result.output) # nodes concluídos antes da falha print(result.trace) # trace parcial print(result.error) # mensagem humana/técnica + + +## Contrato de falha + +`WorkflowRunResult` preserva: + +- `output`: nós concluídos antes da falha; +- `trace`: caminho parcial; +- `error`: mensagem; +- `error_details`: quando disponível, `status_code`, `body`, `attempts`. + +Assim o framework continua genérico e o domínio interpreta detalhes do provider sem acoplar o engine à integração. + + +# Parte III — mapa de arquivos para manutenção + + +## Template base + +| Área | Arquivo | +|---|---| +| API / sessão / SSE / entrada | `templates/agent_template_backend/app/main.py` | +| State | `app/state.py` | +| Grafo | `app/workflows/agent_graph.py` | +| Runtime comum dos agentes | `app/agents/runtime.py` | +| Billing | `app/agents/billing_agent.py` | +| Produtos | `app/agents/product_agent.py` | +| Pedidos | `app/agents/orders_agent.py` | +| Suporte | `app/agents/support_agent.py` | +| Routing | `config/routing.yaml` | +| Agents registry | `config/agents.yaml` | +| Tools | `config/tools.yaml` | +| Policies | `config/tool_policies.yaml` | +| Parâmetros MCP | `config/mcp_parameter_mapping.yaml` | +| MCP servers | `config/mcp_servers.yaml` | +| Guardrails | `config/guardrails.yaml` | +| Judges | `config/judges.yaml` | +| Prompt policy | `config/prompt_policy.yaml` | +| Workflow devolução | `workflows/devolucao_pedido.v1.yaml` | +| Workflow active pointer | `workflows/devolucao_pedido.active.yaml` | +| Actions devolução | `app/workflow_actions/devolucao.py` | +| Renderers | `app/presentation/tool_renderers.py` | +| Observabilidade | `app/observability/telemetry_observer.py` | +| Runtime do framework | `libs/agent_framework/src/agent_framework/runtime/agent_runtime.py` | +| Router | `libs/agent_framework/src/agent_framework/routing/enterprise_router.py` | +| Multi-intent | `libs/agent_framework/src/agent_framework/routing/multi_intent.py` | +| Pending topics | `libs/agent_framework/src/agent_framework/routing/pending_topics.py` | +| Parâmetros/reconciliação | `libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py` | +| Workflow runtime | `libs/agent_framework/src/agent_framework/workflows/` | + +## Como criar uma nova regra sem hardcode no core + +1. Defina a intent em `config/routing.yaml`. +2. Aponte para um agente existente ou crie o agente em `app/agents/`. +3. Registre o agente no grafo somente se for novo. +4. Declare capabilities em `config/tools.yaml`. +5. Declare confirmação/pre-validation/workflow em `config/tool_policies.yaml`. +6. Configure aliases/extract/defaults em `config/mcp_parameter_mapping.yaml`. +7. Implemente a tool no MCP Server, não no router. +8. Se houver orquestração multi-etapas, crie workflow YAML e actions Python. +9. Acrescente guardrails/judges somente quando a regra for transversal/qualidade; não use guardrail como router. +10. Teste estado, coleta, confirmação, intent shift, retry, idempotência e groundedness. +11. Se a capability precisar de um comportamento avançado, consulte primeiro os cenários de `Tuning-Performance` antes de duplicar infraestrutura no agente. diff --git a/MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md b/MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md new file mode 100644 index 00000000..e707ee7e --- /dev/null +++ b/MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md @@ -0,0 +1,1884 @@ +# Detailed Rule Manual for `agent_template_backend` + +## Technical Preface — how the `agent_template_backend` decision engine works + +`agent_template_backend` is a **corporate reference template** for building agents on the Agent Framework OCI. Decision logic is not concentrated in one `if`, prompt, or router. Final behavior results from cooperation among declarative configuration, LangGraph state, transactional runtime, MCP Tool Router, RAG, memory, guardrails, judges, Output Supervisor, workflows, and persistence. + +A message may: + +- be sanitized/blocked before routing; +- belong to an already-open transaction; +- fill a pending parameter; +- confirm/reject an action; +- interrupt the previous operation through intent shift; +- continue with the current agent through route stickiness; +- contain multiple independent intents; +- resume a paused workflow; +- select one or more candidate tools; +- go through pre-validation; +- change its execution path because of policy; +- execute a tool directly or a deterministic workflow; +- use MCP as operational evidence; +- use RAG as documentary knowledge; +- use summarized/long-term memory as context; +- be reviewed by Output Supervisor, guardrails, and judges; +- persist state/evidence for the next turn. + +When diagnosing the template, the right question is not only “which intent was found?” but: + +> **What state was the session in, which mechanism had precedence, which intent/route won, which tool was selected, which parameters were resolved, which policy/pre-validation applied, what execution occurred, and which evidence supported the final response?** + +## P.1. Engine overview + +```mermaid +flowchart TD + U["Message / GatewayRequest"] --> IGR["Input Guardrails"] + IGR --> LTM["Load Long-Term Memory"] + LTM --> RT["EnterpriseRouter / Supervisor"] + RT --> CP["Conversation policy / state precedence"] + CP --> AG["Domain agent"] + AG --> TP["Tool policy + parameters"] + TP --> PV["Pre-validation when configured"] + PV --> CF["Confirmation when transactional"] + CF --> EX["Direct MCP or Workflow"] + EX --> RAG["RAG when needed"] + RAG --> CMP["Response composition"] + CMP --> OS["Output Supervisor"] + OS --> OGR["Output Guardrails"] + OGR --> J["Judges"] + J --> SR["Supervisor Review"] + SR --> MEM["Persistence / memory / checkpoint"] + MEM --> F["Response"] +``` + +Not every turn traverses every layer. A tracking query may finish quickly with MCP + renderer; a return may require collection, confirmation, and workflow execution. + +## P.2. Actual corporate graph in the template + +`app/workflows/agent_graph.py` builds a `FrameworkStateGraph(AgentState)` with the main nodes: + +```text +START + ↓ +input_guardrails + ↓ +load_long_term_memory + ↓ +routing_decision + ↓ +billing_agent | product_agent | orders_agent | support_agent + | handoff | human_handoff | end_session | supervisor_agent + ↓ +output_supervisor + ↓ +output_guardrails + ↓ +judge + ↓ +supervisor_review + ↓ +persist_long_term_memory + ↓ +persist + ↓ +END +``` + +The graph is the backbone; domain rules live in YAML, agents, MCP, and workflows. + +## P.3. Three state families + +### P.3.1. States declared in `routing.yaml` + +| State | Owning agent | +|---|---| +| `WAITING_BILLING_CONFIRMATION` | `billing_agent` | +| `WAITING_PRODUCT_CONFIRMATION` | `product_agent` | +| `WAITING_ORDER_CONFIRMATION` | `orders_agent` | +| `WAITING_SUPPORT_CONFIRMATION` | `support_agent` | +| `COLLECTING_BILLING_PARAMETERS` | `billing_agent` | +| `COLLECTING_PRODUCT_PARAMETERS` | `product_agent` | +| `COLLECTING_ORDER_PARAMETERS` | `orders_agent` | +| `COLLECTING_SUPPORT_PARAMETERS` | `support_agent` | + +They keep the next turn with the owning agent while parameters or confirmation are pending. + +### P.3.2. Canonical transactional runtime states + +The runtime uses states such as: + +```text +COLLECTING_PARAMETERS +AWAITING_CONFIRMATION +CONFIRMED +EXECUTING +WORKFLOW_PAUSED +TOOL_RESULT_CLARIFICATION +COMPLETED +FAILED +CANCELLED +BLOCKED +OUT_OF_SCOPE +``` + +These control parameters, confirmation, execution, and transaction termination. + +### P.3.3. Workflow-engine states + +A workflow has an independent execution identified by `execution_id`, with results such as: + +```text +PAUSED / WAITING_INPUT +COMPLETED +FAILED +``` + +The three groups are related, but they must not be treated as a single enum. + +## P.4. Conceptual transactional state machine + +```mermaid +stateDiagram-v2 + [*] --> COLLECTING_PARAMETERS: required fields missing + COLLECTING_PARAMETERS --> AWAITING_CONFIRMATION: complete parameters + validations OK + COLLECTING_PARAMETERS --> CANCELLED: intent shift / abandonment + + AWAITING_CONFIRMATION --> EXECUTING: positive confirmation + AWAITING_CONFIRMATION --> CANCELLED: negative confirmation + AWAITING_CONFIRMATION --> AWAITING_CONFIRMATION: inconclusive response + + EXECUTING --> COMPLETED: tool/workflow completed + EXECUTING --> WORKFLOW_PAUSED: workflow requests input + EXECUTING --> FAILED: technical error + EXECUTING --> BLOCKED: policy/guardrail + EXECUTING --> OUT_OF_SCOPE: domain rule rejects + + WORKFLOW_PAUSED --> EXECUTING: valid resume + WORKFLOW_PAUSED --> COMPLETED: workflow ends +``` + +## P.5. Routing + +`config/routing.yaml` is the declarative source for intents, priorities, agents, tools, keywords, and examples. + +The main `EnterpriseRouter` sequence is: + +```text +active state/transaction +→ deterministic matching +→ LLM router when enabled +→ fallback +``` + +Deterministic matching favors the best priority/specificity combination; **lower numeric `priority` values take precedence**. + +When `ENABLE_LLM_ROUTER=true`, the LLM receives the allowed catalog and classifies within it. The LLM must not invent new tools or agents. + +## P.6. Route stickiness + +`ENABLE_ROUTE_STICKINESS` enables a lightweight classifier that decides semantic continuity among: + +```text +CONTINUE +ROUTE +HUMAN_HANDOFF +END_SESSION +``` + +Relevant configuration: + +```text +ROUTE_STICKINESS_LLM_PROFILE +ROUTE_STICKINESS_CONFIDENCE_THRESHOLD +ROUTE_STICKINESS_HISTORY_TURNS +ROUTE_STICKINESS_MAX_TOKENS +``` + +`CONTINUE` keeps the active agent; `ROUTE` goes back to EnterpriseRouter. Stickiness does not authorize transactions and does not replace tool policy. + +## P.7. Intent shift + +During `COLLECTING_PARAMETERS` or `AWAITING_CONFIRMATION`, the framework protects the current transaction from accidental topic changes. An explicit change of subject may, however, cancel/clear the transactional latch and return the turn to normal routing. + +The current utterance also has precedence when filling pending fields. A response such as `PED-1001` while collecting `order_id` must not be reinterpreted as a new intent. + +## P.8. Parameter collection + +Parameter requirements are produced by the combination: + +```text +tools.yaml args_schema ++ tool_policies.yaml requires ++ mcp_parameter_mapping.yaml ++ canonical state data +``` + +Example: + +```text +cancelar_pedido +requires: [order_id] +``` + +Without `order_id`, the runtime enters `COLLECTING_PARAMETERS`, uses the tool schema/user prompt to request the field, and preserves agent ownership. + +## P.9. Temporal reconciliation + +The framework contains a temporal reconciler in `runtime/transaction_parameters.py`. It is used **after** the normal current-turn extraction attempt when required fields are still missing. + +Principles: + +- the current utterance is the newest source and has precedence; +- history resolves references but does not invent operational facts; +- fields may be preserved, resolved, cleared, or remain unresolved; +- ambiguity must remain unresolved; +- candidate results still pass domain validations/pre-validation. + +This allows coherent cross-turn relationships without converting conversational history into backend evidence. + +## P.10. Contextual reentry + +`EnterpriseRouter` and the runtime support `contextual_reentry`: a short turn may reenter a rule when the immediately preceding context constrains its meaning. + +The runtime keeps the current utterance separate from `relevant_conversation_context`; that context is interpretive and does not replace tools/MCP as operational authority. + +## P.11. Multi-intent and `pending_topics` + +`MultiIntentPlanner` can split independent goals: + +```text +"track the order and then cancel it" +``` + +into distinct topics without decomposing internal parameters of one action. + +When one action must finish before the next, remaining goals may be persisted in `pending_topics`. `drain_pending_topics()` appears directly in the template graph. + +## P.12. Tool policies + +`tools.yaml` describes capabilities. `tool_policies.yaml` describes **how** a sensitive capability may execute. + +In the base template: + +- `cancelar_pedido`: transactional + confirmation + `order_id` + pre-validation; +- `solicitar_troca`: transactional + confirmation; +- `solicitar_devolucao`: transactional + confirmation + `order_id/reason` + workflow. + +This prevents sensitive execution rules from being hardcoded inside agents. + +## P.13. Pre-validation + +Pre-validation occurs after required parameters are complete and before confirmation. + +Flow: + +```text +complete parameters +→ side-effect-free MCP validator +→ eligible? + ├─ false: OUT_OF_SCOPE / terminate latch + └─ true: AWAITING_CONFIRMATION +``` + +In the template, `cancelar_pedido` uses `validar_cancelamento_pedido` with `fail_open=false`. + +## P.14. Transaction confirmation + +Tools with `require_confirmation=true` do not execute automatically. + +The framework first attempts to interpret explicit confirmations deterministically and can use semantic fallback when necessary. A positive response promotes the transaction to execution; a negative one cancels it; an inconclusive response keeps the transaction active. + +## P.15. Transactional workflow + +A policy may define: + +```yaml +execution: + mode: workflow + workflow: devolucao_pedido + version: active +``` + +After confirmation, the logical tool is executed by `WorkflowToolExecutor`, which loads the versioned YAML and executes the deterministic graph. The domain declares nodes/actions; the framework owns runtime, checkpointing, and tracing. + +## P.16. Pause/Resume + +The workflow engine supports pause nodes, `expected_input`, `resume_from`, and resume by `execution_id`. The base return workflow does not pause; the capability is demonstrated separately in `Tuning-Performance/Pause_Resume_Workflow`. + +An important rule is that pause compilation must not automatically rerun a side-effecting action when the user answers. + +## P.17. Guardrails + +In the global template: + +**Input** +- `MSK` +- `VLOOP` + +**Output** +- `REVPREC` +- `PINJ` +- `DLEX_OUT` + +Pipelines can be enabled/disabled through `.env`. Guardrails evaluate permission/safety/operational coherence; they must not replace routing or domain rules. + +## P.18. Output Supervisor + +Output Supervisor sits between the agent and output guardrails. It may review the candidate response, apply retry/sanitize/block/handover policies, and prevent premature claims about effects that are not supported by operational results. + +`OUTPUT_SUPERVISOR_MAX_RETRIES` controls the regeneration limit. + +## P.19. Judges + +`config/judges.yaml` enables: + +| Judge | Threshold/policy | +|---|---| +| `response_quality` | `0.7` | +| `groundedness` | `0.6` | +| `sentiment` | does not fail on negative | +| `tone` | `fail_closed=true` | + +Global configuration: + +```text +enabled=true +fail_closed=true +sample_rate=0.25 +always_run_for_transactional=true +``` + +Transactional responses are therefore evaluated even when the general sampling rate would skip them. + +## P.20. MCP, operational evidence, and renderers + +The template separates three responsibilities: + +```text +routing → which capabilities belong to the intent +tool runtime → which capability should actually execute +MCP server → operational fact / integration +``` + +Some tools use `response.mode: renderer`, such as `telecom.invoice`, `telecom.plan`, `retail.order`, and `retail.delivery`. In those cases, MCP results may be presented deterministically without requiring LLM composition. + +## P.21. RAG + +`AgentRuntimeMixin._retrieve_rag_context()` uses the framework's official RAG path. RAG is for documentary knowledge; MCP is for operational state. + +The runtime also supports **Domain-Requested RAG**: a tool may return `requires_rag=true` and `rag_queries`, forcing retrieval even when MCP would normally be considered sufficient. + +## P.22. Domain-requested LLM composition + +A tool/workflow may return: + +```json +{ + "requires_llm_composition": true, + "response_instruction": "Explain using only workflow evidence." +} +``` + +The domain does not create its own LLM gateway. AgentRuntime uses the official provider, preserving tracing, cost controls, profiles, and guardrails. + +## P.23. Memory + +The template provides: + +- ConversationSummaryMemory; +- recent memory; +- optional Long-Term Memory; +- operational checkpoint/persistence. + +Memory helps interpret context, preferences, and continuity. **It does not replace Transaction Evidence or MCP** for asserting that an operation occurred. + +## P.24. Transaction Evidence + +Completed transaction results can be persisted as structured operational evidence and correlated with future turns. This prevents later responses from mentioning a previous protocol/cancellation without providing the same evidence to judges/groundedness. + +## P.25. Idempotency + +Transactional state, checkpointing, and `execution_id` also protect against retry/replay/reexecution. A repeated confirmation must not create two transactions just because the channel resent a message. + +## P.26. Voice interruption and replay + +The framework contains channel short-circuits for idle nudges, non-interruptible speech, post-finalization, and barge-in. In several cases it simply replays the last utterance without reopening LangGraph, tools, or guardrails; where needed it uses the `processing_interruption_classifier` profile. + +## P.27. Workflow error and recovery + +`WorkflowRuntime` preserves the last valid snapshot and exposes `error`, partial trace, and `error_details` when the provider supplies `status_code`, `body`, and `attempts`. The domain can distinguish technical failure from business-rule rejection without coupling the framework to the provider. + +## P.28. Observability + +The template emits telemetry to: + +- Langfuse; +- OpenTelemetry; +- corporate analytics/observer; +- IC events; +- NOC; +- GRL; +- workflow; +- guardrails; +- judges. + +Telemetry should allow reconstruction of: + +```text +input → route → agent → tool → policy → workflow → output controls → persistence +``` + +## P.29. `agents.yaml`: logical application/agent isolation + +`config/agents.yaml` registers two reference `agent_id` values: + +- `telecom_contas`; +- `retail_orders`. + +Each can point to prompt policy, routing, guardrails, judges, MCP servers, and tools, plus `metadata.system_prefix`. The goal is to prevent policies, memory/checkpoints, or decisions from leaking across logical identities. + +## P.30. Troubleshooting golden rule + +Always investigate in this order: + +```text +1. Which agent_id is active? +2. What was the state/checkpoint? +3. Was there an active transaction or paused workflow? +4. Which route/stickiness decision occurred? +5. Which intent won and why? +6. Which mcp_tools did the intent authorize? +7. Which tool was actually selected? +8. Which parameters were resolved? +9. Did temporal reconciliation occur? +10. Did pre-validation occur? +11. Was confirmation required? +12. Direct tool or workflow? +13. Which MCP/workflow result was produced? +14. Did the response use renderer, RAG, or LLM? +15. Did Output Supervisor/guardrails change anything? +16. Did judges approve it? +17. Was state/evidence persisted? +``` + +This is the engine on which the template's five rules are built. + +## 1. How to read this manual + +This manual follows the same model as the Accounts Agent manual. Each rule is explained at six levels: + +1. **Rule/intent** — what it means and its boundary. +2. **Routing** — `routing.yaml` attribute by attribute and how the intent is discovered. +3. **Tools** — operation, arguments, aliases, extraction, policy, confirmation, pre-validation, and return. +4. **Workflow** — when present, nodes, actions, conditions, and termination. +5. **Binding** — Python/YAML/`.env` files involved. +6. **Diagnostics** — why a specific decision occurs. + +A separate section then covers `Tuning-Performance`. + +## 2. Agent catalog and `agent_id` isolation + +| agent_id | Name | Domain | Specific configuration | +|---|---|---|---| +| `telecom_contas` | Agente Telecom Contas | `telecom` | prompt `./config/agents/telecom_contas/prompt_policy.yaml`; guardrails `./config/agents/telecom_contas/guardrails.yaml`; judges `./config/agents/telecom_contas/judges.yaml` | +| `retail_orders` | Agente Retail Pedidos | `retail` | prompt `./config/agents/retail_orders/prompt_policy.yaml`; guardrails `./config/agents/retail_orders/guardrails.yaml`; judges `./config/agents/retail_orders/judges.yaml` | + +The `default_agent_id` is `telecom_contas`. Each entry's `system_prefix` guides the runtime so that policies, memory/checkpoints, or decisions from another `agent_id` are not mixed. + +## 3. Component binding + + +```mermaid +flowchart LR + U["GatewayRequest / message"] --> G["app/main.py"] + G --> WF["app/workflows/agent_graph.py"] + WF --> R["config/routing.yaml"] + R --> A["app/agents/*_agent.py"] + A --> RT["AgentRuntimeMixin"] + RT --> T["config/tools.yaml"] + T --> P["config/tool_policies.yaml"] + T --> M["config/mcp_parameter_mapping.yaml"] + P --> MCP["MCP Tool Router / Gateway"] + M --> MCP + MCP --> S["mcp/servers/telecom or retail"] + P --> DW["workflows/*.yaml when execution=workflow"] + DW --> WA["app/workflow_actions/*.py"] + A --> RAG["RAG / memory / LLM"] + A --> OS["Output Supervisor"] + OS --> GR["Guardrails"] + GR --> J["Judges"] + J --> PS["Persistence / checkpoint / evidence"] +``` + +## 4. Rule inventory + +| Intent | Rule | Agent | Priority | Tools | +|---|---|---|---:|---| +| `billing_invoice_explanation` | Billing / Invoice Explanation | `billing_agent` | 10 | `consultar_fatura`, `consultar_pagamentos` | +| `product_services_information` | Products, Plan, Services, and VAS | `product_agent` | 20 | `consultar_plano`, `listar_servicos` | +| `retail_order_cancel` | Order Cancellation | `orders_agent` | 20 | `consultar_pedido`, `cancelar_pedido` | +| `retail_order_tracking` | Order Query and Tracking | `orders_agent` | 30 | `consultar_pedido`, `consultar_entrega` | +| `retail_support_exchange_return` | Exchange, Return, Warranty, and Retail Support | `support_agent` | 25 | `consultar_pedido`, `solicitar_troca`, `solicitar_devolucao` | + +# 5. Rule — Billing / Invoice Explanation + +**Intent:** `billing_invoice_explanation` +**Domain:** `telecom` +**Agent:** `billing_agent` +**Priority:** `10` + +## What this rule means + +Questions about invoices, billing, due dates, duplicate copies, disputes, and amounts. + +### Rule boundary + +This is an informational/operational billing rule. It queries evidence; by itself it does not authorize a transactional financial action. + +## `routing.yaml` attribute by attribute + +| Attribute | Value in this rule | Role in the engine | +|---|---|---| +| `name` | billing_invoice_explanation | Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities. | +| `domain` | telecom | Logical domain. It helps constrain context, agents, and catalog interpretation. | +| `agent` | billing_agent | Agent that receives the turn when this intent wins. | +| `description` | Questions about invoices, billing, due dates, duplicate copies, disputes, and amounts. | Semantic definition used by maintainers and by the LLM fallback. | +| `priority` | 10 | Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence. | +| `mcp_tools` | consultar_fatura
consultar_pagamentos | Capabilities initially authorized/expected for this intent. | +| `keywords` | fatura
conta
cobrança
boleto
vencimento
segunda via
contestar
valor alto
invoice | Deterministic triggers evaluated before semantic fallback. | +| `examples` | Minha fatura veio alta.
Quero entender uma cobrança.
Preciso da segunda via da conta. | Examples offered to the LLM classifier; they are neither regexes nor executable rules. | + +## How this intent is found + +1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request. +2. In deterministic matching, this intent offers keywords such as `fatura`, `conta`, `cobrança`, `boleto`, `vencimento`, `segunda via`, `contestar`, `valor alto`, `invoice`. +3. In collisions, `priority=10` participates in tie-breaking; lower values take precedence. +4. If LLM fallback is used, the description and examples such as `Minha fatura veio alta.`, `Quero entender uma cobrança.`, `Preciso da segunda via da conta.` help classification. +5. When the intent wins, state receives the route/agent and initial tool set `['consultar_fatura', 'consultar_pagamentos']`. + +## Owning agent and Python behavior + +File: `app/agents/billing_agent.py`. +Its `run()` follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble `messages`, call the LLM, and return a state patch. +This pattern comes from `app/agents/runtime.py::AgentRuntimeMixin`, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic. + +## Tools in this rule + +### Tool `consultar_fatura` + +**What it does:** Queries summarized invoice data by msisdn/invoice_id. + +| Property | Value | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `fatura`, `conta`, `boleto` | +| presentation | `mode=renderer`; renderer `telecom.invoice` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `msisdn` | `string` | canonical context `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | +| `invoice_id` | `string` | canonical context `contract_key` | Identificador da fatura que o cliente deseja consultar. | + +**MCP aliases:** `customer_key → msisdn`, `contract_key → invoice_id`, `interaction_key → ura_call_id`, `session_key → session_id`. + +**Conversational extraction:** +- `mes_referencia`: strategy `month_name_pt`; Extrair mês citado na mensagem. janeiro=1, fevereiro=2, março=3, abril=4, maio=5, junho=6, julho=7, agosto=8, setembro=9, outubro=10, novembro=11, dezembro=12. + + +**What it returns:** In the sample MCP it returns `invoice_id`, `msisdn`, `valor_total`, `vencimento`, `status`, and an `itens` list; the final envelope is `{ok, result, metadata}`. + +### Tool `consultar_pagamentos` + +**What it does:** Queries the customer's payment history. + +| Property | Value | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `pagamento`, `pagamentos` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `msisdn` | `string` | canonical context `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | + +**MCP aliases:** `customer_key → msisdn`, `interaction_key → ura_call_id`, `session_key → session_id`. + +**What it returns:** Returns `msisdn` and `pagamentos[]`, with date, amount, and payment status from the mock. + +## Workflow + +This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation. + +## Binding between YAML and Python + +- `config/routing.yaml` → finds `billing_invoice_explanation` and selects `billing_agent`. +- `config/tools.yaml` → describes arguments, MCP server, selection keywords, and renderer. +- `config/tool_policies.yaml` → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow. +- `config/mcp_parameter_mapping.yaml` → maps canonical keys and extracts fields from the message. +- `app/agents/billing_agent.py` → uses `AgentRuntimeMixin` to execute capabilities without duplicating infrastructure. +- `app/workflows/agent_graph.py` → connects the agent to the corporate graph and output controls. +- `mcp/servers/telecom_mcp_server/main.py` → mock/contract implementation for tool `consultar_fatura`. +- `mcp/servers/telecom_mcp_server/main.py` → mock/contract implementation for tool `consultar_pagamentos`. + +### Relevant `.env` and configuration + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` and `ENABLE_LLM_ROUTER` control the routing catalog/semantic fallback. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE`, and `END_SESSION_MESSAGE` control continuity/session behavior. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH`, and `MCP_TOOL_TIMEOUT_SECONDS` control tools. +- `MCP_GATEWAY_ENABLED` chooses between a dedicated MCP Gateway and direct access to configured MCP servers. +- Logical server `telecom` is resolved by `config/mcp_servers.yaml`; in the base template it points to `http://localhost:8100/mcp` using the legacy HTTP contract. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, and `ENABLE_OUTPUT_SUPERVISOR` affect the cycle before/after the agent. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` and `ENABLE_LONG_TERM_MEMORY` may enrich prompt/context without replacing MCP evidence. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K`, and `KBDB_*` control documentary retrieval when used. + + +### Special diagnostic — why two tools appear under the same intent + +The billing intent authorizes `consultar_fatura` and `consultar_pagamentos` because billing questions may require invoice evidence or payment-history evidence. This **does not mean both tools must run on every turn**. + +`tools.yaml.selection_keywords`, current text, available arguments, and runtime state help select the appropriate capability. “I need a duplicate invoice / what is my invoice amount?” should favor `consultar_fatura`; a specific payment question should favor `consultar_pagamentos`. + +# 6. Rule — Products, Plan, Services, and VAS + +**Intent:** `product_services_information` +**Domain:** `telecom` +**Agent:** `product_agent` +**Priority:** `20` + +## What this rule means + +Questions about plans, packages, products, services, VAS, internet, roaming, and benefits. + +### Rule boundary + +It is used to discover plans/services/VAS and explain attributes. A product question must not be converted into a proactive offer or a transactional action. + +## `routing.yaml` attribute by attribute + +| Attribute | Value in this rule | Role in the engine | +|---|---|---| +| `name` | product_services_information | Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities. | +| `domain` | telecom | Logical domain. It helps constrain context, agents, and catalog interpretation. | +| `agent` | product_agent | Agent that receives the turn when this intent wins. | +| `description` | Questions about plans, packages, products, services, VAS, internet, roaming, and benefits. | Semantic definition used by maintainers and by the LLM fallback. | +| `priority` | 20 | Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence. | +| `mcp_tools` | consultar_plano
listar_servicos | Capabilities initially authorized/expected for this intent. | +| `keywords` | plano
serviço
pacote
internet
roaming
vas
benefício
assinatura | Deterministic triggers evaluated before semantic fallback. | +| `examples` | Quais serviços estão ativos no meu plano?
Quero saber sobre meu pacote de internet.
Tenho roaming internacional? | Examples offered to the LLM classifier; they are neither regexes nor executable rules. | + +## How this intent is found + +1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request. +2. In deterministic matching, this intent offers keywords such as `plano`, `serviço`, `pacote`, `internet`, `roaming`, `vas`, `benefício`, `assinatura`. +3. In collisions, `priority=20` participates in tie-breaking; lower values take precedence. +4. If LLM fallback is used, the description and examples such as `Quais serviços estão ativos no meu plano?`, `Quero saber sobre meu pacote de internet.`, `Tenho roaming internacional?` help classification. +5. When the intent wins, state receives the route/agent and initial tool set `['consultar_plano', 'listar_servicos']`. + +## Owning agent and Python behavior + +File: `app/agents/product_agent.py`. +Its `run()` follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble `messages`, call the LLM, and return a state patch. +This pattern comes from `app/agents/runtime.py::AgentRuntimeMixin`, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic. + +## Tools in this rule + +### Tool `consultar_plano` + +**What it does:** Queries the active plan and commercial attributes. + +| Property | Value | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `plano` | +| presentation | `mode=renderer`; renderer `telecom.plan` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `msisdn` | `string` | canonical context `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | +| `asset_id` | `string` | canonical context `resource_key`; canonical context `contract_key` | Identificador do plano ou ativo comercial associado ao cliente. | + +**MCP aliases:** `customer_key → msisdn`, `resource_key → asset_id`, `contract_key → asset_id`, `session_key → session_id`. + +**What it returns:** Returns `msisdn`, `asset_id`, plan name, internet allowance, roaming attribute, and status. + +### Tool `listar_servicos` + +**What it does:** Lists active services and additional VAS. + +| Property | Value | +|---|---| +| MCP server | `telecom` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `serviços`, `servicos`, `vas` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `msisdn` | `string` | canonical context `customer_key` | Número da linha do cliente (MSISDN) usado para consultar informações de telecom. | + +**MCP aliases:** `customer_key → msisdn`, `session_key → session_id`. + +**What it returns:** Returns `msisdn` and `servicos[]` containing name, status, and amount. + +## Workflow + +This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation. + +## Binding between YAML and Python + +- `config/routing.yaml` → finds `product_services_information` and selects `product_agent`. +- `config/tools.yaml` → describes arguments, MCP server, selection keywords, and renderer. +- `config/tool_policies.yaml` → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow. +- `config/mcp_parameter_mapping.yaml` → maps canonical keys and extracts fields from the message. +- `app/agents/product_agent.py` → uses `AgentRuntimeMixin` to execute capabilities without duplicating infrastructure. +- `app/workflows/agent_graph.py` → connects the agent to the corporate graph and output controls. +- `mcp/servers/telecom_mcp_server/main.py` → mock/contract implementation for tool `consultar_plano`. +- `mcp/servers/telecom_mcp_server/main.py` → mock/contract implementation for tool `listar_servicos`. + +### Relevant `.env` and configuration + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` and `ENABLE_LLM_ROUTER` control the routing catalog/semantic fallback. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE`, and `END_SESSION_MESSAGE` control continuity/session behavior. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH`, and `MCP_TOOL_TIMEOUT_SECONDS` control tools. +- `MCP_GATEWAY_ENABLED` chooses between a dedicated MCP Gateway and direct access to configured MCP servers. +- Logical server `telecom` is resolved by `config/mcp_servers.yaml`; in the base template it points to `http://localhost:8100/mcp` using the legacy HTTP contract. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, and `ENABLE_OUTPUT_SUPERVISOR` affect the cycle before/after the agent. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` and `ENABLE_LONG_TERM_MEMORY` may enrich prompt/context without replacing MCP evidence. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K`, and `KBDB_*` control documentary retrieval when used. + +# 7. Rule — Order Cancellation + +**Intent:** `retail_order_cancel` +**Domain:** `retail` +**Agent:** `orders_agent` +**Priority:** `20` + +## What this rule means + +Explicit cancellation of an order or purchase. + +### Rule boundary + +The intent represents the customer's desire to cancel. Execution still depends on `order_id`, pre-validation, and confirmation; an ineligible order is blocked before confirmation. + +## `routing.yaml` attribute by attribute + +| Attribute | Value in this rule | Role in the engine | +|---|---|---| +| `name` | retail_order_cancel | Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities. | +| `domain` | retail | Logical domain. It helps constrain context, agents, and catalog interpretation. | +| `agent` | orders_agent | Agent that receives the turn when this intent wins. | +| `description` | Explicit cancellation of an order or purchase. | Semantic definition used by maintainers and by the LLM fallback. | +| `priority` | 20 | Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence. | +| `mcp_tools` | consultar_pedido
cancelar_pedido | Capabilities initially authorized/expected for this intent. | +| `keywords` | cancelar pedido
cancelamento do pedido
cancelar a compra
cancelar compra | Deterministic triggers evaluated before semantic fallback. | +| `examples` | Quero cancelar meu pedido.
Cancele o pedido.
Quero cancelar a compra. | Examples offered to the LLM classifier; they are neither regexes nor executable rules. | + +## How this intent is found + +1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request. +2. In deterministic matching, this intent offers keywords such as `cancelar pedido`, `cancelamento do pedido`, `cancelar a compra`, `cancelar compra`. +3. In collisions, `priority=20` participates in tie-breaking; lower values take precedence. +4. If LLM fallback is used, the description and examples such as `Quero cancelar meu pedido.`, `Cancele o pedido.`, `Quero cancelar a compra.` help classification. +5. When the intent wins, state receives the route/agent and initial tool set `['consultar_pedido', 'cancelar_pedido']`. + +## Owning agent and Python behavior + +File: `app/agents/orders_agent.py`. +Its `run()` follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble `messages`, call the LLM, and return a state patch. +This pattern comes from `app/agents/runtime.py::AgentRuntimeMixin`, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic. + +## Tools in this rule + +### Tool `consultar_pedido` + +**What it does:** Queries a retail order by order_id/customer_id. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| presentation | `mode=renderer`; renderer `retail.order` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | canonical context `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**MCP aliases:** `customer_key → customer_id`, `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns `order_id`, `customer_id`, `status`, `valor_total`, and `itens[]`. In the mock, `123` and `PED-ENTREGUE` are `ENTREGUE`; other orders are `EM_TRANSPORTE`. + +### Tool `cancelar_pedido` + +**What it does:** Simulates cancellation of a retail order. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `transactional` | +| confirmation required | `true` | +| requires | `order_id` | +| selection_keywords | `cancelar pedido`, `cancelamento do pedido`, `cancelar compra`, `cancelar a compra` | +| pre-validation | `validar_cancelamento_pedido`; `fail_open=false` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido que o cliente deseja cancelar. | + +**MCP aliases:** `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns a protocol, `order_id`, `CANCELAMENTO_SOLICITADO` status, and guidance. Because it is transactional, it must only execute after parameters, pre-validation, and confirmation. + +### Internal tool used by the policy + +### Tool `validar_cancelamento_pedido` + +**What it does:** Pre-validates order cancellation without executing transactional side effects. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `internal` | +| confirmation required | `false` | +| requires | `order_id` | +| selection_keywords | — | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | canonical context `resource_key` | Identificador do pedido a ser pre-validado para cancelamento. | +| `target_tool` | `string` | state/context, parameter collection, or explicit call | Nome interno da operação transacional que será pre-validada; normalmente preenchido pelo runtime e não solicitado ao usuário. | + +**MCP aliases:** `resource_key → order_id`. + +**What it returns:** Returns `eligible`, `status`, `order_id`, a `reason` when blocked, and `side_effect_free` metadata. It is an internal/read-only tool used before confirmation. + +## Workflow + +This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation. + +## Binding between YAML and Python + +- `config/routing.yaml` → finds `retail_order_cancel` and selects `orders_agent`. +- `config/tools.yaml` → describes arguments, MCP server, selection keywords, and renderer. +- `config/tool_policies.yaml` → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow. +- `config/mcp_parameter_mapping.yaml` → maps canonical keys and extracts fields from the message. +- `app/agents/orders_agent.py` → uses `AgentRuntimeMixin` to execute capabilities without duplicating infrastructure. +- `app/workflows/agent_graph.py` → connects the agent to the corporate graph and output controls. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `cancelar_pedido`. + +### Relevant `.env` and configuration + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` and `ENABLE_LLM_ROUTER` control the routing catalog/semantic fallback. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE`, and `END_SESSION_MESSAGE` control continuity/session behavior. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH`, and `MCP_TOOL_TIMEOUT_SECONDS` control tools. +- `MCP_GATEWAY_ENABLED` chooses between a dedicated MCP Gateway and direct access to configured MCP servers. +- Logical server `retail` is resolved by `config/mcp_servers.yaml`; in the base template it points to `http://localhost:8200/mcp` using the legacy HTTP contract. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, and `ENABLE_OUTPUT_SUPERVISOR` affect the cycle before/after the agent. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` and `ENABLE_LONG_TERM_MEMORY` may enrich prompt/context without replacing MCP evidence. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K`, and `KBDB_*` control documentary retrieval when used. + + +### Special diagnostic — why `PED-ENTREGUE` never reaches confirmation + +Intent `retail_order_cancel` represents the **customer's objective**: cancel an order. After routing, the `cancelar_pedido` policy requires `order_id`, calls pre-validation tool `validar_cancelamento_pedido`, and only allows `AWAITING_CONFIRMATION` when the validator returns `eligible=true`. + +In the sample MCP: + +```text +PED-1001 +→ validar_cancelamento_pedido +→ eligible=true +→ AWAITING_CONFIRMATION +→ "yes" +→ cancelar_pedido +→ protocol CANCEL-2026-001 +``` + +For: + +```text +PED-ENTREGUE +→ validar_cancelamento_pedido +→ eligible=false / NOT_ELIGIBLE +→ OUT_OF_SCOPE +→ no confirmation question +→ cancelar_pedido does not execute +``` + +This illustrates the architectural rule: **intent is not operational authorization**. Intent expresses what the customer wants; domain pre-validation determines whether the operation may proceed. + +# 8. Rule — Order Query and Tracking + +**Intent:** `retail_order_tracking` +**Domain:** `retail` +**Agent:** `orders_agent` +**Priority:** `30` + +## What this rule means + +Order, delivery, tracking, delay, and purchase-status queries. + +### Rule boundary + +This is read-only: it queries order/delivery state and must not modify the order. + +## `routing.yaml` attribute by attribute + +| Attribute | Value in this rule | Role in the engine | +|---|---|---| +| `name` | retail_order_tracking | Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities. | +| `domain` | retail | Logical domain. It helps constrain context, agents, and catalog interpretation. | +| `agent` | orders_agent | Agent that receives the turn when this intent wins. | +| `description` | Order, delivery, tracking, delay, and purchase-status queries. | Semantic definition used by maintainers and by the LLM fallback. | +| `priority` | 30 | Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence. | +| `mcp_tools` | consultar_pedido
consultar_entrega | Capabilities initially authorized/expected for this intent. | +| `keywords` | pedido
entrega
rastreio
rastreamento
encomenda
compra
atraso
correios | Deterministic triggers evaluated before semantic fallback. | +| `examples` | Meu pedido não chegou.
Quero rastrear minha entrega.
Qual é o status da minha compra? | Examples offered to the LLM classifier; they are neither regexes nor executable rules. | + +## How this intent is found + +1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request. +2. In deterministic matching, this intent offers keywords such as `pedido`, `entrega`, `rastreio`, `rastreamento`, `encomenda`, `compra`, `atraso`, `correios`. +3. In collisions, `priority=30` participates in tie-breaking; lower values take precedence. +4. If LLM fallback is used, the description and examples such as `Meu pedido não chegou.`, `Quero rastrear minha entrega.`, `Qual é o status da minha compra?` help classification. +5. When the intent wins, state receives the route/agent and initial tool set `['consultar_pedido', 'consultar_entrega']`. + +## Owning agent and Python behavior + +File: `app/agents/orders_agent.py`. +Its `run()` follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble `messages`, call the LLM, and return a state patch. +This pattern comes from `app/agents/runtime.py::AgentRuntimeMixin`, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic. + +## Tools in this rule + +### Tool `consultar_pedido` + +**What it does:** Queries a retail order by order_id/customer_id. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| presentation | `mode=renderer`; renderer `retail.order` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | canonical context `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**MCP aliases:** `customer_key → customer_id`, `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns `order_id`, `customer_id`, `status`, `valor_total`, and `itens[]`. In the mock, `123` and `PED-ENTREGUE` are `ENTREGUE`; other orders are `EM_TRANSPORTE`. + +### Tool `consultar_entrega` + +**What it does:** Queries delivery and tracking data for an order. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `entrega`, `rastreio`, `rastreamento`, `transportadora`, `previsão` | +| presentation | `mode=renderer`; renderer `retail.delivery` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido cuja entrega ou rastreamento será consultado. | + +**MCP aliases:** `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns `order_id`, carrier, tracking code, forecast, and movement events. + +## Workflow + +This rule does not require a dedicated declarative workflow in the base template. Execution occurs through MCP/the standard runtime; transactional states may still exist for parameter collection and confirmation. + +## Binding between YAML and Python + +- `config/routing.yaml` → finds `retail_order_tracking` and selects `orders_agent`. +- `config/tools.yaml` → describes arguments, MCP server, selection keywords, and renderer. +- `config/tool_policies.yaml` → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow. +- `config/mcp_parameter_mapping.yaml` → maps canonical keys and extracts fields from the message. +- `app/agents/orders_agent.py` → uses `AgentRuntimeMixin` to execute capabilities without duplicating infrastructure. +- `app/workflows/agent_graph.py` → connects the agent to the corporate graph and output controls. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `consultar_entrega`. + +### Relevant `.env` and configuration + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` and `ENABLE_LLM_ROUTER` control the routing catalog/semantic fallback. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE`, and `END_SESSION_MESSAGE` control continuity/session behavior. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH`, and `MCP_TOOL_TIMEOUT_SECONDS` control tools. +- `MCP_GATEWAY_ENABLED` chooses between a dedicated MCP Gateway and direct access to configured MCP servers. +- Logical server `retail` is resolved by `config/mcp_servers.yaml`; in the base template it points to `http://localhost:8200/mcp` using the legacy HTTP contract. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, and `ENABLE_OUTPUT_SUPERVISOR` affect the cycle before/after the agent. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` and `ENABLE_LONG_TERM_MEMORY` may enrich prompt/context without replacing MCP evidence. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K`, and `KBDB_*` control documentary retrieval when used. + +# 9. Rule — Exchange, Return, Warranty, and Retail Support + +**Intent:** `retail_support_exchange_return` +**Domain:** `retail` +**Agent:** `support_agent` +**Priority:** `25` + +## What this rule means + +Support, exchange, return, warranty, and product-problem requests. + +### Rule boundary + +It groups post-sale support. The intent may select exchange or return as the specific tool; transactional actions still require confirmation. + +## `routing.yaml` attribute by attribute + +| Attribute | Value in this rule | Role in the engine | +|---|---|---| +| `name` | retail_support_exchange_return | Stable intent identifier. It is stored in routing/telemetry state and links the decision to declared capabilities. | +| `domain` | retail | Logical domain. It helps constrain context, agents, and catalog interpretation. | +| `agent` | support_agent | Agent that receives the turn when this intent wins. | +| `description` | Support, exchange, return, warranty, and product-problem requests. | Semantic definition used by maintainers and by the LLM fallback. | +| `priority` | 25 | Tie-breaker among competing intents. In EnterpriseRouter, lower numeric values take precedence. | +| `mcp_tools` | consultar_pedido
solicitar_troca
solicitar_devolucao | Capabilities initially authorized/expected for this intent. | +| `keywords` | solicitar devolução
devolver pedido
solicitar troca
troca
devolução
devolver
garantia
defeito
produto quebrado
suporte
arrependimento | Deterministic triggers evaluated before semantic fallback. | +| `examples` | Quero trocar um produto.
Meu produto veio com defeito.
Como faço uma devolução? | Examples offered to the LLM classifier; they are neither regexes nor executable rules. | + +## How this intent is found + +1. EnterpriseRouter checks active state/transaction before treating the utterance as a new request. +2. In deterministic matching, this intent offers keywords such as `solicitar devolução`, `devolver pedido`, `solicitar troca`, `troca`, `devolução`, `devolver`, `garantia`, `defeito`, `produto quebrado`, `suporte`. +3. In collisions, `priority=25` participates in tie-breaking; lower values take precedence. +4. If LLM fallback is used, the description and examples such as `Quero trocar um produto.`, `Meu produto veio com defeito.`, `Como faço uma devolução?` help classification. +5. When the intent wins, state receives the route/agent and initial tool set `['consultar_pedido', 'solicitar_troca', 'solicitar_devolucao']`. + +## Owning agent and Python behavior + +File: `app/agents/support_agent.py`. +Its `run()` follows a common pattern: emit start IC, collect MCP context, check transactional clarification/confirmation messages, try a direct MCP/renderer answer, retrieve RAG when necessary, prepare memory, assemble `messages`, call the LLM, and return a state patch. +This pattern comes from `app/agents/runtime.py::AgentRuntimeMixin`, preventing each agent from reimplementing MCP, RAG, cache, memory, IC, and transactional logic. + +## Tools in this rule + +### Tool `consultar_pedido` + +**What it does:** Queries a retail order by order_id/customer_id. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `read_only` | +| confirmation required | `false` | +| requires | — | +| selection_keywords | `consultar pedido`, `status do pedido`, `pedido` | +| presentation | `mode=renderer`; renderer `retail.order` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido que o cliente deseja consultar. | +| `customer_id` | `string` | canonical context `customer_key` | Identificador do cliente associado ao pedido de varejo. | + +**MCP aliases:** `customer_key → customer_id`, `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns `order_id`, `customer_id`, `status`, `valor_total`, and `itens[]`. In the mock, `123` and `PED-ENTREGUE` are `ENTREGUE`; other orders are `EM_TRANSPORTE`. + +### Tool `solicitar_troca` + +**What it does:** Simulates opening an exchange request. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `transactional` | +| confirmation required | `true` | +| requires | `order_id`, `reason` | +| selection_keywords | `solicitar troca`, `trocar`, `troca`, `defeito`, `quebrado` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido para o qual o cliente deseja solicitar troca. | +| `reason` | `string` | default `Solicitação aberta pelo atendimento conversacional.` | Motivo informado pelo cliente para solicitar a troca do pedido. | + +**MCP aliases:** `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** Returns a protocol, `order_id`, `ABERTO` status, and guidance for shipment/continuation of the exchange. + +### Tool `solicitar_devolucao` + +**What it does:** Simulates opening a return request. + +| Property | Value | +|---|---| +| MCP server | `retail` | +| enabled | `True` | +| type/operation | `transactional` | +| confirmation required | `true` | +| requires | `order_id`, `reason` | +| selection_keywords | `solicitar devolução`, `solicitar devolucao`, `devolver pedido`, `devolver`, `devolução`, `devolucao`, `arrependimento` | +| execution | `mode=workflow`; workflow `devolucao_pedido`; version `active` | + +**Required data and origin** + +| Field | Type | How it is obtained | Use | +|---|---|---|---| +| `order_id` | `string` | `hybrid` extraction from `message` | Identificador do pedido para o qual o cliente deseja solicitar devolução. | +| `reason` | `string` | default `Solicitação aberta pelo atendimento conversacional.` | Motivo informado pelo cliente para solicitar a devolução do pedido. | + +**MCP aliases:** `session_key → session_id`. + +**Conversational extraction:** +- `order_id`: strategy `hybrid`; Extraia somente o identificador do pedido informado explicitamente pelo usuário. Retorne null quando não houver identificador de pedido na mensagem. + +**What it returns:** In direct MCP mode it returns protocol/status/guidance; in the normal template the policy selects `execution.mode: workflow`, so final execution goes through the deterministic `devolucao_pedido` workflow. + +**Special execution:** this tool is bound to a deterministic workflow by policy; see the workflow section below. + +## Workflow(s) involved + +### Workflow `devolucao_pedido.v1.yaml` + +**Contract:** `name=devolucao_pedido`, `version=1`, `start=validar_pedido`. + +**Why it is built this way:** a return is a transactional multi-step action. The template separates the conversational decision from deterministic execution: it first validates the order and only registers the return when validation produces `valid=true`. This prevents the LLM from freely choosing the sequence of side effects. + +#### Nodes + +| Node | Action | Input | Role | +|---|---|---|---| +| `validar_pedido` | `validar_pedido` | `order_id=$.input.order_id` | Initial validation point. | +| `registrar_devolucao` | `registrar_devolucao` | `order_id=$.input.order_id`, `reason=$.input.reason` | Executes the return effect/registration. Uses `retry=1`. | + +#### Conditions and termination + +| From | To | Condition | Consequence | +|---|---|---|---| +| `validar_pedido` | `registrar_devolucao` | `{"path": "$.nodes.validar_pedido.valid", "equals": true}` | Advances to `registrar_devolucao`. | +| `validar_pedido` | `END` | `{"path": "$.nodes.validar_pedido.valid", "equals": false}` | Terminates the workflow. | +| `registrar_devolucao` | `END` | always | Terminates the workflow. | + +#### Python actions + +- `app/workflow_actions/devolucao.py::validar_pedido`: validates `order_id` and returns a contract containing `valid`. +- `app/workflow_actions/devolucao.py::registrar_devolucao`: deterministically records the return result and produces `protocol`, `order_id`, `status`, and the data required for the response. + +#### Pause/Resume + +This base workflow **does not contain a pause node**. Collection of `order_id`/`reason` and confirmation happen earlier in the transactional runtime. Pause/resume examples are demonstrated separately in `Tuning-Performance/Pause_Resume_Workflow`. + +## Binding between YAML and Python + +- `config/routing.yaml` → finds `retail_support_exchange_return` and selects `support_agent`. +- `config/tools.yaml` → describes arguments, MCP server, selection keywords, and renderer. +- `config/tool_policies.yaml` → defines read-only/transactional behavior, confirmation, pre-validation, and/or workflow. +- `config/mcp_parameter_mapping.yaml` → maps canonical keys and extracts fields from the message. +- `app/agents/support_agent.py` → uses `AgentRuntimeMixin` to execute capabilities without duplicating infrastructure. +- `app/workflows/agent_graph.py` → connects the agent to the corporate graph and output controls. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `consultar_pedido`. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `solicitar_troca`. +- `mcp/servers/retail_mcp_server/main.py` → mock/contract implementation for tool `solicitar_devolucao`. + +### Relevant `.env` and configuration + +- `ROUTING_CONFIG_PATH=./config/routing.yaml` and `ENABLE_LLM_ROUTER` control the routing catalog/semantic fallback. +- `ENABLE_ROUTE_STICKINESS`, `ROUTE_STICKINESS_*`, `HUMAN_HANDOFF_MESSAGE`, and `END_SESSION_MESSAGE` control continuity/session behavior. +- `ENABLE_MCP_TOOLS`, `MCP_SERVERS_CONFIG_PATH`, `TOOLS_CONFIG_PATH`, `TOOL_POLICIES_PATH`, `MCP_PARAMETER_MAPPING_PATH`, and `MCP_TOOL_TIMEOUT_SECONDS` control tools. +- `MCP_GATEWAY_ENABLED` chooses between a dedicated MCP Gateway and direct access to configured MCP servers. +- Logical server `retail` is resolved by `config/mcp_servers.yaml`; in the base template it points to `http://localhost:8200/mcp` using the legacy HTTP contract. +- `ENABLE_INPUT_GUARDRAILS`, `ENABLE_OUTPUT_GUARDRAILS`, `ENABLE_JUDGES`, and `ENABLE_OUTPUT_SUPERVISOR` affect the cycle before/after the agent. +- `ENABLE_CONVERSATION_SUMMARY_MEMORY` and `ENABLE_LONG_TERM_MEMORY` may enrich prompt/context without replacing MCP evidence. +- `RAG_PROVIDER`, `VECTOR_STORE_PROVIDER`, `GRAPH_STORE_PROVIDER`, `RAG_TOP_K`, and `KBDB_*` control documentary retrieval when used. + + +### Special diagnostic — exchange and return share an intent, but not the same execution + +`retail_support_exchange_return` groups post-sale support because the phrases have strong semantic overlap. **Tool** selection occurs inside the allowed set: + +- “trocar”, “troca”, “defeito”, “quebrado” → `solicitar_troca`; +- “devolver”, “devolução”, “arrependimento” → `solicitar_devolucao`; +- `consultar_pedido` may be used to obtain resource context. + +Both actions are transactional and require confirmation. The main difference is that `solicitar_devolucao` has this policy in `tool_policies.yaml`: + +```yaml +execution: + mode: workflow + workflow: devolucao_pedido + version: active +``` + +Therefore, after confirmation, a return is not merely a direct call: it enters the deterministic workflow. Exchange follows the standard transactional tool execution path. + +# Cross-cutting template rules and mechanisms + + +## Tool selection within one intent + +`routing.yaml.mcp_tools` defines the set compatible with the intent. `tools.yaml.selection_keywords`, available arguments, transactional state, and policies help determine which capability should execute. Two tools belonging to the same intent does not mean both must run. + +## Direct MCP response versus LLM + +Agents call `build_direct_mcp_answer()`. When the result contains a sufficient deterministic renderer/contract, the runtime may respond directly and mark RAG as `skipped: direct_mcp_answer`. + +When a direct answer is insufficient, the agent may retrieve RAG, prepare memory, and use the LLM. + +## `prompt_policy.yaml` + +Defines tone and preferred vocabulary; it also registers intents/agents for prompt composition. It does not replace `routing.yaml`. + +## Configuration by `agent_id` + +`config/agents//prompt_policy.yaml`, `guardrails.yaml`, and `judges.yaml` allow each logical identity to be specialized. The registry lives in `config/agents.yaml`. + +## MCP transport + +`config/mcp_servers.yaml` documents three styles: + +- `http`: framework legacy contract; +- `fastmcp`: official MCP Streamable HTTP; +- `sse`: official MCP SSE. + +In the base template, `telecom` and `retail` use local `http`, but the registry can change without rewriting agents. + +## MCP Gateway + +With `MCP_GATEWAY_ENABLED=true`, the backend delegates calls to the dedicated MCP Gateway (`MCP_GATEWAY_URL`). With `false`, it uses registry endpoints directly. + +## Summarized memory + +`ENABLE_CONVERSATION_SUMMARY_MEMORY=true` allows summary + recent messages to be prepared before assembling `messages`. The goal is to reduce context while preserving continuity. + +## RAG + +The template may use memory/vector/graph stores and KBDB. RAG does not replace an operational tool. `ProductAgent` emits detailed IC even when retrieval was attempted but produced no context. + +## Observability + +The runtime can publish events to Langfuse, OTEL, and analytics. `AgentObserver` standardizes IC/NOC/GRL. The template's `TelemetryObserver` connects workflow events to observability infrastructure. + +## Presentation + +`app/presentation/tool_renderers.py` decouples MCP payload from textual/visual response. Renderers are useful when deterministic presentation should avoid LLM cost/latency. + +## Workflow actions + +`app/workflow_actions/` contains domain effects/actions referenced by YAML. Workflow defines order/conditions; the action implements the operation. + +## Diagnosing an unexpected decision + +1. Check `agent_id`. +2. Inspect `transaction_status`, `next_state`, paused workflow, and checkpoint. +3. Inspect `routing_decision` and method (`state`, keyword, LLM, stickiness). +4. Confirm intent, route, and `mcp_tools`. +5. See which tool was actually selected. +6. Compare `requires` with `resolved_arguments`/`missing_parameters`. +7. Look for temporal reconciliation/contextual reentry. +8. Inspect `transaction_pre_validation`. +9. Confirm whether `AWAITING_CONFIRMATION` occurred. +10. Identify direct execution versus workflow. +11. Inspect `mcp_results`, `transaction_evidence`, RAG, and renderer. +12. Check Output Supervisor, guardrails, and judges. +13. Confirm persistence/pending topics at the end of the turn. + +# Part II — `Tuning-Performance` + +`Tuning-Performance` should not be read merely as “speed optimization.” The folder acts as a catalog of **isolated framework-capability scenarios**, useful for benchmarking, regression, and architectural understanding. + +The base template already incorporates several of these capabilities. Some directories contain a modified executable copy; others contain documentation only; `Normal` and `Long_Term_Memory` are empty in this package and therefore do not represent an additional executable variant in this version. + +## `Tuning-Performance` inventory + +| Scenario | Content in this package | Objective | +|---|---|---| +| `Authentication` | README + executable template variant | Cross-cutting authentication through providers/middleware and route policies. | +| `Deterministic_Transactional_Workflow` | README + executable template variant | Deterministic multi-step execution after confirmation. | +| `Domain_Requested_LLM_Composition` | documentation/example | Domain requests composition through the official LLM without creating a private LLM gateway. | +| `Domain_Requested_RAG` | documentation/example | Domain requests framework RAG when MCP is insufficient. | +| `External_Guardrails_Judges` | README + executable template variant | External guardrail/judge extensions and overhead measurement. | +| `Long_Term_Memory` | documentation/example | Reserved directory; the capability exists in framework/template, with no local variant in this package. | +| `Normal` | documentation/example | Reserved baseline; empty directory in this package. | +| `Offline_Workflow_Regression` | documentation/example | Opt-in deterministic fallback for offline workflow-DSL regression tests. | +| `Pause_Resume_Workflow` | README + executable template variant | Pause/resume by execution_id and expected_input. | +| `Route_Stickness` | documentation/example | Semantic continuity, handoff, session ending, and MCP policies. | +| `Transaction_Evidence` | README + executable template variant | Persistence/correlation of transactional operational evidence. | +| `Transaction_Pre_Validation` | README + executable template variant | Side-effect-free MCP validator before confirmation. | +| `Voice_Interruption_Replay` | documentation/example | Voice short-circuit/replay without incorrectly reexecuting the graph. | +| `Workflow_Error_Recovery` | documentation/example | Partial snapshot and structured error_details on workflow failure. | + +# T1. Tuning — `Authentication` + +**Objective:** Cross-cutting authentication through providers/middleware and route policies. + +## What this scenario demonstrates + +Demonstrates authentication as a cross-cutting HTTP concern, installed before conversational processing, with provider-specific configuration and public/protected route policies. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/Authentication/agent_template_backend_authentication`. + +**Changed files:** `requirements.txt`, `README.md`, `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Added files:** `docs/MANUAL_AUTENTICACAO.md`, `config/authentication.example.yaml`, `scripts/generate_secret_hash.py`. + + +## Engine and configuration + +The variant uses `install_authentication()`/providers from `libs/agent_framework/security` and adds `config/authentication.example.yaml`. `.env.example` demonstrates: + +```text +AGENT_AUTH_MODE=basic|api_key|bearer_static|jwt|oauth2_introspection|trusted_proxy +AGENT_AUTH_PUBLIC_PATHS +AGENT_AUTH_PUBLIC_PREFIXES +``` + +In the Basic example, the credential is stored as a hash (`AGENT_AUTH_BASIC_SECRET_HASH`) and `scripts/generate_secret_hash.py` helps generate it. + +Authentication is **cross-cutting**: it occurs at the HTTP edge/middleware before the conversational engine. It must not become a routing keyword or an agent rule. + +## What to validate + +- truly public routes; +- fail-closed behavior on protected routes; +- secret storage/rotation; +- claims/roles/scopes per provider; +- blocking direct pod access when using `trusted_proxy`; +- observability without logging secrets/tokens. + +The documentation itself marks this as a reference implementation requiring security review before production. + + +# T2. Tuning — `Deterministic_Transactional_Workflow` + +**Objective:** Deterministic multi-step execution after confirmation. + +## What this scenario demonstrates + +Demonstrates how a confirmed transactional capability can be delegated to a deterministic workflow so the LLM does not choose the side-effect sequence. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend`. + +**Changed files:** `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/agents/runtime.py`, `app/workflows/agent_graph.py`. + +**Added files:** `tests/test_transactional_workflow_template.py`. + + +## Flow + +```text +router +→ support_agent +→ collect order_id + reason +→ AWAITING_CONFIRMATION +→ explicit confirmation +→ policy execution.mode=workflow +→ WorkflowToolExecutor +→ devolucao_pedido.active.yaml +→ devolucao_pedido.v1.yaml +→ validar_pedido +→ registrar_devolucao +→ protocol + workflow_execution_id +``` + +The main gain is not simply “having confirmation” — that already exists. The differentiator is **removing post-confirmation sequence choice from the LLM**. + +## What to measure + +- collection/confirmation time; +- workflow latency; +- action retries; +- idempotency/reexecution; +- `workflow_execution_id` consistency; +- response when `validar_pedido.valid=false`. + + +# T3. Tuning — `Domain_Requested_LLM_Composition` + +**Objective:** Domain requests composition through the official LLM without creating a private LLM gateway. + +## What this scenario demonstrates + +Demonstrates a domain result explicitly requesting answer composition by the framework's official LLM path. + + +## Contract + +A tool/workflow may return: + +```json +{ + "requires_llm_composition": true, + "response_instruction": "Explain using only workflow evidence." +} +``` + +or `response_instructions` as a list. + +`AgentRuntimeMixin` detects the flag recursively. When active, `build_direct_mcp_answer()` does not end the turn; MCP output becomes evidence for composition through the official LLM. + +## Architectural rule + +The domain may request **wording/composition**, but it must not use this mechanism to decide whether a transaction occurs, invent amounts/protocols, or create a private LLM provider. Provider, profile, tracing, credentials, and costs remain framework responsibilities. + + +# T4. Tuning — `Domain_Requested_RAG` + +**Objective:** Domain requests framework RAG when MCP is insufficient. + +## What this scenario demonstrates + +Demonstrates a domain result explicitly requesting framework RAG, including one or more retrieval queries. + + +## Contract + +```json +{ + "requires_rag": true, + "rag_queries": [ + "Documentary question 1", + "Documentary question 2" + ] +} +``` + +Flow: + +```text +tool/workflow +→ requires_rag +→ AgentRuntimeMixin +→ framework RagService +→ vector/graph store +→ LLM with MCP evidence + RAG evidence +``` + +The flag may override `SKIP_RAG_WHEN_MCP_SUFFICIENT`. The domain does not instantiate embeddings/vector stores; it only declares the need and queries. + + +# T5. Tuning — `External_Guardrails_Judges` + +**Objective:** External guardrail/judge extensions and overhead measurement. + +## What this scenario demonstrates + +Demonstrates external guardrail/judge extensions and the latency/behavioral overhead they introduce. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/External_Guardrails_Judges/agent_template_backend`. + +**Changed files:** `README.md`, `llm_profiles.yaml`, `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/judges.yaml`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `config/guardrails.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Added files:** `app/extensions/example_judges.py`, `app/extensions/__init__.py`, `app/extensions/example_guardrails.py`. + + +## What changes + +The variant adds extensions in `app/extensions/example_guardrails.py` and `app/extensions/example_judges.py` and changes configuration to demonstrate `type: external`. + +## Correct benchmark + +Compare with the extension disabled and separate: + +- p50/p95/p99; +- allow/deny/sanitize; +- timeout/error; +- LLM-judge cost; +- fail-open/fail-closed behavior; +- transactional cases, because `always_run_for_transactional` may bypass sampling. + +Synchronous implementations may use a worker thread; `async` uses the event loop. Tuning should observe provider/pool contention and must not log prompts/PII/financial payloads. + + +# T6. Tuning — `Long_Term_Memory` + +**Objective:** Reserved directory; the capability exists in framework/template, with no local variant in this package. + +## What this scenario demonstrates + +The directory is empty in this package; the capability is documented from the base template itself. + + +## How it works in the base template + +The graph calls `load_long_term_memory` before routing and `persist_long_term_memory` near the end. The manager is created by `create_long_term_memory_manager(settings, telemetry=telemetry)` and injected into agents. + +Main variables: + +```text +ENABLE_LONG_TERM_MEMORY +LONG_TERM_MEMORY_PROVIDER +LONG_TERM_MEMORY_SQLITE_PATH +LONG_TERM_MEMORY_TABLE +LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS +LONG_TERM_MEMORY_MIN_CONFIDENCE +LONG_TERM_MEMORY_AUTO_EXTRACT +LONG_TERM_MEMORY_INJECT_CONTEXT +``` + +**Do not confuse it with Transaction Evidence:** LTM is semantic/durable memory; transaction evidence is structured operational fact tied to an execution/resource. + + +# T7. Tuning — `Normal` + +**Objective:** Reserved baseline; empty directory in this package. + +## What this scenario demonstrates + +The directory is empty; the effective baseline is `templates/agent_template_backend`. + + +## Baseline used in this manual + +The baseline is `templates/agent_template_backend`. When evaluating any tuning scenario, compare against the exact same: + +- LLM/provider; +- persistence; +- MCP transport; +- guardrails/judges; +- RAG; +- load; +- test data. + +Without a controlled baseline, latency differences cannot be attributed to the capability being studied. + + +# T8. Tuning — `Offline_Workflow_Regression` + +**Objective:** Opt-in deterministic fallback for offline workflow-DSL regression tests. + +## What this scenario demonstrates + +Demonstrates an opt-in deterministic fallback used only for offline regression of workflow DSL behavior. + + +## Behavior + +Production still requires LangGraph. Deterministic fallback exists only when `allow_deterministic_fallback=True`, for builders/offline tests. + +It exercises the DSL: + +- actions; +- edges; +- conditions; +- pause/resume; +- trace. + +It must not be automatically selected in production, because that would hide missing/misconfigured LangGraph infrastructure. + + +# T9. Tuning — `Pause_Resume_Workflow` + +**Objective:** Pause/resume by execution_id and expected_input. + +## What this scenario demonstrates + +Demonstrates pausing a workflow for user input and resuming the exact execution by `execution_id`. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/Pause_Resume_Workflow/agent_template_backend`. + +**Changed files:** `README.md`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`. + +**Added files:** `app/demo.py`, `tests/test_pause_resume.py`, `workflows/confirmacao.active.yaml`, `workflows/confirmacao.v1.yaml`. + + +## Structure + +The variant adds `workflows/confirmacao.v1.yaml`, `confirmacao.active.yaml`, `app/demo.py`, and tests. + +`WorkflowRuntime.arun()` starts the execution; when a node declares pause, it returns `PAUSED`. `aresume(name, execution_id, value)` resumes the same execution. + +The YAML demonstrates: + +- `expected_input`; +- normalization; +- allowed values; +- `resume_from`; +- reprompt; +- `semantic_classifier`; +- contextual reentry by option. + +Pause is separated from the previous action so resuming does not repeat a side effect. + + +# T10. Tuning — `Route_Stickness` + +**Objective:** Semantic continuity, handoff, session ending, and MCP policies. + +## What this scenario demonstrates + +Demonstrates route continuity, rerouting, human handoff, and session termination without allowing stickiness to authorize tools. + + +## Decision order + +```text +session ended? → reject/replay according to channel +route stickiness enabled? + → CONTINUE → active agent + → ROUTE/low confidence/error → EnterpriseRouter + → HUMAN_HANDOFF → global node + → END_SESSION → global node +``` + +Documented variables: + +```text +ENABLE_ROUTE_STICKINESS=true +ROUTE_STICKINESS_LLM_PROFILE=route_continuity +ROUTE_STICKINESS_CONFIDENCE_THRESHOLD=0.90 +ROUTE_STICKINESS_HISTORY_TURNS=2 +ROUTE_STICKINESS_MAX_TOKENS=80 +HUMAN_HANDOFF_MESSAGE=... +END_SESSION_MESSAGE=... +``` + +Stickiness does not authorize tools. Even under `CONTINUE`, MCP calls still pass through read-only/transactional policies. + + +# T11. Tuning — `Transaction_Evidence` + +**Objective:** Persistence/correlation of transactional operational evidence. + +## What this scenario demonstrates + +Demonstrates persistence of completed transactional evidence so later turns and judges can ground references to prior operations. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/Transaction_Evidence/agent_template_backend`. + +**Changed files:** `.env.example`, `app/main.py`, `app/state.py`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `config/mcp_parameter_mapping.yaml`, `config/tools.yaml`, `config/tool_policies.yaml`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Added files:** none. + + +## Problem solved + +A transaction may occur in one turn and be referenced later. Without persisted evidence, groundedness may consider a prior cancellation/protocol unsupported. + +The runtime writes `transaction_evidence` and correlates relevant items into `relevant_transaction_evidence`. + +Example: + +```text +cancelar_pedido(PED-1001) +→ COMPLETED +→ protocol +→ transaction_evidence +... +"show me my order" +→ consultar_pedido +→ relevant_transaction_evidence from cancellation +→ response + judges receive the same evidence +``` + +Transaction Evidence is operational, not semantic memory. + + +# T12. Tuning — `Transaction_Pre_Validation` + +**Objective:** Side-effect-free MCP validator before confirmation. + +## What this scenario demonstrates + +Demonstrates side-effect-free validation before the user is asked to confirm a sensitive transaction. + +## Delta from the base template + +Analyzed variant: `Tuning-Performance/Transaction_Pre_Validation/agent_template_backend`. + +**Changed files:** `.env.example`, `docs/TRANSACTION_SEMANTIC_CONFIRMATION.md`, `app/agents/product_agent.py`, `app/workflows/agent_graph.py`. + +**Added files:** none. + + +## Flow + +```text +complete parameters +→ validar_cancelamento_pedido +→ eligible? + ├─ false → OUT_OF_SCOPE / terminal / clear latch + └─ true → AWAITING_CONFIRMATION + ↓ + yes + ↓ + cancelar_pedido +``` + +`fail_open=false` is appropriate for a sensitive operation. Rejection does not become `transaction_evidence`, because the business operation did not occur. + +Expected events include: + +```text +IC.TRANSACTION_PREVALIDATION_REQUESTED +IC.TRANSACTION_PREVALIDATION_PASSED +IC.TRANSACTION_PREVALIDATION_REJECTED +IC.TRANSACTION_CONFIRMATION_REQUIRED +``` + + +# T13. Tuning — `Voice_Interruption_Replay` + +**Objective:** Voice short-circuit/replay without incorrectly reexecuting the graph. + +## What this scenario demonstrates + +Demonstrates voice replay/short-circuit decisions that avoid unnecessary graph and tool execution. + + +## Framework-native order + +1. ended session → terminal replay; +2. idle nudge → replay last real utterance; +3. non-interruptible speech → literal replay; +4. interruptible speech with context → `processing_interruption_classifier`; +5. insufficient context → normal processing. + +On short-circuit, metadata reports `replay=true`, `framework_short_circuit=true` and avoids LangGraph/tools/guardrails. In classifier cases, only the lightweight classification LLM may be called. + + +# T14. Tuning — `Workflow_Error_Recovery` + +**Objective:** Partial snapshot and structured error_details on workflow failure. + +## What this scenario demonstrates + +Demonstrates preserving partial output/trace and structured provider error details when a workflow fails. + + +## Failure contract + +`WorkflowRunResult` preserves: + +- `output`: nodes completed before failure; +- `trace`: partial path; +- `error`: message; +- `error_details`: when available, `status_code`, `body`, `attempts`. + +This keeps the framework generic while allowing the domain to interpret provider details without coupling the workflow engine to a specific integration. + + +# Part III — maintenance file map + + +## Base template + +| Area | File | +|---|---| +| API / session / SSE / entry | `templates/agent_template_backend/app/main.py` | +| State | `app/state.py` | +| Graph | `app/workflows/agent_graph.py` | +| Common agent runtime | `app/agents/runtime.py` | +| Billing | `app/agents/billing_agent.py` | +| Products | `app/agents/product_agent.py` | +| Orders | `app/agents/orders_agent.py` | +| Support | `app/agents/support_agent.py` | +| Routing | `config/routing.yaml` | +| Agents registry | `config/agents.yaml` | +| Tools | `config/tools.yaml` | +| Policies | `config/tool_policies.yaml` | +| MCP parameters | `config/mcp_parameter_mapping.yaml` | +| MCP servers | `config/mcp_servers.yaml` | +| Guardrails | `config/guardrails.yaml` | +| Judges | `config/judges.yaml` | +| Prompt policy | `config/prompt_policy.yaml` | +| Return workflow | `workflows/devolucao_pedido.v1.yaml` | +| Workflow active pointer | `workflows/devolucao_pedido.active.yaml` | +| Return actions | `app/workflow_actions/devolucao.py` | +| Renderers | `app/presentation/tool_renderers.py` | +| Observability | `app/observability/telemetry_observer.py` | +| Framework runtime | `libs/agent_framework/src/agent_framework/runtime/agent_runtime.py` | +| Router | `libs/agent_framework/src/agent_framework/routing/enterprise_router.py` | +| Multi-intent | `libs/agent_framework/src/agent_framework/routing/multi_intent.py` | +| Pending topics | `libs/agent_framework/src/agent_framework/routing/pending_topics.py` | +| Parameters/reconciliation | `libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py` | +| Workflow runtime | `libs/agent_framework/src/agent_framework/workflows/` | + +## How to create a new rule without hardcoding the core + +1. Define the intent in `config/routing.yaml`. +2. Point it to an existing agent or create one under `app/agents/`. +3. Register the agent in the graph only if it is new. +4. Declare capabilities in `config/tools.yaml`. +5. Declare confirmation/pre-validation/workflow in `config/tool_policies.yaml`. +6. Configure aliases/extract/defaults in `config/mcp_parameter_mapping.yaml`. +7. Implement the tool in the MCP Server, not in the router. +8. For multi-step orchestration, create workflow YAML and Python actions. +9. Add guardrails/judges only for cross-cutting/quality concerns; do not use guardrails as routers. +10. Test state, collection, confirmation, intent shift, retry, idempotency, and groundedness. +11. If the capability needs advanced behavior, consult the `Tuning-Performance` scenarios before duplicating infrastructure in the agent. diff --git a/README.md b/README.md index 46d437e3..693f51c5 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ agent_template_backend/ └── README_ENTERPRISE_TEMPLATE.md ``` -> **Importante:** recursos como checkpoint/persistência, Long-Term Memory, RAG genérico, MCP Tool Router, roteamento/supervisor, coleta de parâmetros, reconciliação temporal, idempotência, segurança, Output Supervisor, judges, guardrails e observabilidade corporativa pertencem ao **core do `agent_framework_oci`**. O template apenas os configura, compõe ou estende quando necessário para o domínio. +> **Importante:** recursos como checkpoint/persistência, Long-Term Memory, RAG genérico, MCP Tool Router, roteamento/supervisor, coleta de parâmetros, reconciliação temporal, idempotência, segurança, Output Supervisor, judges, guardrails e observabilidade corporativa pertencem ao **core do `agent_framework_oci`**. O template apenas os configura, compõe ou estende quando necessário para o domínio. Se deseja entender mais sobre o projeto agent_template_backend, clique aqui: [MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND](./MANUAL_REGRAS_AGENT_TEMPLATE_BACKEND.md) `tools.yaml` e `tool_policies.yaml` têm responsabilidades diferentes e complementares: o primeiro descreve **quais tools existem e seus contratos/parâmetros**; o segundo define **como e em quais condições elas podem ser executadas**, incluindo confirmação e comportamento transacional. diff --git a/README_en.md b/README_en.md index a4f6297c..78accc5c 100644 --- a/README_en.md +++ b/README_en.md @@ -197,7 +197,7 @@ agent_template_backend/ └── README_ENTERPRISE_TEMPLATE.md ``` -> **Important:** capabilities such as checkpoint/persistence, Long-Term Memory, generic RAG, MCP Tool Router, routing/supervisor, parameter collection, temporal reconciliation, idempotency, security, Output Supervisor, judges, guardrails, and enterprise observability belong to the **`agent_framework_oci` core**. The template only configures, composes, or extends them when required by the domain. +> **Important:** capabilities such as checkpoint/persistence, Long-Term Memory, generic RAG, MCP Tool Router, routing/supervisor, parameter collection, temporal reconciliation, idempotency, security, Output Supervisor, judges, guardrails, and enterprise observability belong to the **`agent_framework_oci` core**. The template only configures, composes, or extends them when required by the domain. If you want to know more about agent_template_backend, click here: [MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN](MANUAL_RULES_AGENT_TEMPLATE_BACKEND_EN.md) `tools.yaml` and `tool_policies.yaml` have different and complementary responsibilities: the former describes **which tools exist and their contracts/parameters**; the latter defines **how and under which conditions they may execute**, including confirmation and transactional behavior.