First commit

This commit is contained in:
2026-10-30 22:04:44 -03:00
commit 645ecdfb07
2794 changed files with 282545 additions and 0 deletions

View File

@@ -0,0 +1,331 @@
# SPEC-002 — Agent Runtime
## 1. Visão geral
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.
## 2. Organização da implementação
| Elemento | Localização | Função |
|---|---|---|
| Runtime compartilhado | `libs/agent_framework/src/agent_framework/runtime/` | Capacidades reutilizáveis para execução dos agentes. |
| 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. |
| Estado do workflow | `templates/agent_template_backend/app/state.py` | Definição tipada dos dados transportados entre nós. |
| Configuração dos agentes | `templates/agent_template_backend/config/agents.yaml` | Cadastro de agentes e caminhos de políticas/configurações. |
| Configuração de roteamento | `templates/agent_template_backend/config/routing.yaml` | Modo do roteador, fallback, limiar e catálogo de intenções. |
| Configuração das ferramentas | `templates/agent_template_backend/config/tools.yaml` | Definições de ferramentas utilizadas pelos agentes. |
## 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
from typing import Any, TypedDict
class AgentState(TypedDict, total=False):
tenant_id: str
agent_id: str
session_id: str
conversation_key: str
workflow_id: str
agent_profile: dict[str, Any]
user_text: str
sanitized_input: str
route: str
intent: str
route_decision: dict[str, Any]
answer: str
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_results: list[dict[str, Any]]
rag_results: list[dict[str, Any]]
available_mcp_tools: list[str]
selected_tool_call: dict[str, Any]
pending_tool_call: dict[str, Any]
active_transaction: dict[str, Any]
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
O workflow é compilado com `FrameworkStateGraph(AgentState)` e utiliza um checkpointer criado por `create_langgraph_checkpointer(self.settings)`.
```mermaid
flowchart TD
START([START]) --> input_guardrails
input_guardrails -->|continue| load_long_term_memory
input_guardrails -->|blocked| output_guardrails
load_long_term_memory --> routing_decision
routing_decision --> billing_agent
routing_decision --> product_agent
routing_decision --> orders_agent
routing_decision --> support_agent
routing_decision --> handoff
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])
```
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']`.
## 5. Nós do workflow
| 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
# 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
fallback_agent: billing_agent
confidence_threshold: 0.65
allow_handoff: true
```
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`.
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.
## 7. Execução dos agentes e ferramentas
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`.
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.
## 8. Estado transacional
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.
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`.
A documentação de referência dos fluxos transacionais encontra-se em [`docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md`](../docs/TRANSACTION_STATE_DEVELOPER_GUIDE.md).
## 9. Memória e checkpoints
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.
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.
## 10. Guardrails, supervisão e judges
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`.
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.
## 11. Observabilidade
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.
## 12. Tratamento de erros e recuperação por componente
### 12.1. Princípios de propagação de falhas
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.
| Área | Representação utilizada | Efeito na execução |
|---|---|---|
| Guardrails | Decisões com `allowed`, `code` e `reason`; decisões da supervisão com `action` | Pode interromper roteamento, substituir/sanitizar a resposta ou continuar. |
| 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. |
| 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. |
| RAG | Resultado de recuperação ou objeto de erro técnico | A falha pode ser incorporada ao contexto de execução do agente. |
| 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. |
| 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.
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.
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`.
**Referência:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`input_guardrails`, `_input_guardrail_user_message`, `_after_input_guardrails`).
### 12.3. Roteamento, classificação e continuidade
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.
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`.
**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 |
|---|---|
| LangGraph | Construção, compilação e execução do grafo de estado. |
| Agentes de domínio | Nós especializados para faturamento, produtos, pedidos e suporte. |
| MCP | Seleção, parametrização e execução de ferramentas pelos agentes. |
| RAG | Recuperação de informações incorporada à execução dos agentes. |
| Guardrails | Avaliação da entrada e da saída. |
| Judges | Avaliação posterior à geração da resposta. |
| 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
- `libs/agent_framework/src/agent_framework/runtime/`
- `templates/agent_template_backend/app/state.py`
- `templates/agent_template_backend/app/workflows/agent_graph.py`
- `templates/agent_template_backend/config/agents.yaml`
- `templates/agent_template_backend/config/routing.yaml`
- `templates/agent_template_backend/config/tools.yaml`
- [`SPEC-004 — MCP Gateway`](SPEC-004-MCP-Gateway.md)
- [`SPEC-005 — Guardrails`](SPEC-005-Guardrails.md)
- [`SPEC-007 — Observability`](SPEC-007-Observability.md)
- [`SPEC-012 — Canonical Contracts`](SPEC-012-Canonical-Contracts.md)