
Arquitetura de agente na WhatsApp Cloud API: webhooks e filas
Como a mensagem percorre webhook, fila, agente e resposta na WhatsApp Cloud API, com tratamento de duplicidade, ordem e falhas, para operar com segurança.
Quer aplicar isso na sua empresa?
Agendar conversa com o Juan →Arquitetura de agente na WhatsApp Cloud API: webhooks e filas
Uma arquitetura de agente na WhatsApp Cloud API separa quatro etapas: um endpoint de webhook que valida e responde rápido, uma fila que guarda o trabalho, um worker que roda o agente por conversa e um passo de envio que registra o que foi respondido. Duplicidade se resolve com o identificador da mensagem como chave única, e ordem se resolve processando uma conversa por vez, sem confiar na ordem de chegada. O resto do desenho existe para que uma falha em qualquer etapa não gere resposta repetida, resposta fora de contexto ou mensagem perdida.
Principais pontos
- O webhook só valida a assinatura, grava o evento e enfileira. Nenhuma chamada ao modelo acontece dentro dele.
- O identificador da mensagem recebida é a chave de deduplicação, gravada de forma atômica antes de qualquer processamento.
- A ordem é garantida por conversa, não globalmente: uma fila particionada pelo número do cliente, com um worker por vez em cada conversa.
- O agente lê o histórico do seu próprio armazenamento, trata o texto do cliente como dado não confiável e só age por ferramentas com permissão limitada.
- Toda etapa precisa de registro com um identificador de correlação, para responder depois o que chegou, o que foi decidido e o que foi enviado.
Qual é o caminho da mensagem, do webhook à resposta?
O caminho tem sete passos, e cada um deve ser um ponto de falha isolado:
- A Meta envia um POST para o seu endpoint com o evento (mensagem recebida ou atualização de status).
- O endpoint valida a assinatura, grava o payload bruto e devolve sucesso.
- Um passo de deduplicação descarta eventos já vistos e coloca os novos na fila.
- Um worker pega o evento respeitando a ordem da conversa.
- O worker monta o contexto, chama o agente e recebe uma decisão: responder, executar uma ação ou transferir para um humano.
- Os guardrails validam a saída e a ação antes de qualquer efeito externo.
- O passo de envio chama a API da Meta, registra o resultado e marca o evento como concluído.
A razão de tanta separação é simples. Cada etapa tem um tempo de resposta e um modo de falha diferentes. O webhook precisa ser rápido. O modelo pode demorar ou falhar. O envio pode ser recusado por regra do canal. Se tudo ocorre na mesma requisição, qualquer lentidão vira reenvio de evento pela Meta, e qualquer erro vira mensagem perdida.
Se você ainda está decidindo entre canais e abordagens, vale ler antes WhatsApp Business API ou app: qual usar com agente de IA e o guia de integração de IA no WhatsApp da empresa.
O que o endpoint de webhook deve fazer, e o que não deve?
Pela documentação da Meta, o webhook tem dois comportamentos. No cadastro, a Meta faz uma requisição GET com um token de verificação e um desafio, e o seu endpoint devolve o desafio se o token conferir. Em operação, ela envia POSTs com o evento e um cabeçalho de assinatura calculado com o segredo do app. Confirme os nomes exatos dos campos e do cabeçalho na documentação oficial vigente antes de implementar, porque eles são parte do contrato com a Meta.
O que o endpoint deve fazer, nesta ordem:
- Calcular a assinatura sobre o corpo bruto da requisição, antes de qualquer parsing, e rejeitar se não bater. Reserializar o JSON antes de validar quebra a assinatura.
- Gravar o payload bruto em um armazenamento durável, com a hora de recebimento.
- Enfileirar uma referência ao evento, não o texto inteiro, para manter a fila leve.
- Responder com sucesso o mais rápido possível.
O que ele não deve fazer: chamar o modelo, consultar o CRM, baixar mídia ou enviar resposta. A Meta reenvia eventos quando não recebe sucesso, e isso é correto do ponto de vista dela. Se o seu endpoint demora porque está esperando um modelo, você mesmo fabrica duplicidade.
O mesmo princípio aparece em outros provedores. A documentação de webhooks da Stripe é uma boa referência de como pensar em verificação de assinatura, resposta rápida e processamento assíncrono, mesmo que os detalhes do WhatsApp sejam outros.
Como tratar mensagens duplicadas?
Duplicidade não é defeito raro, é comportamento esperado de qualquer entrega com reenvio. Ela acontece por reenvio da Meta, por retry do seu próprio worker depois de uma falha parcial e por reprocessamento manual de uma fila. A defesa é a idempotência: processar o mesmo evento duas vezes deve produzir o mesmo efeito que processar uma vez.
O identificador da mensagem recebida (o campo de id dentro do evento) é a chave natural. A forma de usá-lo importa mais do que a escolha da tecnologia:
- Faça a deduplicação com uma operação atômica: inserir o identificador em uma tabela com restrição de unicidade, ou usar um comando de gravação condicional em um cache. Verificar com uma leitura e gravar depois abre uma janela de corrida entre dois eventos simultâneos.
- Deduplique na entrada da fila e proteja de novo no worker. Uma barreira só não cobre o reprocessamento.
- Guarde o estado do evento: recebido, em processamento, concluído, falhou. Um evento em processamento que travou precisa de um prazo para ser retomado, senão fica preso para sempre.
- Separe os tipos de evento. As atualizações de status (enviada, entregue, lida, falha) chegam pelo mesmo canal das mensagens, mas não devem acionar o agente.
Há uma segunda camada que costuma ser esquecida: a duplicidade das ações. Se o agente cria um pedido, abre um chamado ou agenda um horário, o reenvio do evento não pode criar dois. A solução é derivar uma chave de idempotência da combinação entre o identificador da mensagem e a ação pretendida, e passá-la ao sistema de destino quando ele aceitar. O guia de requisições idempotentes da Stripe mostra esse padrão em uma API real. Quando o sistema de destino não oferece esse recurso, registre a ação no seu lado antes de executar e consulte esse registro antes de repetir.
O envio da resposta ao cliente merece o mesmo cuidado. Não assuma que chamar a API de envio duas vezes seja inofensivo: o cliente receberia duas mensagens. Grave a intenção de envio antes, o resultado depois, e em caso de dúvida (timeout sem resposta) verifique o registro e os status recebidos antes de tentar de novo. Isso é prática de implementação, não garantia da Meta.
Como preservar a ordem das mensagens?
A entrega de webhooks não deve ser tratada como ordenada. Duas mensagens enviadas em sequência pelo cliente podem chegar invertidas, ou a segunda pode chegar enquanto a primeira ainda está sendo processada. Os carimbos de tempo do evento ajudam, mas podem empatar, então use-os como apoio e não como único critério.
O desenho que funciona é ordenar por conversa, não no sistema inteiro:
- Use o número do cliente (ou o identificador da conversa) como chave de partição da fila.
- Garanta um único worker ativo por conversa, com bloqueio ou com a própria partição.
- Mantenha um número sequencial por conversa no seu banco, atribuído quando o evento é aceito.
- Antes de enviar a resposta, verifique se chegou algo novo naquela conversa depois do início do processamento. Se chegou, descarte a resposta pronta e gere outra com o contexto completo.
Essa última verificação evita um erro clássico: o agente responde à primeira pergunta enquanto o cliente já corrigiu a informação na terceira mensagem.
Uma técnica complementar é agrupar mensagens curtas. Clientes escrevem em rajadas de frases soltas. Esperar uma janela curta de silêncio e entregar tudo ao agente como um único turno reduz chamadas ao modelo e melhora a resposta. O tamanho da janela é uma decisão de produto que você ajusta no piloto, não um valor universal.
Como o agente se encaixa, e o que ele pode fazer?
O worker não passa o payload cru da Meta ao modelo. Ele monta o contexto a partir do seu armazenamento: histórico recente da conversa, dados do cliente que o fluxo permite usar, estado atual (por exemplo, se há um atendente humano assumindo) e as instruções do agente. Se a conversa está com um humano, o agente não responde. Esse estado precisa ser lido a cada turno, e o desenho do transbordo está detalhado em Transbordo humano em agentes de IA no WhatsApp.
Três regras de segurança valem para esse passo:
- O texto do cliente é entrada não confiável. Ele pode conter instruções disfarçadas. O guia da OWASP sobre prevenção de prompt injection descreve as defesas, e a principal é nunca dar ao agente mais permissão do que o fluxo precisa.
- As ferramentas são poucas, nomeadas e com escopo restrito. Leitura primeiro, escrita só quando necessária, e ações sensíveis com aprovação humana.
- A saída e a ação passam por validação antes do efeito. Os padrões estão em Guardrails para agentes de IA.
Mídia (áudio, imagem, documento) entra por uma fila separada. O evento traz um identificador da mídia, e o download e a transcrição acontecem em outro worker, que depois devolve o resultado à conversa respeitando a mesma ordem. Misturar isso no fluxo principal faz uma mensagem de áudio travar todas as seguintes.
Como lidar com falhas, reenvios e observabilidade?
Falhas acontecem em três lugares: no modelo, nas ferramentas e no envio. Para cada um, defina antes o que acontece:
- Retry com espera crescente para falhas temporárias, com um limite de tentativas.
- Uma fila de mensagens mortas para o que excedeu o limite, com alerta para uma pessoa e não com descarte silencioso.
- Uma resposta de contingência, curta e honesta, para quando o agente não consegue responder, combinada com o transbordo.
- Tratamento explícito das recusas de envio da Meta, como mensagens fora da janela de atendimento, que não se resolvem repetindo a chamada.
Para operar, cada evento recebe um identificador de correlação que acompanha o webhook, a fila, a chamada ao modelo, as ferramentas e o envio. Com isso, a pergunta "por que o cliente recebeu aquela resposta?" tem resposta. O primer de observabilidade do OpenTelemetry explica a lógica de traços, métricas e logs. Na prática, acompanhe a idade da fila, o tempo entre mensagem recebida e resposta enviada, a taxa de transbordo e o volume na fila de mensagens mortas.
Sobre dados pessoais: o payload bruto contém telefone e conteúdo da conversa. Defina quanto tempo ele fica guardado, quem acessa e o que é mascarado nos logs. A base legal e o registro são tema de LGPD no WhatsApp com IA, e a ANPD é a referência oficial para orientações.
Cenário ilustrativo: três mensagens em sequência
Imagine uma loja que usa o agente para informar prazo de pedido. O cliente escreve: "Oi", depois "queria saber do meu pedido" e, em seguida, "é o 4521, não o 4512". Este é um cenário ilustrativo, não um caso real.
Sem controle de ordem e duplicidade, o sistema pode responder sobre o pedido errado, ou duas vezes, porque a Meta reenviou o primeiro evento enquanto o modelo ainda pensava. Com a arquitetura descrita aqui, o fluxo muda:
- Cada evento é gravado e deduplicado pelo identificador, então o reenvio é ignorado.
- As três mensagens caem na mesma partição e esperam uma janela curta de silêncio.
- O worker entrega as três ao agente como um único turno.
- Se a terceira mensagem chegar durante o processamento, a resposta pronta é descartada e refeita.
- A consulta ao pedido usa uma ferramenta de leitura, e o envio registra a intenção antes de chamar a API.
O resultado é uma única resposta, sobre o pedido certo, com um rastro completo para auditoria.
Como aplicamos isso: mapear, limitar, pilotar, transferir
O método segue quatro passos. Primeiro, mapear o fluxo atual: quais mensagens chegam, em que volume aproximado, quais perguntas se repetem e quem responde hoje. Segundo, limitar dados e ações: o que o agente lê, o que ele pode executar e o que exige aprovação. Terceiro, pilotar um único fluxo real, com logs, a arquitetura de fila e deduplicação já ativas e uma métrica de sucesso combinada de antemão (veja como medir um piloto de automação com IA). Por fim, transferir a operação com documentação e decidir se o piloto expande, ajusta ou para. Esta seção descreve o método de trabalho, não um resultado de cliente.
Checklist mínimo antes de ligar o piloto:
- A assinatura do webhook é validada sobre o corpo bruto.
- O endpoint responde sem chamar o modelo.
- O identificador da mensagem tem restrição de unicidade.
- A fila é particionada por conversa.
- Há uma verificação de mensagem nova antes do envio.
- Existe fila de mensagens mortas com alerta.
- O estado de transbordo é lido a cada turno.
- O prazo de retenção do payload bruto está definido.
Perguntas frequentes
Preciso mesmo de uma fila para um agente de WhatsApp pequeno? Para um volume muito baixo e um fluxo simples, você pode começar com uma tabela de eventos e um worker que lê dela, o que já é uma fila em sua forma mais básica. O que não se deve fazer é chamar o modelo dentro do webhook, porque isso gera reenvios e perda de mensagens. Escolha a ferramenta de fila conforme a sua infraestrutura e o que a equipe consegue operar.
A Meta garante que cada mensagem chega uma única vez e em ordem? Não trate a entrega como garantida nesses dois pontos. Reenvios acontecem quando o endpoint não confirma com sucesso, e a ordem de chegada pode diferir da ordem de envio. Por isso a deduplicação pelo identificador e a ordenação por conversa ficam por conta da sua arquitetura. Confirme sempre o comportamento atual na documentação oficial da Meta.
Como evito que o agente responda duas vezes ao mesmo cliente? Combine três coisas: deduplicação atômica do evento de entrada, registro da intenção de envio antes de chamar a API e um worker único por conversa. Antes de enviar, verifique se já existe uma resposta registrada para aquele turno. Em caso de timeout no envio, consulte o registro e os status antes de repetir a chamada.
O que fazer com mensagens que o agente não consegue processar? Depois de um número limitado de tentativas com espera crescente, mova o evento para uma fila de mensagens mortas e avise uma pessoa. Ao cliente, envie uma resposta curta de contingência e transfira a conversa para um atendente humano. Descartar em silêncio é a pior opção, porque o cliente fica sem resposta e a equipe sem sinal do problema.