diff --git a/MANUAL_REGRAS_AGENTE_CONTAS.md b/MANUAL_REGRAS_AGENTE_CONTAS.md index 06dc9879..bc242631 100644 --- a/MANUAL_REGRAS_AGENTE_CONTAS.md +++ b/MANUAL_REGRAS_AGENTE_CONTAS.md @@ -2,6 +2,1310 @@ > Versão aprofundada gerada a partir do pacote `agent_contas_oci_template (9)(1).zip`. O objetivo é permitir entender **por que** o agente escolheu uma regra, como os componentes estão amarrados e onde diagnosticar decisões inesperadas. + +# Prefácio técnico — como funciona o motor de decisão do Agente de Contas + +Antes de estudar cada regra individualmente, é importante entender que o Agente de Contas **não decide o que fazer por um único classificador de intenção**. O comportamento final é resultado de uma cadeia de mecanismos coordenados pelo Agent Framework OCI e especializados pelo domínio Contas. + +Uma mensagem pode: + +- ser bloqueada ou sanitizada por guardrails; +- continuar uma transação que já estava em andamento; +- preencher um parâmetro que estava faltando; +- corrigir um parâmetro informado anteriormente; +- abandonar explicitamente uma transação anterior; +- retomar um workflow pausado; +- produzir uma ou várias intents; +- ser reclassificada com base no contexto; +- selecionar uma tool; +- ter essa tool alterada por uma validação de domínio; +- exigir confirmação antes de executar; +- iniciar ou retomar um workflow transacional; +- produzir resultados parciais diferentes para vários itens; +- passar por guardrails de saída; +- ser avaliada por judges; +- ser persistida em checkpoint/memória para o próximo turno. + +Por isso, para diagnosticar corretamente uma decisão, a pergunta não deve ser apenas: + +> “Qual intent foi encontrada?” + +A pergunta correta é: + +> **“Em qual estado a conversa estava, quem tinha precedência naquele turno, qual intent foi encontrada, quais parâmetros foram resolvidos, qual validação de domínio ocorreu, qual tool efetiva foi escolhida, qual workflow foi executado e quais controles de saída aprovaram a resposta?”** + +--- + +## P.1. Visão geral do motor + +Em alto nível, um turno passa pelas seguintes camadas: + +```mermaid +flowchart TD + U["Mensagem do cliente"] --> IG["Input Guardrails"] + IG --> MEM["Memória / Checkpoint"] + MEM --> TX["Continuidade transacional / Workflow pausado"] + TX --> RT["Routing / Intent"] + RT --> MI["Multi-intent / Pending Topics"] + MI --> AG["Agente proprietário"] + AG --> CP["Coleta de parâmetros"] + CP --> TR["Reconciliação temporal quando necessária"] + TR --> PV["Pre-validation / validação de domínio"] + PV --> CF["Confirmação transacional quando necessária"] + CF --> TL["Tool efetiva / MCP"] + TL --> WF["Workflow declarativo ou execução direta"] + WF --> OR["Resultado operacional / evidências"] + OR --> OS["Output Supervisor + Output Guardrails"] + OS --> J["Judges"] + J --> PS["Persistência / memória / checkpoint"] + PS --> F["Resposta ao cliente"] +``` + +Nem todos os turnos percorrem todos os blocos. Uma simples consulta de plano, por exemplo, pode passar rapidamente por routing → tool → resposta. Já uma contestação ou cancelamento pode atravessar praticamente todo o motor. + +--- + +## P.2. Princípio de precedência: o estado atual pode ser mais importante que a nova intent + +O router não trata cada mensagem como uma conversa nova. + +Antes de classificar uma nova intent, o framework verifica se existe uma operação ativa. Isso evita erros clássicos como interpretar: + +```text +Agente: Deseja confirmar o cancelamento? +Cliente: Sim. +``` + +como uma nova intent genérica. + +A precedência conceitual é: + +```text +1. segurança de entrada +2. workflow/transação já ativa +3. parâmetro pendente +4. confirmação pendente +5. mudança explícita de intenção +6. routing determinístico +7. routing semântico/LLM +8. fallback +``` + +Na prática, há nuances importantes: em `AWAITING_CONFIRMATION`, uma confirmação inequívoca é consumida antes de procurar mudança de assunto; em `COLLECTING_PARAMETERS`, se a fala fornece um dos campos pendentes, a transação continua proprietária do turno. + +--- + +## P.3. Existem três máquinas de estado diferentes + +Um ponto essencial para manutenção é não confundir três famílias de estado. + +### P.3.1. Estados de roteamento do domínio + +Declarados em `config/routing.yaml` através de `state_policies`: + +| Estado | Agente proprietário | +|---|---| +| `WAITING_FATURAS_CONFIRMATION` | `faturas_agent` | +| `WAITING_VAS_CONFIRMATION` | `vas_agent` | +| `WAITING_CONTESTACAO_CONFIRMATION` | `contestacao_agent` | +| `WAITING_SUPORTE_CONTAS_CONFIRMATION` | `suporte_contas_agent` | +| `COLLECTING_FATURAS_PARAMETERS` | `faturas_agent` | +| `COLLECTING_VAS_PARAMETERS` | `vas_agent` | +| `COLLECTING_CONTESTACAO_PARAMETERS` | `contestacao_agent` | +| `COLLECTING_SUPORTE_CONTAS_PARAMETERS` | `suporte_contas_agent` | + +Esses estados servem principalmente para **fixar a propriedade do próximo turno**. Eles não representam, sozinhos, o status completo da transação. + +### P.3.2. Estados transacionais do runtime + +O runtime do framework trabalha com estados canônicos: + +```text +COLLECTING_PARAMETERS +AWAITING_CONFIRMATION +WORKFLOW_PAUSED +TOOL_RESULT_CLARIFICATION +EXECUTING +``` + +Estados terminais: + +```text +COMPLETED +FAILED +CANCELLED +BLOCKED +OUT_OF_SCOPE +``` + +Também podem aparecer estados intermediários como `CONFIRMED` durante o ciclo de execução e avaliação. + +Esses estados controlam: + +- se ainda faltam parâmetros; +- se o usuário precisa confirmar; +- se a tool já pode executar; +- se há workflow pausado; +- se uma resposta curta pertence à operação atual; +- se a transação anterior ainda deve influenciar o turno. + +### P.3.3. Estados do engine de workflows + +O motor YAML de workflows possui sua própria semântica operacional: + +```text +executando + ├─ COMPLETED + ├─ PAUSED / WAITING_INPUT + └─ FAILED +``` + +Um workflow pausado preserva: + +- `workflow_name`; +- `execution_id`; +- nó onde ocorreu a pausa; +- payload da execução; +- contrato de `expected_input`; +- nó de retorno definido por `resume_from`. + +Portanto: + +> `WAITING_CONTESTACAO_CONFIRMATION`, `AWAITING_CONFIRMATION` e `WAITING_INPUT` podem todos significar “algo está esperando o usuário”, mas pertencem a camadas diferentes e têm funções diferentes. + +--- + +## P.4. Máquina de estados transacional + +A máquina conceitual de uma tool transacional é: + +```mermaid +stateDiagram-v2 + [*] --> COLLECTING_PARAMETERS: faltam dados + COLLECTING_PARAMETERS --> COLLECTING_PARAMETERS: dado parcial ou correção + COLLECTING_PARAMETERS --> AWAITING_CONFIRMATION: contrato completo + pre-validation OK + COLLECTING_PARAMETERS --> CANCELLED: abandono explícito / intent shift autorizado + + AWAITING_CONFIRMATION --> EXECUTING: confirmação SIM + AWAITING_CONFIRMATION --> CANCELLED: confirmação NÃO + AWAITING_CONFIRMATION --> AWAITING_CONFIRMATION: pergunta / resposta inconclusiva + AWAITING_CONFIRMATION --> CANCELLED: abandono explícito + + EXECUTING --> WORKFLOW_PAUSED: workflow pede nova entrada + EXECUTING --> COMPLETED: execução concluída + EXECUTING --> FAILED: falha operacional + EXECUTING --> BLOCKED: validação/política bloqueia + EXECUTING --> OUT_OF_SCOPE: política de domínio impede continuidade + + WORKFLOW_PAUSED --> EXECUTING: resume válido + WORKFLOW_PAUSED --> FAILED: erro no resume + WORKFLOW_PAUSED --> COMPLETED: workflow termina + + COMPLETED --> [*] + FAILED --> [*] + CANCELLED --> [*] + BLOCKED --> [*] + OUT_OF_SCOPE --> [*] +``` + +Essa máquina é genérica. Cada regra pode utilizar apenas uma parte dela. + +--- + +## P.5. Routing: como a intenção é determinada + +O `EnterpriseRouter` combina decisões determinísticas e semânticas. + +A sequência principal é: + +```text +state/transaction precedence + ↓ +keywords determinísticas + ↓ +LLM Router, se ENABLE_LLM_ROUTER=true + ↓ +fallback_agent +``` + +O `routing.yaml` define, por intent: + +- `name`; +- `domain`; +- `agent`; +- `priority`; +- `description`; +- `mcp_tools`; +- `keywords`; +- `examples`. + +### Matching determinístico + +As keywords podem casar por mecanismos como: + +- correspondência exata; +- sequência ordenada de tokens; +- sequência de tokens informativos tolerando conectores. + +Se várias intents casarem, a decisão considera: + +```text +menor valor de priority +→ match mais específico/estrito +→ keyword mais longa/específica +``` + +### Routing semântico + +Se o determinístico não for suficiente e o LLM router estiver habilitado, o framework envia ao classificador o catálogo permitido de intents, incluindo descrição e exemplos. + +O LLM **classifica**. Ele não deve inventar: + +- novo nome de intent; +- agente; +- tool; +- regra de negócio. + +Esses elementos continuam vindo da configuração declarativa. + +--- + +## P.6. Route stickiness + +Route stickiness existe para impedir que uma conversa pule de agente sem necessidade quando o cliente continua falando sobre o mesmo assunto. + +Ela é útil em diálogos como: + +```text +Cliente: Minha conta veio alta. +Agente: Identifiquei estes itens... +Cliente: E esse valor de 19,99? +``` + +A segunda fala é curta e, isoladamente, poderia ser ambígua. O contexto e a stickiness ajudam a manter o agente proprietário. + +Mas stickiness **não pode aprisionar a conversa**. Uma nova solicitação explícita pode preemptar a rota anterior quando as regras de intent shift permitirem. + +--- + +## P.7. Intent shift + +Intent shift é o mecanismo usado quando o cliente abandona ou interrompe explicitamente o assunto corrente e inicia outro. + +Exemplo: + +```text +Agente: Qual cobrança deseja contestar? +Cliente: Esquece isso. Quero ver minha fatura. +``` + +O comportamento esperado é: + +```text +transação anterior +COLLECTING_PARAMETERS + ↓ +detecção de abandono / mudança explícita + ↓ +CANCELLED + ↓ +limpeza de next_state / parâmetros / latches + ↓ +novo routing + ↓ +contas_invoice_query +``` + +O router registra metadados como: + +```text +transaction_interruption = intent_shift +``` + +e o runtime encerra corretamente o contrato anterior. + +### Intent shift não é qualquer frase diferente + +Uma regra importante da implementação atual é: + +> **fornecer um parâmetro pendente tem precedência sobre tentar classificar uma mudança semântica de intenção.** + +Se a transação espera `valor` e o cliente diz: + +```text +É 19,99. +``` + +isso deve ser consumido como parâmetro, e não interpretado como nova intent. + +Da mesma forma, uma frase como: + +```text +Isso mesmo, pode cancelar. +``` + +durante confirmação/coleta não deve abandonar a transação apenas porque possui palavras que poderiam casar com outra regra. + +--- + +## P.8. Coleta de parâmetros + +Tools transacionais possuem um contrato de parâmetros. + +Esse contrato nasce da combinação de: + +- `config/tools.yaml`; +- `config/tool_policies.yaml`; +- `config/mcp_parameter_mapping.yaml`; +- schema declarado pela tool; +- dados já existentes no state/contexto. + +O runtime diferencia: + +```text +known_arguments +missing_parameters +resolved_arguments +requested_arguments +``` + +### Primeira tentativa: coleta tradicional do turno atual + +O comportamento normal é tentar extrair os campos pendentes **somente da fala atual**. + +Isso evita que o histórico seja reutilizado indiscriminadamente. + +Exemplo: + +```text +missing_parameters = ["subject", "valor"] + +Cliente: É o Tamboro. +``` + +Resultado possível: + +```text +subject = Tamboro +valor = pendente +``` + +O runtime permanece em: + +```text +COLLECTING_PARAMETERS +``` + +e solicita somente o campo restante. + +--- + +## P.9. Reconciliação temporal + +A reconciliação temporal é uma **segunda linha de resolução**, e não a primeira. + +Ela existe para resolver casos em que a informação está espalhada por turnos relacionados. + +Princípio implementado: + +```text +extração do turno atual + ↓ +faltam required fields? + ├─ não → segue fluxo + └─ sim + ↓ +reconciliação temporal + ↓ +pre-validation autoritativa +``` + +### Exemplo + +```text +Cliente: Não reconheço o Tamboro. +... +Agente: Qual valor você quer contestar? +Cliente: É a de 19,99. +``` + +A fala atual fornece explicitamente o valor. O histórico recente pode ajudar a associar: + +```text +subject = Tamboro +valor = 19,99 +``` + +Mas essa associação ainda é apenas **candidata**. + +Ela precisa passar por validação de domínio. + +### Regras da reconciliação + +A implementação foi deliberadamente restritiva: + +1. a fala atual é a fonte principal; +2. contexto histórico serve para resolver referência, não para inventar uma nova afirmação; +3. campos já conhecidos podem ser preservados; +4. correção atual prevalece temporalmente sobre valor antigo; +5. um campo pode ser: + - `resolved`; + - `preserve`; + - `clear`; + - `unresolved`; +6. ambiguidade deve resultar em `unresolved`, não em chute; +7. reconciliação não valida se o dado existe no backend; +8. a autoridade final é a **pre-validation**. + +### Por que isso é importante + +Sem essa divisão, o LLM poderia concluir erroneamente: + +```text +“19,99 apareceu perto de Tamboro no histórico, então é Tamboro.” +``` + +O motor permite criar o candidato, mas somente a validação de domínio pode confirmar que essa relação é verdadeira. + +--- + +## P.10. Contextual reentry + +Contextual reentry é usado quando uma intent informativa produz contexto suficiente para que uma resposta curta do cliente abra uma ação transacional. + +Exemplo típico: + +```text +Cliente: Não reconheço essas cobranças. +→ contas_invoice_explanation + +Agente explica os itens. + +Cliente: É a de 14,99. +``` + +A segunda fala, isoladamente, não contém: + +```text +“quero contestar” +``` + +Mas o contexto imediatamente anterior pode mostrar que o cliente estava identificando qual cobrança não reconhecia. + +Nesse cenário, o runtime mantém: + +- fala atual separada; +- contexto conversacional delimitado; +- intent/reentrada contextual; +- parâmetros candidatos; +- validação autoritativa antes da ação. + +Contextual reentry não transforma todo o histórico em evidência operacional. Ele usa apenas contexto limitado para interpretação. + +--- + +## P.11. Pre-validation: a autoridade de domínio antes da execução + +Pre-validation é um dos mecanismos mais importantes do Agente de Contas. + +Ela acontece antes de uma ação sensível e deve responder perguntas como: + +```text +O serviço existe? +Esse é realmente o nome canônico? +Esse valor pertence a esse item? +O VAS é avulso, estratégico ou bundle? +A cobrança pode ser contestada? +A tool inicialmente escolhida continua correta? +``` + +No `tool_policies.yaml`, uma tool pode declarar um pre-validator. + +Exemplos: + +```text +cancelar_vas_avulso + ↓ +validar_vas_subject + +contestar_cobranca + ↓ +validar_contestacao +``` + +### Pre-validation pode alterar a operação + +Esse é o motivo pelo qual: + +```text +intent encontrada != tool final necessariamente +``` + +Exemplo: + +```text +Cliente: Quero cancelar Paramount+. +``` + +Routing inicial: + +```text +contas_vas_cancel +→ cancelar_vas_avulso +``` + +Validação de domínio: + +```text +Paramount+ +→ classe estratégica/bundle +``` + +Resultado: + +```text +effective_tool = tratar_vas_estrategico +``` + +A intenção do cliente continua sendo cancelar, mas a **operação válida para aquela entidade** mudou. + +--- + +## P.12. Confirmação de transação + +Tools marcadas com: + +```yaml +require_confirmation: true +``` + +não podem executar imediatamente. + +A sequência é: + +```text +tool selecionada + ↓ +parâmetros completos + ↓ +pre-validation aprovada + ↓ +AWAITING_CONFIRMATION + ↓ +pergunta ao cliente + ↓ +SIM / NÃO / CONTINUAR +``` + +### Classificação determinística primeiro + +Respostas inequívocas são tratadas sem LLM quando possível: + +```text +sim +pode confirmar +não +cancela essa operação +``` + +### Fallback semântico + +Em `routing.yaml`, `transaction_confirmation.semantic_fallback` permite classificar respostas inconclusivas em: + +```text +SIM +NAO +CONTINUAR +``` + +`CONTINUAR` significa: + +- pergunta adicional; +- correção; +- nova informação; +- ambiguidade; +- possível mudança de assunto. + +Ou seja, `CONTINUAR` **não executa** nem rejeita a transação automaticamente. + +### Multi-intent na confirmação + +Uma resposta pode confirmar a operação atual e ainda introduzir outro assunto: + +```text +Sim, e me manda a segunda via. +``` + +O motor pode: + +1. confirmar a transação pendente; +2. executar a ação; +3. colocar a segunda via em `pending_topics`; +4. continuar depois sem perder a intenção secundária. + +--- + +## P.13. Workflow transacional + +Nem toda tool precisa de workflow. + +Workflows são usados quando a execução precisa de: + +- múltiplos passos; +- condições; +- efeitos externos ordenados; +- pausa; +- resume; +- tratamento de caminhos alternativos; +- auditoria clara do fluxo. + +Eles ficam em: + +```text +workflows/*.yaml +``` + +e apontam para actions Python, principalmente em: + +```text +app/domain/contas/workflow_actions.py +``` + +Um workflow declara: + +- `name`; +- `version`; +- `start`; +- `nodes`; +- `action`; +- `edges`; +- condições `when`; +- prioridades; +- configuração `pause`; +- `expected_input`; +- `resume_from`; +- término em `END`. + +### Exemplo conceitual + +```text +START + ↓ +validar / preparar + ↓ +executar integração + ↓ +condição? + ├─ precisa perguntar algo → PAUSED + │ ↓ + │ resposta + │ ↓ + │ resume + │ + └─ não → próximo nó + ↓ + END +``` + +A lógica de orquestração fica em YAML; a regra de domínio executável fica em Python. + +--- + +## P.14. Pause e resume + +Um workflow pode pedir uma nova entrada sem perder a execução corrente. + +Quando isso ocorre: + +```text +status = WAITING_INPUT / PAUSED +workflow_name = ... +execution_id = ... +paused_at = ... +``` + +O nó declara: + +```text +expected_input +resume_from +return_from +``` + +Na próxima mensagem, o runtime tenta primeiro verificar se ela satisfaz o contrato de entrada esperado. + +Se satisfizer: + +```text +mensagem + ↓ +match_expected_input + ↓ +resume(execution_id) + ↓ +resume_from +``` + +Se não satisfizer, o motor pode: + +- repedir esclarecimento; +- permitir reentrada contextual; +- detectar abandono/intenção diferente conforme política. + +--- + +## P.15. Multi-intent + +O agente suporta frases com vários objetivos: + +```text +“Cancela o Tamboro, manda a segunda via e consulta o status do protocolo.” +``` + +O objetivo do multi-intent planner é decompor **ações independentes**, e não desmontar os parâmetros internos de uma mesma ação. + +Correto: + +```text +1. cancelar Tamboro +2. consultar/obter segunda via +3. consultar status +``` + +Incorreto: + +```text +1. Tamboro +2. valor 19,99 +3. motivo +``` + +se esses elementos forem apenas parâmetros de uma única contestação. + +--- + +## P.16. Pending topics + +Quando uma frase contém mais de uma ação e uma delas precisa ser resolvida primeiro, as demais podem ser persistidas em: + +```text +pending_topics +``` + +Um pending topic representa uma intenção já descoberta, mas ainda não executada. + +Exemplo: + +```text +Cliente: Cancela o Tamboro e me manda a segunda via. +``` + +Possível ciclo: + +```text +cancelamento + ↓ +coleta / confirmação + ↓ +execução + ↓ +topic concluído + ↓ +drain pending_topics + ↓ +segunda via +``` + +Isso evita exigir que o usuário repita a segunda solicitação. + +--- + +## P.17. Vários itens dentro da mesma regra + +Multi-intent e multi-item são conceitos diferentes. + +Exemplo multi-item: + +```text +“Cancela Tamboro e Paramount+.” +``` + +Há uma única intenção de alto nível: + +```text +cancelar serviços +``` + +mas existem duas entidades. + +Por isso o motor pode produzir: + +```text +items: + - Tamboro + - Paramount+ +``` + +e validar cada uma separadamente. + +O resultado também deve permanecer separado: + +```text +Tamboro +→ avulso +→ cancelamento permitido +→ success + +Paramount+ +→ estratégico +→ tratar_vas_estrategico +→ não executar cancelamento avulso +``` + +Nunca se deve usar o sucesso de um item para afirmar sucesso dos outros. + +--- + +## P.18. Guardrails de entrada + +Antes do routing, o grafo principal executa `input_guardrails`. + +No Agente de Contas, `config/guardrails.yaml` habilita: + +| Rail | Papel no motor | +|---|---| +| `INPUT_SIZE` | limita/valida tamanho de entrada | +| `MSK` | sanitização/masking de conteúdo sensível conforme framework | +| `DLEX_IN` | validação lexical/entrada | +| `TOX` | toxicidade de entrada | +| `PINJ` | proteção contra prompt injection | +| `COER` | coerência/inteligibilidade da entrada | +| `VLOOP` | detecção de repetição/loop conversacional | + +O `COER` **não deve decidir intent**, parâmetros, validade de negócio ou intent shift. Essas responsabilidades pertencem ao router e ao runtime transacional. + +O `VLOOP` possui tratamento especial para não bloquear respostas legítimas repetidas como `sim` durante `AWAITING_CONFIRMATION`. + +Se um input é bloqueado, a resposta de segurança ainda passa pela cadeia de guardrails de saída antes de chegar ao cliente. + +--- + +## P.19. Guardrails de retrieval e tool + +Além da entrada/saída existem rails específicos para outros pontos: + +```yaml +retrieval: + - RAGSEC + - RET_REL + +tool: + - TOOL_VAL +``` + +Conceitualmente: + +- `RAGSEC` protege o uso de conteúdo recuperado; +- `RET_REL` verifica relevância da recuperação; +- `TOOL_VAL` valida uso/resultado de tools de acordo com o contrato do framework. + +Esses controles não substituem a pre-validation de domínio. São camadas complementares. + +--- + +## P.20. Output Supervisor e guardrails de saída + +Depois que o agente gera uma resposta, ela não é necessariamente entregue imediatamente. + +O grafo passa por: + +```text +agente + ↓ +Output Supervisor + ↓ +Output Guardrails +``` + +No agente Contas estão configurados rails como: + +| Rail | Função geral | +|---|---| +| `TIM_OOS` | política de escopo do atendimento Contas/TIM | +| `TIM_AOFERTA` | evita oferta proativa indevida | +| `TIM_REVPREC` | evita verbalizar ação transacional antes da evidência real | +| `PINJ` | proteção contra conteúdo de prompt injection refletido | +| `DLEX_OUT` | validação lexical de saída | +| `TOXOUT` | toxicidade de saída | +| `CMP` | coerência/completude operacional, incluindo protocolos esperados | +| `GND` | groundedness em evidência | +| `ALUC_RISK` | risco de alucinação | + +O Output Supervisor pode: + +```text +ALLOW +SANITIZE +RETRY +BLOCK +HANDOVER +``` + +conforme os resultados dos rails e políticas declaradas. + +`guardrails.yaml` define: + +```text +max_retries = 3 +fallback_message +handover_message +``` + +Isso é especialmente importante em ações transacionais: o agente não deve dizer “cancelei” apenas porque tentou chamar uma tool. A resposta precisa estar apoiada no resultado operacional. + +--- + +## P.21. Judges + +Depois dos guardrails de saída, o grafo executa judges. + +No `config/judges.yaml` atual existem dois judges externos: + +```text +tim_response_quality +threshold = 0.70 + +tim_groundedness +threshold = 0.60 +``` + +Configurações relevantes: + +```text +enabled = true +fail_closed = true +sample_rate = 1.0 +always_run_for_transactional = true +``` + +Os judges recebem um contexto reduzido contendo, entre outros: + +- pergunta; +- resposta final; +- intent; +- route; +- resultados MCP; +- resultados RAG; +- evidências transacionais; +- status da transação; +- policy da tool; +- tools transacionais envolvidas. + +### Diferença entre guardrail e judge + +Uma forma útil de pensar: + +```text +Guardrail: +“Esta entrada/saída pode prosseguir?” + +Judge: +“Quão boa e fundamentada está a resposta produzida?” +``` + +Os dois podem usar LLM, mas têm responsabilidades diferentes. + +--- + +## P.22. Supervisor review + +Após os judges, o grafo ainda possui `supervisor_review`. + +Fluxo real do grafo principal: + +```text +START + ↓ +input_guardrails + ↓ +load_long_term_memory + ↓ +routing_decision + ↓ +conversation_policy + ↓ +agente / handoff / controle de sessão + ↓ +output_supervisor + ↓ +output_guardrails + ↓ +judge + ↓ +supervisor_review + ↓ +persist_long_term_memory + ↓ +persist + ↓ +END +``` + +Esse fluxo ajuda a entender por que uma resposta produzida pelo agente pode não ser exatamente a mesma resposta persistida/entregue ao usuário. + +--- + +## P.23. Memória, checkpoint e persistência + +O estado do turno não vive apenas na memória do LLM. + +O framework persiste estruturas operacionais para permitir: + +- continuidade; +- pause/resume; +- confirmação em outro turno; +- coleta progressiva de parâmetros; +- pending topics; +- idempotência; +- auditoria; +- observabilidade. + +O contexto canônico possui precedência de dados: + +```text +tool_arguments + ↓ +business_context + ↓ +context + ↓ +session + ↓ +session.metadata + ↓ +state +``` + +Ou seja, um parâmetro explicitamente resolvido para uma tool deve prevalecer sobre um valor genérico mais antigo no state. + +--- + +## P.24. Evidência operacional versus contexto conversacional + +O framework diferencia duas coisas que não devem ser confundidas. + +### Contexto conversacional + +Serve para entender: + +```text +“esse” +“o primeiro” +“a de 19,99” +“isso mesmo” +``` + +### Evidência operacional + +Serve para afirmar fatos: + +```text +serviço existe +cancelamento foi concluído +protocolo foi gerado +valor pertence à fatura +status foi atualizado +``` + +Histórico conversacional **não é evidência de backend**. + +Por isso: + +> O LLM pode usar a conversa para descobrir qual item o cliente quis dizer, mas somente tool/pre-validation/backend pode confirmar que esse item existe ou que uma transação ocorreu. + +--- + +## P.25. Idempotência e proteção contra reexecução + +Transações conversacionais precisam tolerar: + +- retry HTTP; +- retry do canal; +- usuário repetindo confirmação; +- checkpoint reprocessado; +- reload da aplicação. + +Por isso o runtime mantém identificadores e estado transacional suficientes para distinguir: + +```text +pedido novo +continuação +resume +retry +reexecução indevida +``` + +Workflows utilizam `execution_id`, e transações mantêm identificação/estado próprio. Isso reduz o risco de executar duas vezes uma ação apenas porque a mesma mensagem reapareceu. + +--- + +## P.26. Conversation policy + +Após `routing_decision`, o grafo passa por `conversation_policy`. + +Essa camada pode decidir que a rota final do turno é: + +```text +faturas_agent +vas_agent +contestacao_agent +suporte_contas_agent +handoff +human_handoff +end_session +supervisor_agent +conversation_policy_response +``` + +Ou seja, routing de intent não é necessariamente o último controle antes do agente. Políticas conversacionais podem interferir em continuidade, encerramento e transferência. + +--- + +## P.27. Por que a ordem dos mecanismos importa + +Considere: + +```text +Cliente: “Sim, e manda a segunda via.” +``` + +durante `AWAITING_CONFIRMATION`. + +Uma implementação ingênua poderia encontrar: + +```text +“segunda via” +→ contas_invoice_query +``` + +e perder a confirmação. + +O motor correto avalia: + +```text +1. existe AWAITING_CONFIRMATION? +2. “sim” confirma a transação? +3. existe texto remanescente? +4. o restante contém uma segunda intent? +5. executa transação principal +6. preserva segunda via como pending topic +7. continua a conversa +``` + +Outro exemplo: + +```text +Cliente: “É a de 19,99.” +``` + +durante `COLLECTING_PARAMETERS`. + +Ordem correta: + +```text +1. verificar parâmetro pendente +2. extrair 19,99 +3. se necessário reconciliar com contexto +4. validar subject + valor +5. só depois considerar nova intent +``` + +É essa precedência que impede o motor de “pular” de regra em cada mensagem curta. + +--- + +## P.28. Resumo dos mecanismos e suas fontes + +| Mecanismo | Fonte principal | Responsabilidade | +|---|---|---| +| Routing | `config/routing.yaml` + `EnterpriseRouter` | descobrir intent/agente | +| State policies | `config/routing.yaml` | manter propriedade do turno | +| Route stickiness | router/runtime | manter continuidade contextual | +| Intent shift | `EnterpriseRouter` + runtime | abandonar corretamente operação anterior | +| Multi-intent | `MultiIntentPlanner` | separar objetivos independentes | +| Pending topics | runtime/grafo | preservar intents ainda não executadas | +| Coleta de parâmetros | runtime + tool contract | preencher required fields | +| Reconciliação temporal | `transaction_parameters.py` | recuperar relação coerente entre turnos | +| Contextual reentry | router/runtime | usar contexto imediato para reentrada | +| Pre-validation | `tool_policies.yaml` + validators | autoridade de domínio antes da ação | +| Confirmação | policy + runtime + semantic fallback | impedir execução sem aceite | +| Workflow | `workflows/*.yaml` | orquestrar passos/condições | +| Pause/resume | workflow runtime | continuar execução em outro turno | +| Guardrails de entrada | `guardrails.yaml` | proteger/sanitizar entrada | +| Retrieval/tool guardrails | `guardrails.yaml` | controlar RAG/tools | +| Output Supervisor | framework + `guardrails.yaml` | retry/block/sanitize/handover | +| Guardrails de saída | `guardrails.yaml` | validar resposta final | +| Judges | `judges.yaml` | avaliar qualidade/groundedness | +| Conversation policy | `conversation_policy.py` | continuidade/transferência/controle | +| Checkpoint | framework persistence | durabilidade de estado | +| Long-term memory | framework memory | contexto durável apropriado | +| Idempotência | runtime/workflow | evitar execução duplicada | +| Telemetria | observability config/framework | explicar o caminho executado | + +--- + +## P.29. Regra de ouro para interpretar o agente + +Quando houver um comportamento inesperado, nunca analise apenas uma linha do `routing.yaml`. + +Siga esta cadeia: + +```text +Mensagem + ↓ +Input guardrails + ↓ +Estado anterior + ↓ +Transação/workflow ativo? + ↓ +Parâmetro pendente? + ↓ +Confirmação pendente? + ↓ +Intent shift? + ↓ +Routing + ↓ +Multi-intent / pending topics + ↓ +Tool candidata + ↓ +Coleta / reconciliação temporal + ↓ +Pre-validation + ↓ +Tool efetiva + ↓ +Confirmação + ↓ +Workflow / MCP + ↓ +Resultado operacional + ↓ +Output Supervisor / guardrails + ↓ +Judges + ↓ +Persistência + ↓ +Resposta +``` + +Esse é o **motor de decisão real** do Agente de Contas. Os capítulos seguintes documentam como cada regra específica utiliza esse motor. + +--- + ## 1. Como ler este manual Cada regra é documentada em seis níveis: