# Relatório de Correções — Agent Framework OCI + Contas

Data: 2026-08-28  
Base analisada: `agent_contas_oci_template (6).zip`

## 1. Objetivo

Este trabalho tratou as frentes técnicas identificadas a partir do comparativo de 30 replays e, principalmente, dos contratos de regressão já existentes no próprio projeto. A separação arquitetural foi preservada:

- **Framework**: lifecycle transacional, coleta genérica de parâmetros, confirmação, snapshot, roteamento/continuidade, guardrails e infraestrutura horizontal.
- **Agent Contas / domínio / MCP**: semântica TIM, prompts voltados ao cliente, contrato das capabilities, evidência de fatura, regras de contestação, pró-rata e mapeamentos de integração.

Nenhuma regra TIM foi movida para o core do framework.

## 2. Correções realizadas no framework

### 2.1 Coleta de parâmetros sem expor nomes internos

**Problema**  
O runtime possuía um pequeno dicionário hardcoded para `order_id`, `reason` e `customer_id` e, para qualquer outro parâmetro, podia produzir o nome técnico convertido para texto. Isso explica respostas da família `informe subject` apontadas no relatório.

**Correção**  
O framework agora usa metadados declarados pelo agente em `args_schema`:

- `user_prompt`: pergunta exata voltada ao cliente, com maior prioridade;
- `label`: rótulo amigável opcional;
- `description`: fallback semântico;
- sem metadados: pergunta neutra que **não expõe o nome técnico**.

Além disso, o framework pergunta **um parâmetro por vez**, embora o extrator LLM continue capaz de consumir vários valores espontaneamente informados no mesmo turno.

**Resultado arquitetural**  
O framework continua sem saber o significado de `subject`, `valor`, `order_id` etc. A semântica pertence ao agente.

### 2.2 Snapshot imutável da confirmação

**Problema**  
Havia `pending_tool_call` e `active_transaction`, mas não existia um snapshot separado e explícito que representasse exatamente a operação apresentada ao usuário no momento da confirmação.

**Correção**  
Foi introduzido `confirmation_snapshot`, contendo:

- `transaction_id`;
- `tool_name`;
- cópia dos `arguments`;
- `started_from_intent`.

Ao entrar em `AWAITING_CONFIRMATION`, o snapshot é congelado. Um `sim` executa **esse snapshot**, mesmo que `active_transaction`, `pending_tool_call` ou outro contexto seja alterado depois. Ao concluir/cancelar a transação, o snapshot operacional é limpo.

**Benefício**  
Garante o contrato:

> confirmar = executar exatamente tool + parâmetros que estavam congelados quando a confirmação foi solicitada.

### 2.3 Itens do framework já presentes nesta versão e apenas revalidados

Não foram duplicadas correções que já estavam na base recebida:

- extração LLM de parâmetros transacionais;
- precedência de confirmação explícita;
- `transaction_interruption=intent_shift`;
- encerramento/limpeza de transações `COMPLETED`, `FAILED`, `CANCELLED`, `BLOCKED`, `OUT_OF_SCOPE`;
- route stickiness sem reaproveitar transação terminal;
- replay pós-finalização sem reabrir atendimento;
- validação direta de `expected_protocols` no CMP;
- isolamento do contexto operacional dos guardrails após intent shift no Contas.

## 3. Correções realizadas no Agent Contas / MCP

### 3.1 Prompts declarativos dos parâmetros

Foram adicionados `user_prompt` às capabilities transacionais:

- `cancelar_vas_avulso.subject` → `Qual serviço você deseja cancelar?`
- `tratar_vas_estrategico.subject` → `Qual serviço ou benefício você deseja tratar?`
- `validar_contestacao.subject` → `Qual cobrança ou item você não reconhece?`
- `validar_contestacao.valor` → `Qual é o valor da cobrança?`
- `contestar_cobranca.subject` → `Qual cobrança ou item você deseja contestar?`
- `contestar_cobranca.valor` → `Qual é o valor da cobrança que você deseja contestar?`

Assim, a linguagem de atendimento fica no domínio e o framework apenas executa o contrato.

### 3.2 Capability `buscar_informacao` restaurada sem duplicar RAG

A capability voltou a existir no registry/MCP para manter paridade de contrato, mas não reimplementa recuperação no domínio.

Ela devolve um contrato explícito:

- `requires_rag=true`;
- `source=agent_framework.rag`;
- `rag_queries=[...]`.

Portanto, a API antiga é preservada e o RAG continua sendo responsabilidade do framework.

### 3.3 `invoice_explanation` preserva evidência suficiente para composição

O retorno passa a preservar também:

- `invoice_detail`;
- `invoice_amount`;
- `invoice_period`;
- `invoice_emissao`.

A action `formatar_invoice_explanation` agora sinaliza:

- `await_user_input=true`;
- `requires_llm_composition=true`;
- `response_instruction` de composição grounded;
- preservação da pergunta `Com essa explicação, sanei sua dúvida?`.

### 3.4 Pró-rata determinístico e fail-closed

Foram restaurados helpers de preparação do pró-rata:

- derivação determinística dos planos a partir do PDF parseado;
- uso da visão contratual por linha, evitando confundir DANFE com plano consolidado;
- identificação de plano controle;
- exigência de **exatamente dois planos**;
- falha fechada com `requires_exactly_two_plans` quando o contrato não é atendido.

Nenhum LLM é usado nessa decisão.

### 3.5 CVAL aplicado também na pré-validação

`validar_contestacao` deixou de apenas aceitar o item após o preflight e passou a executar a mesma validação CVAL usada antes do efeito financeiro.

A validação usa:

- item resolvido;
- **valor originalmente solicitado pelo cliente**;
- evidência de `billing_analysis`;
- `validation_log` estruturado.

Valor solicitado acima do valor comprovado é bloqueado com `reason=CVAL` e erro `valor_ajuste_maior_que_item`.

Foi corrigido também um teste de regressão inconsistente: ele exigia aprovar R$ 50 para um item comprovado em R$ 10, ao mesmo tempo em que dizia proteger a regra “valor não pode exceder o item”. O caso positivo foi ajustado para R$ 10; a implementação não foi enfraquecida para satisfazer uma expectativa insegura.

### 3.6 Grounding de término de desconto e valor divergente

`termino_desconto` foi endurecido para não transformar uma hipótese de negócio em fato. O workflow só informa causa de retirada/término quando a evidência de backend/mock contém um campo causal explicitamente associado a desconto/promoção (por exemplo `discount_reason`, `terminationReason`, status de desconto/promoção encerrado ou data de término registrada). Contadores como `1/12`, `8/12` ou `12/12`, ausência de desconto na fatura e o próprio texto do cliente não são tratados como prova de expiração.

Quando a causa não está disponível, a resposta informa que os dados existentes não registram o motivo, sem afirmar fim de fidelidade ou expiração promocional.

`valor_divergente` preserva a semântica de alteração do valor do plano e referência segura ao final da linha, conforme contrato de regressão.

### 3.7 Status de solicitação não usa `interaction_key` como protocolo

Foi removido:

`interaction_key -> protocol`

O protocolo agora é extraído explicitamente da mensagem, impedindo que `message_id`/`interaction_key` seja tratado como protocolo de atendimento.

### 3.8 Finalização exige status explícito

`finalizar_atendimento` agora declara `status` em `requires`, e o mapping possui extração explícita do campo. Isso preserva o contrato de domínio e evita finalização sem estado definido.

### 3.9 Prompt de billing mais grounded

O `FaturasAgent` recebeu regra explícita para não transformar ausência de evidência em hipótese factual. Sem evidência, ele não pode afirmar como causa:

- fim de promoção;
- perda de elegibilidade;
- alteração de consumo;
- reajuste tarifário;
- mudança de plano.

Isso endereça diretamente o comportamento observado no comparativo, em que hipóteses eram apresentadas como explicação.

### 3.10 Prompt de suporte não simula efeitos de lifecycle

O `SuporteContasAgent` foi reforçado para não anunciar em texto livre:

- transferência;
- encerramento;
- protocolo;
- sucesso operacional.

Resultados terminais devem refletir apenas o estado/tool atual. Handoff e finalização continuam controlados pela orquestração.

## 4. Fontes alterados

### Framework

| Arquivo | Alteração |
|---|---|
| `agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py` | Prompt declarativo de parâmetros; remoção de labels hardcoded; pergunta neutra sem leak; `confirmation_snapshot`; execução a partir do snapshot; limpeza do snapshot no lifecycle. |
| `agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py` | Sincronizado com o source para manter o artefato de build consistente. |
| `agent_framework_oci/tests/test_transactional_tool_flow.py` | Regressões para `user_prompt`, ausência de leak de nome técnico e confirmação por snapshot imutável. |

### Agent Contas / MCP

| Arquivo | Alteração |
|---|---|
| `config/tools.yaml` | `user_prompt` dos parâmetros; capability `buscar_informacao`; `finalizar_atendimento.status` obrigatório. |
| `config/mcp_parameter_mapping.yaml` | Protocolo deixa de vir de `interaction_key`; extração explícita de `protocol`; extração explícita de `status` na finalização. |
| `config/prompts/billing.yaml` | Proibição explícita de hipóteses causais sem evidência. |
| `config/prompts/support.yaml` | Não simular handoff/finalização/protocolo; tratamento terminal grounded. |
| `app/domain/contas/service.py` | `buscar_informacao`; preservação de `invoice_detail`, amount, period e emissão em `invoice_explanation`. |
| `app/domain/contas/workflow_actions.py` | Metadados de composição LLM/await no invoice explanation; semântica de `termino_desconto` e `valor_divergente`. |
| `contas_mcp/servers/contas_mcp_server/main.py` | Registro `buscar_informacao`; helpers de pró-rata; preparação fail-closed; CVAL na pré-validação; dispatch das novas/restauradas capabilities. |
| `tests/migration/test_framework_agent_gap_fixes.py` | Novos contratos de regressão framework × agente. |
| `tests/migration/test_requested_tools_parity_pente_fino.py` | Correção do caso positivo CVAL inconsistente (R$50 → R$10 comprovados). |

## 5. Validação executada

### Framework — testes focados das frentes alteradas

Resultado:

`40 passed`

Incluiu:

- transaction tool flow;
- confirmação voltada ao cliente;
- extração LLM/prevalência de parâmetros;
- route stickiness / intent shift;
- novos testes de snapshot e user-facing parameter contract.

### Agent Contas — regressão completa de migração

Resultado final:

`729 passed`

Antes das correções, o `test_requested_tools_parity_pente_fino.py` expunha 11 falhas. Após as correções:

`14 passed` nesse arquivo e `729 passed` em toda `tests/migration`.

### Suíte completa do framework

Resultado observado na árvore corrigida:

- `225 passed`
- `10 failed`

Os mesmos 10 casos foram executados contra o ZIP original recebido e falham da mesma forma. Portanto são **falhas preexistentes e não introduzidas por este patch**. Estão concentradas em:

- compatibilidade de double de LLM em um teste unitário;
- checkpoint repository/recovery;
- compact telemetry Langfuse legado;
- transactional workflow unit tests;
- dois testes estáticos que procuram um layout de `agent_template_backend` inexistente nesse caminho.

Esses itens não pertencem às frentes do comparativo tratadas neste patch e não foram mascarados.

## 6. Relação com o relatório comparativo

### Problemas do relatório atacados diretamente

- nomes internos de parâmetros na fala;
- coleta transacional sem contrato amigável;
- confirmação sem snapshot explícito;
- risco de reinterpretar argumentos depois do pedido de confirmação;
- explicação de cobrança baseada em hipótese sem evidência;
- gaps de capability/paridade MCP já formalizados pelos testes do projeto;
- pró-rata sem preparação determinística completa;
- pre-validation/CVAL incompleta;
- confusão entre identificador de interação e protocolo;
- finalização sem `status` obrigatório.

### Problemas que já estavam corrigidos nesta versão recebida

- intent shift durante transação;
- limpeza de transação terminal;
- replay pós-finalização;
- barge-in pós-finalização no framework de interrupção;
- `expected_protocols`/CMP;
- contexto histórico de transação anterior nos guardrails do Contas.

## 7. Pontos que continuam sendo política de negócio do Contas

Não foram movidos para o framework, de propósito:

- escada comercial de retenção TIM;
- quando exatamente transferir para humano após retenção;
- primeira/segunda ocorrência de fora de escopo;
- escalonamento jurídico/Anatel específico TIM;
- política de ressarcimento em dobro;
- interpretação de conjuntos de cobranças como “nenhuma delas/todas”; 
- regras específicas de VAS avulso/estratégico e ações comerciais.

Esses comportamentos devem ser implementados/testados no domínio Contas quando os cenários executáveis correspondentes estiverem disponíveis. O pacote recebido não contém os 30 YAMLs de replay citados no PDF, portanto este relatório **não afirma** que os 30 replays agora passam; afirma apenas os resultados das suítes efetivamente presentes e executadas no pacote.

## 8. Conclusão

A principal correção estrutural foi tornar a fronteira mais clara:

- o **framework** controla coleta, lifecycle e confirmação sem expor nomes internos e sem reinterpretar o que foi confirmado;
- o **agente Contas** fornece a linguagem de negócio e os contratos/evidências específicos;
- o **MCP Contas** mantém capabilities e validações determinísticas de domínio sem absorver responsabilidades de conversa/RAG do framework.

A regressão do Contas presente no projeto ficou integralmente verde (`729 passed`).

### Serviço MCP de histórico de descontos

Foi adicionada a tool interna `consultar_historico_descontos` para representar a fonte autoritativa de status e término de descontos. O mock está em `app/domain/contas/fixtures/discount_history.json` e a implementação em `contas_mcp/servers/contas_mcp_server/discount_history_service.py`.

`termino_desconto` consulta esse serviço obrigatoriamente e só verbaliza uma causa quando `termination_reason`, `termination_reason_description` ou outro campo causal explicitamente permitido estiver presente. Códigos técnicos permanecem em metadados; a resposta usa a descrição legível do sistema. Sem causa explícita, o fluxo continua fail-closed.

O mock também distingue explicitamente a **situação contratual na data de referência** da **última fatura emitida**. No cenário atual, `current_value=0` significa valor contratual do desconto em `as_of_date=2025-11-20`; a última fatura cobre `14/10 a 13/11` e ainda registra R$ 80,00 de desconto. Isso é temporalmente consistente: o desconto estava vigente no período faturado e aparece como encerrado na situação contratual de 20/11/2025. Os campos `last_billed_discount_value`, `last_billed_period`, `last_invoice_issue_date` e `current_value_reference` documentam essa diferença.
