fix: Spec Agent Runtime

This commit is contained in:
2026-10-30 10:22:53 -03:00
parent e517f5e6a3
commit 76f3363df3
2 changed files with 269 additions and 205 deletions

3
.idea/workspace.xml generated
View File

@@ -179,7 +179,8 @@
<workItem from="1785453511270" duration="1006000" /> <workItem from="1785453511270" duration="1006000" />
<workItem from="1792665278602" duration="734000" /> <workItem from="1792665278602" duration="734000" />
<workItem from="1793193595355" duration="436000" /> <workItem from="1793193595355" duration="436000" />
<workItem from="1793194079956" duration="4230000" /> <workItem from="1793194079956" duration="5443000" />
<workItem from="1793271962068" duration="758000" />
</task> </task>
<task id="LOCAL-00001" summary="Ajustes na documentação e remanejamento dos folders"> <task id="LOCAL-00001" summary="Ajustes na documentação e remanejamento dos folders">
<option name="closed" value="true" /> <option name="closed" value="true" />

View File

@@ -1,268 +1,331 @@
# SPEC-002 — Agent Runtime # SPEC-002 — Agent Runtime
## Escopo ## 1. Visão geral
O Agent Runtime executa o ciclo de vida conversacional do agente. A execução inclui normalização de contexto, estado LangGraph, memória, checkpoint, roteamento, supervisor, guardrails, MCP, RAG, LLM, judges, persistência e resposta final. O Agent Runtime coordena a execução conversacional dos agentes da plataforma OCI. O runtime combina grafos LangGraph, estado por conversa, roteamento de intenções, agentes de domínio, guardrails, judges, memória de longo prazo e persistência. A biblioteca reutilizável do framework fornece serviços e contratos consumidos pelos backends; o backend de referência `agent_template_backend` compõe esses serviços em um workflow executável.
## Componentes ## 2. Organização da implementação
| Componente | Responsabilidade | | Elemento | Localização | Função |
|---|---| |---|---|---|
| Workflow Builder | Compila o grafo LangGraph. | | Runtime compartilhado | `libs/agent_framework/src/agent_framework/runtime/` | Capacidades reutilizáveis para execução dos agentes. |
| State Manager | Mantém o estado de execução. | | Workflow de referência | `templates/agent_template_backend/app/workflows/agent_graph.py` | Construção do grafo e implementação dos nós do workflow. |
| Session Manager | Resolve sessão e conversation_key. | | Estado do workflow | `templates/agent_template_backend/app/state.py` | Definição tipada dos dados transportados entre nós. |
| Memory Manager | Carrega e persiste histórico. | | Configuração dos agentes | `templates/agent_template_backend/config/agents.yaml` | Cadastro de agentes e caminhos de políticas/configurações. |
| Checkpoint Manager | Persiste estado LangGraph. | | Configuração de roteamento | `templates/agent_template_backend/config/routing.yaml` | Modo do roteador, fallback, limiar e catálogo de intenções. |
| Input Guardrail Node | Executa guardrails de entrada. | | Configuração das ferramentas | `templates/agent_template_backend/config/tools.yaml` | Definições de ferramentas utilizadas pelos agentes. |
| Router Node | Decide rota/intent. |
| Supervisor Node | Decide handoff ou próximo agente quando habilitado. |
| Agent Node | Executa agente de domínio. |
| MCP Client/Router | Executa tools por contrato. |
| RAG Service | Recupera contexto documental. |
| Output Supervisor | Revisa resposta antes de saída. |
| Output Guardrail Node | Executa guardrails de saída. |
| Judge Node | Avalia resposta. |
| Persistence Node | Persiste mensagens, memória e checkpoint. |
## State Model ## 3. Estado de execução
O workflow utiliza o `AgentState` abaixo. A declaração `TypedDict(total=False)` permite que os nós adicionem os campos pertinentes a cada etapa sem exigir a presença de todos os campos em cada estado.
```python ```python
from typing import Any, TypedDict
class AgentState(TypedDict, total=False): class AgentState(TypedDict, total=False):
user_text: str
sanitized_input: str
response_text: str
tenant_id: str tenant_id: str
agent_id: str agent_id: str
channel: str
session_id: str session_id: str
conversation_key: str conversation_key: str
message_id: str workflow_id: str
agent_profile: dict[str, Any]
user_text: str
sanitized_input: str
route: str route: str
intent: str intent: str
context: dict route_decision: dict[str, Any]
business_context: dict answer: str
tool_arguments: dict final_answer: str
history: list[dict[str, Any]]
context: dict[str, Any]
guardrail_decisions: list[dict[str, Any]]
judge_results: list[dict[str, Any]]
next_state: str
domain: str
mcp_tools: list[str] mcp_tools: list[str]
mcp_results: list[dict] mcp_results: list[dict[str, Any]]
rag_context: str rag_results: list[dict[str, Any]]
rag_metadata: dict available_mcp_tools: list[str]
guardrails: list[dict] selected_tool_call: dict[str, Any]
judges: list[dict] pending_tool_call: dict[str, Any]
metadata: dict active_transaction: dict[str, Any]
errors: list[dict] last_transaction: dict[str, Any]
transaction_status: str
transaction_pre_validation: dict[str, Any]
transaction_evidence: list[dict[str, Any]]
last_transaction_evidence: dict[str, Any]
relevant_transaction_evidence: list[dict[str, Any]]
confirmation_required: bool
confirmation_received: bool
tool_policy_result: dict[str, Any]
missing_parameters: list[str]
supervisor_plan: dict[str, Any]
supervisor_results: list[dict[str, Any]]
agent_responses: list[dict[str, Any]]
pending_topics: list[dict[str, Any]]
handled_topics: list[dict[str, Any]]
operation_results: dict[str, dict[str, Any]]
multi_intent_plan: dict[str, Any]
active_agent: str
route_bypassed: bool
continuity_signal: dict[str, Any]
session_control: str
session_ended: bool
human_handoff_requested: bool
blocked: bool
supervisor_action: str
supervisor_guidance: str
supervisor_attempt: int
supervisor_handover_reason: str
output_supervisor_results: list[dict[str, Any]]
output_guardrails_already_applied: bool
long_term_memories: list[dict[str, Any]]
long_term_memory_context: str
long_term_memory_write_result: dict[str, Any]
long_term_memory_subject_key: str
long_term_memory_load_error: str
``` ```
## 4. Fluxo de execução
## Workflow O workflow é compilado com `FrameworkStateGraph(AgentState)` e utiliza um checkpointer criado por `create_langgraph_checkpointer(self.settings)`.
```mermaid ```mermaid
flowchart TD flowchart TD
A[start] --> B[input_guardrails] START([START]) --> input_guardrails
B --> C[routing_decision] input_guardrails -->|continue| load_long_term_memory
C --> D[agent_execution] input_guardrails -->|blocked| output_guardrails
D --> E[output_supervisor] load_long_term_memory --> routing_decision
E --> F[output_guardrails] routing_decision --> billing_agent
F --> G[judge] routing_decision --> product_agent
G --> H[persist] routing_decision --> orders_agent
H --> I[end] routing_decision --> support_agent
C --> J[handoff] routing_decision --> handoff
J --> C routing_decision --> human_handoff
routing_decision --> end_session
routing_decision --> supervisor_agent
billing_agent --> output_supervisor
product_agent --> output_supervisor
orders_agent --> output_supervisor
support_agent --> output_supervisor
handoff --> output_supervisor
human_handoff --> output_supervisor
end_session --> output_supervisor
supervisor_agent --> output_supervisor
output_supervisor --> output_guardrails
output_guardrails -->|continue| judge
output_guardrails -->|blocked| persist
judge --> supervisor_review
supervisor_review --> persist_long_term_memory
persist_long_term_memory --> persist
persist --> END([END])
``` ```
## Nós O roteamento após `input_guardrails` depende de `state['blocked']`. Após `routing_decision`, a rota em `state['route']` seleciona um dos nós registrados, com valor padrão `billing_agent` quando a chave não está presente. O roteamento após `output_guardrails` também consulta `state['blocked']`.
| Nó | Entrada | Saída | ## 5. Nós do workflow
|---|---|---|
| `input_guardrails` | `user_text`, `context` | `sanitized_input`, `guardrails` |
| `routing_decision` | `sanitized_input`, `business_context` | `route`, `intent`, `mcp_tools` |
| `agent_execution` | `state` completo | `response_text`, `mcp_results`, `rag_metadata` |
| `output_supervisor` | `response_text` | `response_text` revisado |
| `output_guardrails` | `response_text` | `response_text`, `guardrails` |
| `judge` | `response_text`, evidências | `judges` |
| `persist` | `state` completo | checkpoint, memória, mensagens |
## Router | Nó | Responsabilidade |
|---|---|
| `input_guardrails` | Avalia e processa a entrada antes do roteamento. |
| `load_long_term_memory` | Carrega contexto de memória de longo prazo. |
| `routing_decision` | Determina o destino de execução da conversa. |
| `billing_agent` | Executa o agente de faturamento. |
| `product_agent` | Executa o agente de produtos e serviços. |
| `orders_agent` | Executa o agente de pedidos. |
| `support_agent` | Executa o agente de suporte. |
| `handoff` | Processa o fluxo de transferência previsto pelo workflow. |
| `human_handoff` | Processa a solicitação de transferência para atendimento humano. |
| `end_session` | Processa o encerramento de sessão. |
| `supervisor_agent` | Executa o fluxo associado ao supervisor. |
| `output_supervisor` | Processa a etapa de supervisão da resposta. |
| `output_guardrails` | Aplica as políticas de saída. |
| `judge` | Realiza a avaliação da resposta. |
| `supervisor_review` | Processa a revisão após o judge. |
| `persist_long_term_memory` | Executa a etapa de escrita de memória de longo prazo. |
| `persist` | Executa a etapa final de persistência do workflow. |
Os nós são encapsulados pelo método `_node`, que os executa no contexto `self.langgraph_telemetry.node(name, state)`.
## 6. Roteamento
O arquivo `config/routing.yaml` define as opções principais sob a chave `router`:
```yaml ```yaml
routing: # Roteamento enterprise configurável com MCP-aware intents.
router:
# mode também pode ser definido por variável de ambiente ROUTING_MODE.
# Valores: router | supervisor
mode: router mode: router
fallback_agent: billing_agent fallback_agent: billing_agent
enable_llm_router: false confidence_threshold: 0.65
intents: allow_handoff: true
billing_invoice_explanation:
route: billing_agent
keywords:
- fatura
- cobrança
- boleto
mcp_tools:
- consultar_fatura
- consultar_pagamentos
``` ```
A configuração contém também `state_policies` para manter determinadas etapas de confirmação ou coleta vinculadas ao agente correspondente, além do catálogo `intents` com atributos como `name`, `domain`, `agent`, `priority`, `mcp_tools`, `keywords` e `examples`.
## Supervisor O catálogo de agentes em `config/agents.yaml` declara os agentes `telecom_contas` e `retail_orders`. Cada registro aponta para arquivos de política de prompts, roteamento, guardrails, judges, servidores MCP e ferramentas, além de metadados do domínio.
```yaml ## 7. Execução dos agentes e ferramentas
supervisor:
enabled: true
profile: supervisor
max_turns: 5
handoff_enabled: true
fallback_route: support_agent
```
## Memory Os nós de domínio encaminham a solicitação para as instâncias dos agentes de faturamento, produtos, pedidos e suporte. A integração com ferramentas MCP é disponibilizada aos agentes por meio da configuração de ferramentas e dos componentes de roteamento de tools. Os resultados de ferramentas podem ser transportados no estado pelo campo `mcp_results`; os nomes selecionados ficam em `mcp_tools`.
| Provider | Uso | O estado também comporta `selected_tool_call`, `pending_tool_call`, `tool_policy_result`, `missing_parameters` e os campos de evidências transacionais. Esses elementos permitem que etapas de preparação, validação, confirmação e execução compartilhem informações ao longo da conversa.
|---|---|
| `memory` | Execução local e testes. |
| `sqlite` | Desenvolvimento local persistente. |
| `mongodb` | Checkpoint e histórico em ambiente distribuído. |
| `autonomous` | Produção com Oracle Autonomous Database. |
## Checkpoints ## 8. Estado transacional
Checkpoint contém: O `AgentState` mantém em `active_transaction` os dados da transação em andamento e em `last_transaction` o registro da última transação encerrada. Os campos `transaction_status`, `transaction_pre_validation`, `transaction_evidence`, `last_transaction_evidence`, `relevant_transaction_evidence`, `confirmation_required` e `confirmation_received` transportam as informações necessárias ao processamento transacional.
```json A configuração de roteamento inclui políticas de estado para as etapas `WAITING_BILLING_CONFIRMATION`, `WAITING_PRODUCT_CONFIRMATION`, `WAITING_ORDER_CONFIRMATION`, `WAITING_SUPPORT_CONFIRMATION`, `COLLECTING_BILLING_PARAMETERS`, `COLLECTING_PRODUCT_PARAMETERS`, `COLLECTING_ORDER_PARAMETERS` e `COLLECTING_SUPPORT_PARAMETERS`.
{
"conversation_key": "default:telecom_contas:session-001",
"checkpoint_id": "ckpt-001",
"state": {},
"pending_writes": [],
"created_at": "2026-06-19T12:00:00Z"
}
```
Formato entregue ao LangGraph: A documentação de referência dos fluxos transacionais encontra-se em [`docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md`](../docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md).
```python ## 9. Memória e checkpoints
pending_writes: list[tuple[str, str, object]]
```
## Business Context O workflow integra duas etapas explícitas de memória de longo prazo: `load_long_term_memory`, anterior ao roteamento, e `persist_long_term_memory`, anterior à persistência final. Os campos `long_term_memories`, `long_term_memory_context`, `long_term_memory_write_result`, `long_term_memory_subject_key` e `long_term_memory_load_error` compõem a interface de estado dessa capacidade.
```yaml A construção do grafo fornece o resultado de `create_langgraph_checkpointer(self.settings)` ao método `compile`. O armazenamento e a recuperação dos checkpoints são executados pelo checkpointer configurado, preservando a continuidade do estado entre interações conforme o backend selecionado.
business_context:
customer_key: "11999999999"
contract_key: "3000131180"
interaction_key: "301953872"
account_key: null
resource_key: null
session_key: "session-001"
metadata:
source_channel: web
```
## Ordem de Prioridade dos Dados ## 10. Guardrails, supervisão e judges
1. `tool_arguments` A entrada é submetida a `input_guardrails` antes da carga de memória e do roteamento. Quando a entrada é bloqueada, o fluxo segue diretamente para `output_guardrails`.
2. `business_context`
3. `context`
4. `session.metadata`
5. `state`
6. extração complementar do texto
## MCP Integration As respostas dos agentes passam por `output_supervisor` e `output_guardrails`. Uma resposta não bloqueada segue para `judge` e `supervisor_review`; uma resposta bloqueada segue para `persist`. Os resultados são transportados nos campos `guardrail_decisions`, `output_supervisor_results`, `judge_results`, `supervisor_action`, `supervisor_guidance` e campos correlatos do estado.
```mermaid ## 11. Observabilidade
flowchart LR
AgentNode --> ToolList[mcp_tools]
ToolList --> Mapping[mcp_parameter_mapping.yaml]
Mapping --> MCP[MCP Gateway/Router]
MCP --> Result[mcp_results]
```
## RAG Integration O workflow envolve cada nó com a instrumentação `langgraph_telemetry.node`. Essa instrumentação associa a execução à identificação do nó e ao estado da conversa. A rastreabilidade das decisões e etapas de execução é tratada pelos mecanismos de telemetria e observabilidade do framework.
```yaml ## 12. Tratamento de erros e recuperação por componente
rag:
enabled: true
namespace_strategy: agent_id
top_k: 5
profile_generation: rag_generation
```
## Eventos ### 12.1. Princípios de propagação de falhas
| Evento | Descrição | O runtime distingue falhas absorvidas pela própria etapa, resultados negativos de políticas/ferramentas e exceções que impedem a execução do grafo. O contrato de cada componente determina se o processamento continua, se a resposta é alterada ou se a exceção é devolvida ao chamador. O campo `blocked` indica uma decisão de política no estado, e não equivale genericamente a uma exceção Python.
|---|---|
| `runtime.started` | Execução iniciada. |
| `runtime.session.loaded` | Sessão carregada. |
| `runtime.memory.loaded` | Memória carregada. |
| `runtime.checkpoint.loaded` | Checkpoint carregado. |
| `runtime.route.selected` | Rota selecionada. |
| `runtime.agent.started` | Agente iniciado. |
| `runtime.agent.completed` | Agente concluído. |
| `runtime.persist.completed` | Persistência concluída. |
| `runtime.failed` | Falha controlada. |
## Erros | Área | Representação utilizada | Efeito na execução |
| Código | Condição | Tratamento |
|---|---|---| |---|---|---|
| `RUNTIME_INVALID_REQUEST` | GatewayRequest inválido | 422 | | Guardrails | Decisões com `allowed`, `code` e `reason`; decisões da supervisão com `action` | Pode interromper roteamento, substituir/sanitizar a resposta ou continuar. |
| `RUNTIME_ROUTE_NOT_FOUND` | Nenhuma rota elegível | fallback ou resposta controlada | | MCP | Resultado de ferramenta com `ok`, `error`, `tool_name` e informações de execução conforme a origem | O agente utiliza o resultado para controlar a continuação da operação. |
| `RUNTIME_CHECKPOINT_ERROR` | Falha em checkpoint | retry ou stateless conforme config | | Memória de longo prazo | Campos `long_term_memory_load_error` e `long_term_memory_write_result` | Uma falha de leitura ou escrita capturada no nó não encerra o grafo. |
| `RUNTIME_MEMORY_ERROR` | Falha em memória | retry ou resposta controlada | | RAG | Resultado de recuperação ou objeto de erro técnico | A falha pode ser incorporada ao contexto de execução do agente. |
| `RUNTIME_AGENT_ERROR` | Falha no agente | NOC + fallback | | Checkpoints | Exceções do repositório, verificação de integridade e recuperação de versões | A leitura pode selecionar checkpoint válido anterior ou iniciar estado limpo; falhas de armazenamento esgotadas são propagadas. |
| `RUNTIME_TIMEOUT` | Timeout geral | resposta controlada | | Workflow | Exceções emitidas pelos nós ou por `graph.ainvoke` | A execução é marcada como falha na telemetria; a exceção é relançada. |
### 12.2. Entrada, sessão e guardrails de entrada
O nó `input_guardrails` verifica primeiro `session_ended`. Caso a sessão já esteja encerrada, define `blocked=True`, `session_control="END_SESSION"`, `session_ended=True` e `next_state="SESSION_ENDED"`, compõe a mensagem configurada em `SESSION_ALREADY_ENDED_MESSAGE` e registra `session.message.rejected_after_end`. Essa condição impede que a mensagem prossiga para roteamento e agentes.
## Contrato Durável de Estado Transacional Para mensagens de sessões ativas, o pipeline avalia os guardrails e guarda as decisões em `guardrail_decisions`. Se alguma decisão possuir `allowed=False`, o nó produz uma resposta segura, estabelece `route="blocked"`, `intent="input_guardrail_blocked"`, limpa as listas de ferramentas e resultados MCP daquele turno e segue pelo ramo de saída. A função `_input_guardrail_user_message` contém respostas específicas para `COER`, `INPUT_SIZE`, `DLEX_IN`, `PINJ`, `TOX` e `CMP`, além de uma resposta padrão para os demais códigos. O motivo detalhado permanece nas decisões e na telemetria; a mensagem ao usuário é controlada pelo runtime.
Hosts que utilizam `AgentRuntime` com transações multi-turno DEVEM declarar no `AgentState` os campos `active_transaction` e `last_transaction`. O primeiro é a fonte canônica da transação em andamento e deve sobreviver a checkpoint/resume; o segundo mantém o snapshot da última transação terminal. A avaliação registra `guardrails.input.completed`, decisões individuais na telemetria de guardrails e eventos GRL por meio do observer. No bloqueio de entrada, não são executados o nó de memória anterior ao roteamento, o roteador nem ferramentas do agente. O ramo segue para `output_guardrails` e, conforme as condições do grafo, termina em `persist`.
```python **Referência:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`input_guardrails`, `_input_guardrail_user_message`, `_after_input_guardrails`).
active_transaction: dict[str, Any]
last_transaction: dict[str, Any]
```
`selected_tool_call` e `pending_tool_call` são campos auxiliares/compatibilidade e não substituem o latch canônico. Durante `COLLECTING_PARAMETERS`, a retomada da transação e o consumo de parâmetros pendentes têm precedência sobre keyword routing genérico. Uma mudança de intenção só deve interromper a transação quando for inequívoca ou explicitamente solicitada pelo usuário. ### 12.3. Roteamento, classificação e continuidade
O contrato completo, ciclo de vida, precedência de roteamento, checklist e testes regressivos estão em [`docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md`](../docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md). A configuração do roteamento é carregada por `routing/config_loader.py`; a ausência do arquivo resulta em `FileNotFoundError`. O `EnterpriseRouter` contém tratamento localizado para erros de chamadas de classificação e de interpretação das saídas do modelo. No classificador semântico de entradas esperadas, uma falha de `llm.ainvoke` é registrada com `logger.warning` e a função retorna `(None, None)`, permitindo o uso dos caminhos subsequentes do roteamento em vez de transformar essa falha em uma classificação válida.
O fluxo utiliza as configurações `fallback_agent` e `confidence_threshold`, assim como políticas de estado em `routing.yaml`. A seleção de fallback é uma decisão de roteamento; não constitui, por si só, um código de erro. As estruturas `route_decision`, `continuity_signal`, `pending_topics` e `multi_intent_plan` preservam informações para retomada e roteamento de turnos correlatos.
## Requisitos Não Funcionais A recuperação de falhas deve ser interpretada conforme o método efetivamente invocado: nem todo erro interno de roteamento é absorvido pelo mesmo `except`; exceções que escapem do nó alcançam o tratamento de falha do workflow em `ainvoke`.
| Categoria | Requisito | **Referências:** `libs/agent_framework/src/agent_framework/routing/config_loader.py`, `routing/enterprise_router.py`, `routing/continuity.py`; `templates/agent_template_backend/app/workflows/agent_graph.py` (`routing_decision`, `ainvoke`).
### 12.4. Execução de agentes, argumentos e ferramentas MCP
A preparação das ferramentas é realizada pelo runtime reutilizável em `runtime/agent_runtime.py`. O método `_prepare_mcp_call` consulta o roteador MCP e devolve o erro de preparação como resultado estruturado quando `prepare_call` o retorna. Se o roteador de ferramentas não estiver disponível, o runtime produz um resultado negativo com `ok=False`, `tool_name` e a descrição `MCP Tool Router indisponível`.
No mapeamento de parâmetros, erros de expressão regular (`re.error`, `IndexError`, `ValueError`) são capturados e registrados como `mcp.parameter.regex_extract_failed`. Na extração por LLM, indisponibilidade do modelo ou da mensagem e exceções de inferência são registradas como `mcp.parameter.llm_extract_failed`. O processamento dos argumentos e o retorno da chamada continuam sujeitos à validação da ferramenta e às políticas do agente; não se assume sucesso pela simples ausência de exceção.
Resultados MCP podem expor `ok=False` e um campo `error`, inclusive para falhas de validação e execução. A implementação emite `NOC.MCP_TOOL_FAILED` em um dos caminhos que agregam resultados negativos de ferramentas. O tratamento de transações, confirmações, evidências e resultados parciais é realizado sobre os dados de execução, incluindo `active_transaction`, `transaction_pre_validation`, `transaction_evidence` e `operation_results`, conforme o tipo de operação.
**Referência:** `libs/agent_framework/src/agent_framework/runtime/agent_runtime.py` (`_prepare_mcp_call`, processamento de parâmetros, execução e agregação de resultados das ferramentas).
### 12.5. RAG e recuperação de conhecimento
O runtime encapsula falhas de recuperação de conhecimento em um resultado técnico que inclui `technical_error=True`, `technical_error_in_rag=True`, `status="error"` e a descrição em `error`. Essa representação permite que o agente diferencie falha de recuperação de uma busca concluída sem evidência útil.
O serviço RAG também valida pré-condições: `RagService.generate_answer` lança `RuntimeError` quando utilizado sem LLM, e o `kbdb_service.py` possui verificações de configuração/assinatura e impede operações de ingestão/publicação quando o provider KBDB está configurado exclusivamente para serving. Na ingestão, diretório inexistente pode produzir `FileNotFoundError` e `chunk_overlap >= chunk_size` produz `ValueError`. Esses erros de inicialização e administração não devem ser confundidos com um resultado de busca vazio em atendimento.
**Referências:** `libs/agent_framework/src/agent_framework/runtime/agent_runtime.py` (tratamento técnico RAG); `rag/rag_service.py`, `rag/kbdb_service.py`, `rag/ingest.py`.
### 12.6. Memória de longo prazo
O nó `load_long_term_memory` captura exceções do `long_term_memory_manager.load(state)`. Quando a leitura falha, publica `long_term_memory.load.failed`, retorna `long_term_memories=[]`, `long_term_memory_context=""` e registra a exceção textual em `long_term_memory_load_error`. A conversa continua sem o contexto de memória recuperado naquele turno.
O nó `persist_long_term_memory` captura exceções do `long_term_memory_manager.persist_turn(state)`. Uma gravação concluída publica `long_term_memory.persist.completed` e armazena seu retorno em `long_term_memory_write_result`; uma falha publica `long_term_memory.persist.failed` e retorna `{"saved": 0, "error": str(exc)}` no mesmo campo. A falha de persistência de memória de longo prazo é, portanto, isolada no nó e não provoca automaticamente o encerramento excepcional do grafo.
Esses campos descrevem a memória de longo prazo do workflow e são distintos da persistência de checkpoints LangGraph.
**Referência:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`load_long_term_memory`, `persist_long_term_memory`).
### 12.7. Checkpoints, tentativas e integridade
O grafo é compilado com o checkpointer criado por `create_langgraph_checkpointer(self.settings)` e utiliza `conversation_key` ou `session_id` como `thread_id` em `ainvoke`. A camada de repositório em `checkpoints/checkpoint_repository.py` implementa tentativas para operações protegidas por `_with_retry`: após uma exceção, calcula espera exponencial limitada com jitter, registra `checkpoint.<operation>.retry` e tenta novamente até `retry_policy.max_attempts`. Esgotadas as tentativas, relança a última exceção.
Na recuperação, `recover_latest` examina registros recentes, desconsidera registros que não satisfazem `is_valid_checkpoint` e ignora checkpoints com `CheckpointIntegrityError`, registrando `checkpoint.recovery.skip_corrupt`. Quando não resta checkpoint válido após falhas de integridade, a recuperação retorna `None` para permitir início sem estado restaurado. A compactação executada após uma gravação é isolada: uma falha registra `checkpoint.compaction.failed` e não desfaz a gravação já concluída.
A estratégia de recuperação de integridade não garante preservação do histórico se nenhum checkpoint válido puder ser recuperado. Falhas de comunicação com o armazenamento que excedam a política de retry seguem o caminho de exceção do componente que invocou a operação.
**Referências:** `libs/agent_framework/src/agent_framework/checkpoints/checkpoint_repository.py`, `checkpoints/langgraph_saver.py`; `templates/agent_template_backend/app/workflows/agent_graph.py` (`ainvoke`).
### 12.8. Supervisão de saída e guardrails de saída
O `output_supervisor` avalia a resposta e interpreta `RailAction`. Para `ALLOW`, `SANITIZE` e `OBSERVE`, utiliza `decision.candidate`; para `HANDOVER`, entrega uma mensagem de encaminhamento ao especialista; para as demais ações, utiliza `decision.fallback_message`. A ação, orientação e resultados são gravados em `supervisor_action`, `supervisor_guidance` e `output_supervisor_results`.
O nó marca `output_guardrails_already_applied=True`. Quando `output_guardrails` recebe esse sinal, retorna a resposta já preparada sem executar novamente o pipeline. Caso contrário, executa `guardrails.run_output`, registra as decisões, os bloqueios e a conclusão GRL, e devolve `final_answer`.
O executor paralelo de rails (`guardrails/parallel_executor.py`) converte falhas inesperadas de tarefas em `RailResult`: escolhe `RailAction.BLOCK` quando `fail_closed` está ativo e `RailAction.OBSERVE` no outro caso. Esse comportamento é uma política do executor e não implica que todo guardrail falhe fechado. O executor também administra cancelamentos e término antecipado quando uma ação terminal é produzida.
**Referências:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`output_supervisor`, `output_guardrails`); `libs/agent_framework/src/agent_framework/guardrails/parallel_executor.py`.
### 12.9. Judges e revisão do supervisor
O nó `judge` constrói o contexto de avaliação com resultados MCP, RAG e evidências transacionais relevantes, executa a avaliação e grava os resultados em `judge_results`. A revisão posterior utiliza `self.supervisor.review` e registra `supervisor.review.completed`. Uma reprovação ou recomendação de um judge integra o mecanismo de avaliação e revisão; não é, por definição, uma exceção de infraestrutura.
A camada de judges contém validação de configuração e de resposta estruturada. O cliente do judge calibrado lança `ValueError` para tarefas não suportadas e quando a saída estruturada é inválida. A construção do LLM e a leitura de configurações de judges também podem produzir `RuntimeError` ou `ValueError` nas condições verificadas em `judges/judge.py`. As exceções não capturadas pelo nó propagam-se para `ainvoke`.
**Referências:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`judge`, `supervisor_review`); `libs/agent_framework/src/agent_framework/judges/judge.py`, `judges/calibrated/llm_client.py`.
### 12.10. Persistência final e falha global do workflow
O nó `persist` produz a observabilidade de conclusão do atendimento, incluindo o evento IC `AGENT_COMPLETED`. A execução pública do grafo acontece em `ainvoke`, que cria a configuração de thread, inicia a telemetria de workflow e emite os eventos de início `NOC.001` e `AGENT_STARTED` antes de invocar `self.graph.ainvoke`.
Se `graph.ainvoke` conclui, o workflow é marcado como concluído e seu estado final é retornado. Se uma exceção escapa do grafo, o `except Exception` de `ainvoke` chama `workflow_telemetry.failed("agent_workflow", exc)`, emite `NOC.005` com `error` e `exception_type` e relança a mesma exceção. Nesse caminho, o método não converte automaticamente o erro em uma resposta conversacional de sucesso.
Falhas absorvidas por nós como memória de longo prazo não acionam esse `except` global. Já erros não tratados durante roteamento, execução dos agentes, salvamento de checkpoints ou outras etapas podem alcançar esse limite e produzir a falha geral do workflow.
**Referência:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`persist`, `ainvoke`).
### 12.11. Eventos e rastreamento operacional
A instrumentação `_node` envolve a execução de cada nó em `self.langgraph_telemetry.node(name, state)`. Os mecanismos complementares usam spans de workflow, eventos semânticos e o observer para GRL, IC e NOC. Entre os registros concretos presentes no fluxo estão `session.message.rejected_after_end`, `guardrails.input.completed`, `guardrails.output.completed`, `output_supervisor.completed`, `supervisor.review.completed`, `long_term_memory.load.failed`, `long_term_memory.persist.failed`, `long_term_memory.persist.completed` e `workflow_telemetry.failed` na falha global.
Erros operacionais devem ser correlacionados por `conversation_key` ou `session_id`, juntamente com `tenant_id` e `agent_id` quando disponíveis. A ocorrência de um evento de falha de memória ou de ferramenta não implica necessariamente falha global do workflow; a determinação depende de o componente ter retornado um estado/resultado ou propagado uma exceção.
**Referências:** `templates/agent_template_backend/app/workflows/agent_graph.py`; `libs/agent_framework/src/agent_framework/observability/`.
## 13. Interfaces de integração
| Interface | Integração no runtime |
|---|---| |---|---|
| Disponibilidade | Componentes deployáveis expõem `/health` e `/ready`. | | LangGraph | Construção, compilação e execução do grafo de estado. |
| Escalabilidade | Apps stateless escalam horizontalmente. Estado conversacional fica em repositórios externos. | | Agentes de domínio | Nós especializados para faturamento, produtos, pedidos e suporte. |
| Segurança | Segredos são fornecidos por secret store ou Kubernetes Secrets. | | MCP | Seleção, parametrização e execução de ferramentas pelos agentes. |
| Observabilidade | Logs, métricas e traces usam correlação por request_id, trace_id, session_id, tenant_id e agent_id. | | RAG | Recuperação de informações incorporada à execução dos agentes. |
| Auditabilidade | Decisões de rota, guardrail, judge, MCP e LLM são rastreáveis. | | Guardrails | Avaliação da entrada e da saída. |
| Portabilidade | Execução suportada em local, Docker Compose e Kubernetes/OKE. | | Judges | Avaliação posterior à geração da resposta. |
| Configuração | Comportamento variável é controlado por `.env` e YAML versionado. | | Memória | Leitura e escrita de informações de longo prazo. |
| Checkpointer | Persistência do estado do grafo. |
| Observabilidade | Telemetria por nó e rastreamento do processamento. |
## 14. Referências de implementação
## Critérios de Aceite - `libs/agent_framework/src/agent_framework/runtime/`
- `templates/agent_template_backend/app/state.py`
- [ ] Runtime recebe GatewayRequest validado. - `templates/agent_template_backend/app/workflows/agent_graph.py`
- [ ] State contém tenant_id, agent_id, session_id, conversation_key, route e intent. - `templates/agent_template_backend/config/agents.yaml`
- [ ] Input guardrails executam antes do roteamento. - `templates/agent_template_backend/config/routing.yaml`
- [ ] Router ou Supervisor seleciona rota. - `templates/agent_template_backend/config/tools.yaml`
- [ ] Agent Node executa sem acessar payload bruto de canal. - [`SPEC-004 — MCP Gateway`](SPEC-004-MCP-Gateway.md)
- [ ] MCP é acessado por contrato. - [`SPEC-005 — Guardrails`](SPEC-005-Guardrails.md)
- [ ] RAG é acessado por serviço reutilizável. - [`SPEC-007 — Observability`](SPEC-007-Observability.md)
- [ ] Output guardrails executam antes da resposta final. - [`SPEC-012 — Canonical Contracts`](SPEC-012-Canonical-Contracts.md)
- [ ] Judges geram JudgeResult.
- [ ] Memória e checkpoint são persistidos conforme provider.
- [ ] Hosts transacionais declaram `active_transaction` e `last_transaction` no `AgentState`.
- [ ] Durante `COLLECTING_PARAMETERS`, respostas a parâmetros pendentes têm precedência sobre keyword routing genérico.
- [ ] Erros geram NOC e resposta controlada.
## Glossário
| Termo | Definição |
|---|---|
| Agent Platform | Plataforma composta por runtime, gateways, evaluator, templates, contratos e componentes operacionais. |
| Agent Framework | Biblioteca/core reutilizável com contratos, guardrails, judges, memória, telemetria, providers e utilitários. |
| Agent Runtime | Motor de execução de agentes baseado em LangGraph, estado, sessão, memória, checkpoints, roteamento e ciclo de vida. |
| Agent Gateway | Aplicação deployável de entrada, roteamento e orquestração entre backends/agentes. |
| Channel Gateway | Aplicação ou módulo de normalização de payloads de canais para GatewayRequest. |
| AI Gateway | Aplicação de governança, roteamento e abstração de chamadas LLM/embedding. |
| MCP Gateway | Aplicação de governança e roteamento de tools MCP. |
| Evaluator | Camada de avaliação online/offline, regressão e certificação. |
| Business Context | Conjunto de chaves canônicas de negócio: customer_key, contract_key, interaction_key, account_key, resource_key e session_key. |