← Todos os casosEnglish

Varejo · 2026

Um agente que atende no WhatsApp e sabe a hora de chamar um humano

Atendimento consultivo por WhatsApp: entende a necessidade, recomenda a partir de catálogo próprio, responde dúvida conceitual por RAG e passa para um especialista com briefing pronto.

Meu papel · Projeto meu

Do desenho do grafo ao deploy, incluindo os guardrails e a suíte de avaliação.

3
clientes em produção sobre a mesma arquitetura2026 · ajuste por operação, não reescrita
14
cenários de eval rodando em CIdesde jun/2026
9
nós no grafo de conversaarquitetura atual

Este caso descreve arquitetura e decisões sem expor código proprietário, credenciais, clientes ou dados de operação.

O problema

Atendimento consultivo no WhatsApp quebra o laço ingênuo de mensagem → modelo → resposta. A pessoa escreve em rajada, o canal reentrega o evento se você demorar, e a conversa precisa lembrar de ontem. Qualquer um dos três, sozinho, já produz um atendimento que parece quebrado.

As restrições reais

  • A pessoa manda três mensagens em oito segundos. São um pensamento só — responder cada uma gera três respostas desencontradas.
  • O webhook não pode esperar o modelo. Se a resposta demora, a API do WhatsApp reentrega o evento e a conversa duplica.
  • A conversa é longa e precisa lembrar. O estado não cabe no prompt e não pode viver em memória de processo, que morre no primeiro redeploy.
  • O agente não pode inventar preço nem prometer prazo. Em venda consultiva, errar isso custa mais caro que não responder.

Arquitetura

carregarentenderdecidirrecuperaragendarcomporguardpersistirhandoff
Linha tracejada é rota condicional. O guard roda depois da composição, não dentro do prompt.
  1. carregar — Hidrata o estado a partir do checkpointer em Postgres e da memória acumulada.
  2. entender — Extrai intenção, entidades e o que ainda falta saber sobre quem está do outro lado.
  3. decidir — Roteia: seguir conversando, agendar, ou entregar a um humano.
  4. recuperar — Resolve o catálogo canônico e, em dúvida conceitual, consulta o índice vetorial.
  5. agendar — Conversa com a agenda real e devolve horários que existem.
  6. compor — Redige a resposta usando só o contexto que foi recuperado.
  7. guard — Barreira de saída: não inventa preço, não promete prazo, não extrapola o catálogo. Roda sobre o texto pronto.
  8. persistir — Grava memória e entendimento acumulado para o próximo turno.
  9. handoff — Monta o briefing estruturado e entrega ao especialista humano.

Decisões e o que custaram

A barreira roda depois de compor, não dentro do prompt

Escolhi
Verificar o texto já pronto contra regras explícitas, como última etapa antes de persistir.
Descartei
Confiar na instrução do prompt para o modelo não inventar preço nem prazo.
Custou
Uma passada a mais por resposta e um conjunto de regras para manter. Em troca, a classe de erro deixa de ser probabilística: pedir no prompt reduz a chance, verificar a saída elimina o caso.

Estado tipado em vez de dicionário solto

Escolhi
Contrato explícito entre os nós do grafo, verificável antes de rodar.
Descartei
Passar um dicionário livre de nó para nó, que é o caminho mais rápido.
Custou
Mais cerimônia para adicionar um campo. Em troca, renomear algo quebra no import e não às duas da manhã em produção.

Dois motores, selecionados por variável de ambiente

Escolhi
Manter o orquestrador imperativo antigo vivo ao lado do grafo novo, alternável sem redeploy.
Descartei
Migrar de uma vez e apagar o caminho antigo.
Custou
Código duplicado e duas implementações para manter durante a transição. Em troca, o rollback é uma variável de ambiente, não uma madrugada.

Telefone pseudonimizado antes de sair do processo

Escolhi
Hash com salt aplicado antes de qualquer log ou trace de observabilidade.
Descartei
Logar o número cru, que é mais simples de depurar quando algo dá errado.
Custou
Depurar um caso específico exige recalcular o hash. Em troca, nenhum trace devolve o número de ninguém.

Resultado

  • O agente conduz a conversa inteira, recomenda a partir do catálogo e entrega ao especialista com briefing estruturado, em vez de transferir uma transcrição crua.
  • A avaliação automatizada roda com um modelo como juiz e devolve código de saída binário, então entra em CI como qualquer teste. Os cenários cobrem o que mais dói: inventar preço, prometer prazo, responder fora do catálogo e perder o fio entre turnos.
  • Rollback de motor sem redeploy durante toda a migração para o grafo.

O que levei disso

Guardrail dentro do prompt é pedido; guardrail fora do prompt é garantia. Passei a tratar a saída do modelo como entrada não confiável — a mesma postura que qualquer um tem com entrada de usuário, e que por algum motivo se perde quando o texto vem de um LLM.

Stack

  • LangGraph
  • Python
  • FastAPI
  • PostgreSQL
  • RAG
  • LLM
  • Langfuse
  • Docker
← Todos os casos