mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-11-05 19:04:13 +00:00
fix: Spec Agent Runtime
This commit is contained in:
3
.idea/workspace.xml
generated
3
.idea/workspace.xml
generated
@@ -179,7 +179,8 @@
|
||||
<workItem from="1785453511270" duration="1006000" />
|
||||
<workItem from="1792665278602" duration="734000" />
|
||||
<workItem from="1793193595355" duration="436000" />
|
||||
<workItem from="1793194079956" duration="4230000" />
|
||||
<workItem from="1793194079956" duration="5443000" />
|
||||
<workItem from="1793271962068" duration="758000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Ajustes na documentação e remanejamento dos folders">
|
||||
<option name="closed" value="true" />
|
||||
|
||||
@@ -1,268 +1,331 @@
|
||||
# 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 |
|
||||
|---|---|
|
||||
| Workflow Builder | Compila o grafo LangGraph. |
|
||||
| State Manager | Mantém o estado de execução. |
|
||||
| Session Manager | Resolve sessão e conversation_key. |
|
||||
| Memory Manager | Carrega e persiste histórico. |
|
||||
| Checkpoint Manager | Persiste estado LangGraph. |
|
||||
| Input Guardrail Node | Executa guardrails de entrada. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
|
||||
## 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
|
||||
from typing import Any, TypedDict
|
||||
|
||||
class AgentState(TypedDict, total=False):
|
||||
user_text: str
|
||||
sanitized_input: str
|
||||
response_text: str
|
||||
tenant_id: str
|
||||
agent_id: str
|
||||
channel: str
|
||||
session_id: str
|
||||
conversation_key: str
|
||||
message_id: str
|
||||
workflow_id: str
|
||||
agent_profile: dict[str, Any]
|
||||
user_text: str
|
||||
sanitized_input: str
|
||||
route: str
|
||||
intent: str
|
||||
context: dict
|
||||
business_context: dict
|
||||
tool_arguments: dict
|
||||
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]
|
||||
rag_context: str
|
||||
rag_metadata: dict
|
||||
guardrails: list[dict]
|
||||
judges: list[dict]
|
||||
metadata: dict
|
||||
errors: list[dict]
|
||||
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
|
||||
|
||||
## Workflow
|
||||
O workflow é compilado com `FrameworkStateGraph(AgentState)` e utiliza um checkpointer criado por `create_langgraph_checkpointer(self.settings)`.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[start] --> B[input_guardrails]
|
||||
B --> C[routing_decision]
|
||||
C --> D[agent_execution]
|
||||
D --> E[output_supervisor]
|
||||
E --> F[output_guardrails]
|
||||
F --> G[judge]
|
||||
G --> H[persist]
|
||||
H --> I[end]
|
||||
C --> J[handoff]
|
||||
J --> C
|
||||
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])
|
||||
```
|
||||
|
||||
## 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 |
|
||||
|---|---|---|
|
||||
| `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 |
|
||||
## 5. Nós do workflow
|
||||
|
||||
## 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
|
||||
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
|
||||
fallback_agent: billing_agent
|
||||
enable_llm_router: false
|
||||
intents:
|
||||
billing_invoice_explanation:
|
||||
route: billing_agent
|
||||
keywords:
|
||||
- fatura
|
||||
- cobrança
|
||||
- boleto
|
||||
mcp_tools:
|
||||
- consultar_fatura
|
||||
- consultar_pagamentos
|
||||
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`.
|
||||
|
||||
## 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
|
||||
supervisor:
|
||||
enabled: true
|
||||
profile: supervisor
|
||||
max_turns: 5
|
||||
handoff_enabled: true
|
||||
fallback_route: support_agent
|
||||
```
|
||||
## 7. Execução dos agentes e ferramentas
|
||||
|
||||
## 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 |
|
||||
|---|---|
|
||||
| `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. |
|
||||
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.
|
||||
|
||||
## 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
|
||||
{
|
||||
"conversation_key": "default:telecom_contas:session-001",
|
||||
"checkpoint_id": "ckpt-001",
|
||||
"state": {},
|
||||
"pending_writes": [],
|
||||
"created_at": "2026-06-19T12:00:00Z"
|
||||
}
|
||||
```
|
||||
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`.
|
||||
|
||||
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
|
||||
pending_writes: list[tuple[str, str, object]]
|
||||
```
|
||||
## 9. Memória e checkpoints
|
||||
|
||||
## 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
|
||||
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
|
||||
```
|
||||
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.
|
||||
|
||||
## Ordem de Prioridade dos Dados
|
||||
## 10. Guardrails, supervisão e judges
|
||||
|
||||
1. `tool_arguments`
|
||||
2. `business_context`
|
||||
3. `context`
|
||||
4. `session.metadata`
|
||||
5. `state`
|
||||
6. extração complementar do texto
|
||||
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`.
|
||||
|
||||
## 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
|
||||
flowchart LR
|
||||
AgentNode --> ToolList[mcp_tools]
|
||||
ToolList --> Mapping[mcp_parameter_mapping.yaml]
|
||||
Mapping --> MCP[MCP Gateway/Router]
|
||||
MCP --> Result[mcp_results]
|
||||
```
|
||||
## 11. Observabilidade
|
||||
|
||||
## 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
|
||||
rag:
|
||||
enabled: true
|
||||
namespace_strategy: agent_id
|
||||
top_k: 5
|
||||
profile_generation: rag_generation
|
||||
```
|
||||
## 12. Tratamento de erros e recuperação por componente
|
||||
|
||||
## Eventos
|
||||
### 12.1. Princípios de propagação de falhas
|
||||
|
||||
| Evento | Descrição |
|
||||
|---|---|
|
||||
| `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. |
|
||||
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.
|
||||
|
||||
## Erros
|
||||
|
||||
| Código | Condição | Tratamento |
|
||||
| Área | Representação utilizada | Efeito na execução |
|
||||
|---|---|---|
|
||||
| `RUNTIME_INVALID_REQUEST` | GatewayRequest inválido | 422 |
|
||||
| `RUNTIME_ROUTE_NOT_FOUND` | Nenhuma rota elegível | fallback ou resposta controlada |
|
||||
| `RUNTIME_CHECKPOINT_ERROR` | Falha em checkpoint | retry ou stateless conforme config |
|
||||
| `RUNTIME_MEMORY_ERROR` | Falha em memória | retry ou resposta controlada |
|
||||
| `RUNTIME_AGENT_ERROR` | Falha no agente | NOC + fallback |
|
||||
| `RUNTIME_TIMEOUT` | Timeout geral | resposta controlada |
|
||||
| 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.
|
||||
|
||||
## 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
|
||||
active_transaction: dict[str, Any]
|
||||
last_transaction: dict[str, Any]
|
||||
```
|
||||
**Referência:** `templates/agent_template_backend/app/workflows/agent_graph.py` (`input_guardrails`, `_input_guardrail_user_message`, `_after_input_guardrails`).
|
||||
|
||||
`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`. |
|
||||
| Escalabilidade | Apps stateless escalam horizontalmente. Estado conversacional fica em repositórios externos. |
|
||||
| Segurança | Segredos são fornecidos por secret store ou Kubernetes Secrets. |
|
||||
| Observabilidade | Logs, métricas e traces usam correlação por request_id, trace_id, session_id, tenant_id e agent_id. |
|
||||
| Auditabilidade | Decisões de rota, guardrail, judge, MCP e LLM são rastreáveis. |
|
||||
| Portabilidade | Execução suportada em local, Docker Compose e Kubernetes/OKE. |
|
||||
| Configuração | Comportamento variável é controlado por `.env` e YAML versionado. |
|
||||
| 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
|
||||
|
||||
## Critérios de Aceite
|
||||
|
||||
- [ ] Runtime recebe GatewayRequest validado.
|
||||
- [ ] State contém tenant_id, agent_id, session_id, conversation_key, route e intent.
|
||||
- [ ] Input guardrails executam antes do roteamento.
|
||||
- [ ] Router ou Supervisor seleciona rota.
|
||||
- [ ] Agent Node executa sem acessar payload bruto de canal.
|
||||
- [ ] MCP é acessado por contrato.
|
||||
- [ ] RAG é acessado por serviço reutilizável.
|
||||
- [ ] Output guardrails executam antes da resposta final.
|
||||
- [ ] 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. |
|
||||
- `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)
|
||||
|
||||
Reference in New Issue
Block a user