# SPEC-012 — Canonical Contracts ## Agent Platform OCI Version: 1.0.0 --- ## Padrão de leitura Cada SPEC está organizada para servir tanto como contrato arquitetural quanto como guia prático de adoção. A estrutura usada é: 1. Conceito. 2. Problema que resolve. 3. Quando usar. 4. Quando não usar. 5. Arquitetura. 6. Implementação. 7. Exemplos. 8. Erros comuns. 9. Critérios de aceite. --- # 1. Conceito Contratos canônicos são estruturas padronizadas usadas para desacoplar canais, gateways, runtime, agentes, tools, LLMs, evaluator e observabilidade. A plataforma usa contratos para garantir que componentes independentes possam evoluir sem quebrar uns aos outros. # 2. Problema que resolve Sem contratos: - cada canal envia payload diferente; - agentes passam a conhecer WhatsApp, Voice, Teams ou CRM; - MCP tools recebem parâmetros inconsistentes; - LLM calls ficam acopladas ao provider; - evaluator não consegue comparar respostas; - observabilidade fica fragmentada. Com contratos: ```text Canal → GatewayRequest → Runtime → BusinessContext → ToolInvocation → ToolResult ``` # 3. Catálogo de contratos | Contrato | Uso | | --- | --- | | GatewayRequest | Entrada canônica da plataforma. | | ChannelResponse | Resposta canônica ao canal. | | BusinessContext | Identidade canônica de negócio. | | AgentState | Estado interno do runtime. | | Session | Sessão técnica/conversacional. | | Checkpoint | Persistência de estado LangGraph. | | ToolInvocation | Chamada canônica de tool MCP. | | ToolResult | Resposta canônica de tool MCP. | | LLMRequest | Chamada canônica ao AI Gateway. | | LLMResponse | Resposta canônica do AI Gateway. | | EvaluationRun | Execução do evaluator. | | EvaluationResult | Resultado de avaliação. | | CertificationResult | Resultado de certificação. | | EventEnvelope | Envelope de eventos IC/NOC/GRL. | # 4. GatewayRequest ## 4.1. Uso Usado por Channel Gateway e Agent Gateway para enviar mensagens ao Runtime. ```json { "channel": "web", "tenant_id": "default", "agent_id": "telecom_contas", "payload": { "message": "Quero consultar minha fatura", "session_id": "session-001", "user_id": "user-001", "message_id": "msg-001", "business_context": { "customer_key": "11999999999", "contract_key": "3000131180", "interaction_key": "301953872", "session_key": "session-001" }, "metadata": { "request_id": "req-001", "contract_version": "gateway-request-v1" } } } ``` ## 4.2. Campos obrigatórios - `channel`; - `payload.message`; - `payload.session_id`; - `payload.message_id`; - `tenant_id` quando multi-tenant; - `agent_id` quando não houver roteamento global. # 5. ChannelResponse ```json { "channel": "web", "session_id": "default:telecom_contas:session-001", "text": "Resposta final do agente.", "metadata": { "tenant_id": "default", "agent_id": "telecom_contas", "route": "billing_agent", "intent": "billing_invoice_explanation", "guardrails": [], "judges": [] } } ``` # 6. BusinessContext ## 6.1. Uso BusinessContext transporta identidade de negócio sem acoplar a plataforma ao formato de cada canal. ```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 ``` ## 6.2. Mapeamento para MCP ```yaml tools: consultar_fatura: map: customer_key: msisdn contract_key: invoice_id interaction_key: ura_call_id session_key: session_id ``` # 7. AgentState ```python 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 route: str intent: str business_context: dict mcp_tools: list[str] mcp_results: list[dict] rag_context: str guardrails: list[dict] judges: list[dict] ``` # 8. ToolInvocation ```json { "tenant_id": "default", "agent_id": "telecom_contas", "tool_name": "consultar_fatura", "arguments": { "msisdn": "11999999999", "invoice_id": "3000131180" }, "business_context": { "customer_key": "11999999999", "contract_key": "3000131180" }, "metadata": { "request_id": "req-001", "trace_id": "trace-001" } } ``` # 9. ToolResult ```json { "tool_name": "consultar_fatura", "ok": true, "data": { "invoice_id": "3000131180", "valor_total": 249.90, "status": "ABERTA" }, "cache": { "hit": false, "ttl_seconds": 300 }, "latency_ms": 140 } ``` # 10. LLMRequest ```json { "tenant_id": "default", "agent_id": "telecom_contas", "profile": "judge", "operation": "judge.response_quality", "messages": [ {"role": "system", "content": "Você é um avaliador."}, {"role": "user", "content": "Avalie a resposta."} ], "metadata": { "request_id": "req-001", "trace_id": "trace-001" } } ``` # 11. LLMResponse ```json { "provider": "oci_openai", "model": "openai.gpt-4.1", "profile": "judge", "content": "Resultado", "usage": { "input_tokens": 1200, "output_tokens": 300, "total_tokens": 1500 }, "latency_ms": 820 } ``` # 12. EvaluationRun ```json { "run_id": "eval-001", "agent_id": "telecom_contas", "source": "langfuse", "period_start": "2026-06-18T00:00:00Z", "period_end": "2026-06-19T00:00:00Z", "status": "running" } ``` # 13. EventEnvelope ```json { "event_type": "IC.AGENT_COMPLETED", "timestamp": "2026-06-19T12:00:00Z", "tenant_id": "default", "agent_id": "telecom_contas", "session_id": "session-001", "trace_id": "trace-001", "payload": {} } ``` # 14. Regras de evolução - campos novos devem ser opcionais; - campos obrigatórios não podem ser removidos dentro da mesma major; - mudança semântica exige nova versão; - contratos são versionados independentemente. # 15. Erros comuns | Erro | Impacto | Correção | | --- | --- | --- | | Payload bruto no Runtime | Acopla canais ao core. | Usar GatewayRequest. | | Tool recebendo BusinessContext bruto sem mapping | Quebra contrato da tool. | Usar mcp_parameter_mapping.yaml. | | LLM direto no agente | Quebra AI Gateway. | Usar LLMRequest/profile. | | Campos sem versão | Dificulta migração. | Declarar contract_version. | # 16. Critérios de aceite - [ ] GatewayRequest documentado e versionado. - [ ] ChannelResponse documentado e versionado. - [ ] BusinessContext usado por canais e MCP. - [ ] ToolInvocation e ToolResult padronizados. - [ ] LLMRequest e LLMResponse padronizados. - [ ] EvaluationRun e EvaluationResult padronizados. - [ ] EventEnvelope usado para IC/NOC/GRL. - [ ] Contratos possuem regras de evolução.