Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Configurar o WhatsApp Business Cloud API

O Hermes conecta ao WhatsApp pela API oficial do WhatsApp Business Cloud, da Meta. Esse é o caminho de nível de produção: sem subprocesso de ponte em Node.js, sem QR code, sem risco de banimento de conta.

Em troca:

  • Você precisa de uma conta Meta Business (não do WhatsApp pessoal).
  • O bot opera em um número de telefone comercial dedicado, não no seu número pessoal.
  • O gateway do Hermes precisa de uma URL HTTPS pública para a Meta entregar as mensagens de entrada por webhook.
  • Respostas mais de 24 horas depois da última mensagem da pessoa exigem um template pré-aprovado (essa é a regra da "janela de atendimento" da Meta, não uma limitação do Hermes).

Se essas restrições não servem para o seu caso, a integração pela ponte Baileys é a alternativa — conta pessoal, sem precisar de URL pública, mas não oficial e sujeita a banimento.

Qual eu devo usar?
  • Cloud API (este guia) — você opera um bot comercial de verdade, quer estabilidade e não se incomoda com a papelada de verificação e templates da Meta
  • Ponte Baileys — projetos pessoais, demos rápidas, configurações de uma pessoa só, disposto a arriscar a conta do número de telefone do bot

Início rápido​

hermes whatsapp-cloud

O assistente conduz você por cada credencial, valida cada uma na hora que você cola (pega a pegadinha número 1 da configuração — colar um número de telefone no campo do Phone Number ID) e imprime instruções exatas para as partes que precisam acontecer fora do assistente (subir o cloudflared, configurar o painel de webhook da Meta).

O resto desta página é a referência manual.


Pré-requisitos​

  1. Uma conta Meta Business. Crie em business.facebook.com.
  2. Um app da Meta com o WhatsApp habilitado. Veja "Criar o app da Meta" abaixo.
  3. Um jeito de expor uma porta local para a internet com HTTPS. O Cloudflare Tunnel (cloudflared) é o recomendado — grátis, sem redirecionamento de porta, sem precisar de domínio. ngrok, seu próprio domínio com proxy reverso + TLS, ou uma VPS com o gateway ligado direto num IP público também funcionam.
  4. Opcional, mas recomendado: ffmpeg no PATH para as mensagens de voz de saída aparecerem como as bolhas nativas de nota de voz do WhatsApp (a onda verde) em vez de anexos de áudio MP3. O Hermes degrada com elegância se ele não estiver presente.

Criar o app da Meta​

  1. Vá em developers.facebook.com/apps → Create App.
  2. Escolha o caso de uso: "Connect with customers through WhatsApp" → Next.
  3. Escolha ou crie um portfólio de negócios. Revise os requisitos de publicação. Confirme → Create app.
  4. Depois de criar, você cai em Customize use case → Connect on WhatsApp → Quickstart. Clique em Start using the API → você está agora na página API Setup.
  5. Confirme que há uma WhatsApp Business Account (WABA) vinculada. Se você criou um portfólio novo no passo 3, uma foi criada automaticamente. Verifique na página de API Setup.

Você vai precisar destes valores do painel — o assistente pede nesta ordem:

ValorOnde no painelFormato do campoObservações
Phone Number IDApp Dashboard → WhatsApp → API Setup → abaixo do menu "From"Numérico, 15 a 17 dígitosNÃO é o número de telefone em si. O erro número 1 na configuração é colar o telefone de verdade aqui.
Access TokenApp Dashboard → WhatsApp → API Setup → "Generate access token"Começa com EAA, 100+ caracteresTokens temporários duram 24 h — veja "Token permanente" abaixo para produção.
App SecretApp Dashboard → Settings → Basic → clique em "Show" ao lado de App secret32 caracteres hexadecimais minúsculosServe para verificar as assinaturas dos webhooks de entrada. Sem ele, a entrega de entrada é recusada com 503.
App ID (opcional)App Dashboard → Settings → BasicNumérico, 15 a 16 dígitosNão é obrigatório para mensagens, é útil para analytics.
WABA ID (opcional)App Dashboard → WhatsApp → API Setup → perto do topoNumérico, 15+ dígitosNão é obrigatório para mensagens, é útil para analytics.

Token permanente (produção)​

Tokens de acesso temporários expiram depois de 24 horas, o que significa que um token gerado hoje para de funcionar amanhã. Em implantações de produção, use um token permanente de System User:

  1. Vá em business.facebook.com/latest/settings → System users (barra lateral esquerda).
  2. Add → nome (por exemplo hermes-bot) → papel: Admin.
  3. Selecione o novo usuário → Assign Assets:
    • Selecione o seu app → ligue Manage app em Full control.
    • Selecione a sua conta do WhatsApp → ligue Manage WhatsApp Business Accounts em Full control.
    • Clique em Assign assets.
  4. Generate token com estas permissões:
    • business_management
    • whatsapp_business_messaging
    • whatsapp_business_management
  5. Defina token expiration: Never.
  6. Copie o token → atualize WHATSAPP_CLOUD_ACCESS_TOKEN em ~/.hermes/.env → reinicie o gateway.

Tokens de System User não expiram, a menos que você os revogue explicitamente.


Expor o Hermes para a internet​

A Cloud API entrega as mensagens de entrada por POST HTTPS na sua URL de webhook — ou seja, o gateway do Hermes precisa estar acessível dos servidores da Meta. Três caminhos comuns:

Grátis, sem redirecionamento de porta, funciona no Windows, no macOS e no Linux. Roda como um processo separado ao lado do gateway.

Instalação:

# Windows
winget install Cloudflare.cloudflared

# macOS
brew install cloudflared

# Linux
# Baixe o binário em https://github.com/cloudflare/cloudflared/releases

Suba um túnel rápido (não precisa de conta na Cloudflare — dá uma URL https://<aleatorio>.trycloudflare.com):

cloudflared tunnel --url http://localhost:8090

Anote a URL impressa — é ela que você vai dar para a Meta.

Túneis rápidos mudam de URL

A URL do túnel rápido gratuito muda toda vez que você reinicia o cloudflared. Para uma URL estável, entre com cloudflared tunnel login e crie um túnel nomeado. Contas gratuitas da Cloudflare têm túneis nomeados ilimitados — veja a documentação da Cloudflare para o fluxo de túnel nomeado.

ngrok​

ngrok http 8090

O plano gratuito mostra uma URL diferente a cada reinício. O plano pago dá um subdomínio estável.

Seu próprio domínio + proxy reverso​

Se você já tem um servidor com certificado TLS (Caddy, nginx etc.), aponte uma rota para localhost:8090. É a opção mais estável para produção, mas exige infraestrutura já existente.


Configurar o webhook do lado da Meta​

Com o seu túnel rodando:

  1. Anote a URL pública impressa pelo túnel — digamos https://abc123.trycloudflare.com.
  2. Gere um Verify Token — o assistente faz isso para você com secrets.token_urlsafe(32); se você está configurando na mão, rode:
    python -c "import secrets; print(secrets.token_urlsafe(32))"
    Salve como WHATSAPP_CLOUD_VERIFY_TOKEN em ~/.hermes/.env.
  3. Suba o gateway do Hermes: hermes gateway.
  4. No App Dashboard da Meta → WhatsApp → Configuration (ou Use cases → Customize → Configuration, dependendo da versão da interface) → clique em Edit na seção de Webhook.
  5. Preencha:
    • Callback URL: https://abc123.trycloudflare.com/whatsapp/webhook
    • Verify Token: a string do passo 2 (tem que bater exatamente)
  6. Clique em Verify and save. A Meta bate na sua URL com uma requisição GET, o gateway devolve o desafio e a Meta marca o webhook como verificado.
  7. Em Webhook fields, clique em Manage → inscreva-se no campo messages. É isso que diz para a Meta entregar de fato as mensagens de entrada no seu webhook.

Para verificar o circuito na mão (de um terceiro terminal):

TUNNEL="https://abc123.trycloudflare.com"
VERIFY="<seu verify token>"

# Deve imprimir HTTP 200 com o corpo "hello"
curl -i "$TUNNEL/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=$VERIFY&hub.challenge=hello"

# Endpoint de saúde — deve mostrar verify_token_configured: true e app_secret_configured: true
curl "$TUNNEL/health"

Lista de destinatários permitidos (lado da Meta)​

Em modo de desenvolvimento (antes do seu app passar pelo App Review), a Meta restringe quais números o seu bot pode contatar:

  1. App Dashboard → WhatsApp → API Setup → menu To.
  2. Clique em Manage phone number list.
  3. Adicione os números que você quer contatar (o seu, o do seu time, testadores amigos). A Meta manda um código de verificação de 6 dígitos para cada um, por SMS ou WhatsApp.

Até 5 números em modo de desenvolvimento. Passar pelo App Review remove esse limite.


Lista de permissão (lado do Hermes)​

Além da lista de destinatários permitidos da Meta, o Hermes tem a própria lista de permissão por plataforma, que controla quais mensagens de entrada o agente processa. Acrescente em ~/.hermes/.env:

# Números de telefone separados por vírgula, com código do país, sem '+' / espaços / hifens
WHATSAPP_CLOUD_ALLOWED_USERS=15551234567,15557654321

# Ou libere para todos (só é seguro em combinação com a lista de destinatários da Meta)
# WHATSAPP_CLOUD_ALLOW_ALL_USERS=true

O assistente configura isso no passo 6. Sem uma lista de permissão, toda mensagem de entrada é negada — isso é intencional, para o bot não poder ser acionado por números aleatórios se a lista de destinatários da Meta for afrouxada algum dia.


Dar acabamento ao perfil do bot no WhatsApp​

O WhatsApp exibe um nome e uma foto de perfil do seu bot no cabeçalho da conversa e na lista de contatos. Isso não pode ser definido pela Cloud API — mora no Business Manager da Meta.

Com o bot funcionando, vá em business.facebook.com/wa/manage/phone-numbers, clique no seu número de telefone e você encontra:

O quêOndeObservações
Nome de exibiçãoTopo da página do número de telefoneAs mudanças passam pelo processo de revisão de nome da Meta (~24 a 48 horas).
Foto de perfilTopo da página do número de telefoneImagem quadrada, recomendado ≥640×640 px. Atualiza na hora.
Sobre / descrição / site / e-mail / horário / categoriaBotão "Edit profile"Aparecem no painel de informações quando a pessoa toca no nome do bot. Cosmético.
Selo de verificado (tique verde)Business Manager → Security Center → Start VerificationExige o processo separado de verificação de empresa da Meta.

O assistente hermes whatsapp-cloud imprime esses links no fim da configuração. Nada disso é necessário para o bot funcionar — é puro acabamento na forma como o bot aparece para as pessoas.


Referência de configuração​

Todas as opções ficam em ~/.hermes/.env. Os valores obrigatórios estão em negrito.

VariávelPadrãoDescrição
WHATSAPP_CLOUD_PHONE_NUMBER_ID—O ID de 15 a 17 dígitos da página API Setup. Não é o número de telefone.
WHATSAPP_CLOUD_ACCESS_TOKEN—Token de acesso da Meta (começa com EAA). Temporário de 24 h ou permanente de System User.
WHATSAPP_CLOUD_APP_SECRET—Hexadecimal de 32 caracteres em Settings → Basic. Sem ele, a entrada é recusada com 503.
WHATSAPP_CLOUD_VERIFY_TOKEN—Segredo compartilhado do aperto de mão via GET. Gerado automaticamente pelo assistente.
WHATSAPP_CLOUD_ALLOWED_USERS—wa_ids separados por vírgula com permissão de falar com o bot.
WHATSAPP_CLOUD_ALLOW_ALL_USERSfalseDefina como true para ignorar a lista de permissão.
WHATSAPP_CLOUD_APP_ID—Opcional, para integração futura com analytics.
WHATSAPP_CLOUD_WABA_ID—Opcional, para integração futura com analytics.
WHATSAPP_CLOUD_WEBHOOK_HOSTnão definido (pilha dupla: todas as interfaces, IPv4+IPv6)Interface em que o servidor de webhook escuta.
WHATSAPP_CLOUD_WEBHOOK_PORT8090Porta em que o servidor de webhook escuta. Tem que bater com a porta que o seu túnel encaminha.
WHATSAPP_CLOUD_WEBHOOK_PATH/whatsapp/webhookCaminho de URL em que a Meta faz o POST.
WHATSAPP_CLOUD_API_VERSIONv20.0Versão da Graph API da Meta. Só sobrescreva se a documentação da Meta recomendar uma versão mais nova.
WHATSAPP_CLOUD_HOME_CHANNEL—wa_id a usar como canal principal do bot (para tarefas de cron etc.).

Você pode ter os dois adaptadores habilitados ao mesmo tempo, Baileys (whatsapp) e Cloud (whatsapp_cloud), apontando para números de telefone diferentes.


Recursos​

Entrada​

  • Mensagens de texto — passadas direto para o agente.
  • Imagens — baixadas automaticamente e anexadas à entrada do agente. Modelos com visão nativa (Claude, GPT-4o, Gemini etc.) leem a imagem direto; modelos sem visão recebem uma descrição de texto gerada automaticamente.
  • Notas de voz — baixadas automaticamente como .ogg, transcritas pelo seu provedor de STT configurado (faster-whisper local, OpenAI/Nous, Groq etc.) e entregues ao agente como texto.
  • Documentos — baixados automaticamente. Arquivos pequenos legíveis como texto (.txt, .md, .json, .py, .csv etc.) de até 100 KB são embutidos na entrada do agente para ele conseguir ler sem chamar uma ferramenta. Arquivos maiores ficam em cache local para as outras ferramentas do agente acessarem.
  • Toques em botões — quando a pessoa toca em um botão que o bot mandou antes (escolha de esclarecimento, aprovação de comando, confirmação de comando de barra), o toque é roteado direto para o tratador certo. Toques velhos caem no tratamento como entrada de texto comum.
  • Contexto de resposta — quando a pessoa responde a uma mensagem anterior do bot, o agente vê a mensagem original como contexto.

Saída​

  • Texto — o markdown é convertido automaticamente para a sintaxe do WhatsApp (**negrito** → *negrito*, ~~riscado~~ → ~riscado~, títulos → negrito, [link](url) → link (url)). Mensagens longas são divididas em pedaços de 4096 caracteres.
  • Imagens — imagens geradas pelo agente e arquivos de imagem locais, os dois suportados, entregues como anexos nativos de foto.
  • Mensagens de voz — a saída de texto para fala é convertida por ffmpeg na bolha nativa de nota de voz do WhatsApp (a onda verde). Sem o ffmpeg instalado, cai para um anexo de áudio MP3. Veja "Mensagens de voz" abaixo.
  • Vídeo / documentos — os dois suportados, enviados como anexos nativos.

Experiência interativa​

Quando o agente aciona um destes fluxos, o Hermes usa as mensagens interativas nativas do WhatsApp — botões de tocar para responder em vez de pedir "responda com o número":

  • ferramenta clarify — perguntas de múltipla escolha aparecem como botões de resposta rápida (1 a 3 opções) ou como uma folha de lista que abre ao toque (4 opções ou mais). Escolher "✏️ Other" deixa a pessoa digitar uma resposta livre, que o agente recebe como a resolução.
  • Aprovações de comando perigoso — quando a execução de terminal ou de código do agente esbarra em um comando controlado, a pessoa vê botões ✅ Approve / ❌ Deny em vez de precisar digitar /approve ou /deny.
  • Confirmações de comando de barra — comandos privilegiados como /reload-mcp mostram botões ✅ Approve Once / 🔒 Always / ❌ Cancel.

Todos os pedidos interativos degradam com elegância para texto puro se os botões não renderizarem (em clientes antigos do WhatsApp, por exemplo).

Confirmações de leitura e indicador de digitação​

O Hermes reconhece as mensagens de entrada na hora:

  • A sua mensagem mostra os tiques duplos azuis assim que o gateway a recebe.
  • O nome do bot na sua conversa do WhatsApp mostra "digitando…" enquanto o agente prepara a resposta.
  • O indicador de digitação desaparece sozinho quando a primeira mensagem de resposta do bot chega.

Isso deixa óbvio quando o bot já viu a sua mensagem, em contraste com quando ele ainda está montando a resposta.

Mensagens de voz​

O WhatsApp distingue entre uma "nota de voz" (a bolha com a onda verde) e um anexo genérico de arquivo de áudio. A diferença é puramente de codec: notas de voz precisam ser audio/ogg com codificação opus.

O TTS do Hermes produz MP3. Dois caminhos:

  • Com ffmpeg no PATH (recomendado) — o TTS de saída é convertido e chega como uma nota de voz de verdade. Instalação:
    • Windows: winget install Gyan.FFmpeg
    • macOS: brew install ffmpeg
    • Linux: gerenciador de pacotes
  • Sem ffmpeg — o TTS de saída chega como anexo de áudio MP3. Toca sem problema, só não parece uma nota de voz. Um aviso é emitido uma única vez no log do gateway para você saber.

Você pode conferir se o gateway encontrou o ffmpeg pelo endpoint de saúde:

curl http://localhost:8090/health
# procure por "ffmpeg_present": true

Limitações conhecidas​

Janela de conversa de 24 horas​

A Meta só permite mensagens em formato livre dentro de uma janela de 24 horas após a última mensagem de entrada da pessoa. Fora dessa janela, a única coisa que a API da Meta aceita é um template de mensagem pré-aprovado.

O que isso significa na prática:

  • Conversa reativa (a pessoa manda mensagem → o bot responde em até 24 h → a pessoa responde → ...) funciona para sempre. Isso cobre mais de 95% do uso normal de um bot.
  • Tarefas de cron que entregam no WhatsApp depois de um intervalo maior que 24 h falham com o código de erro 131047 do Graph ("Re-engagement message").
  • Resultados assíncronos de delegate_task de longa duração que levam mais de 24 h falham do mesmo jeito.
  • Assinantes de webhook que roteiam eventos externos para o WhatsApp falham quando a pessoa não mandou mensagem para o bot recentemente.

O Hermes avisa o agente sobre essa janela no prompt de sistema, então o modelo sabe mencionar isso ao agendar mensagens atrasadas.

O suporte a templates de mensagem (a solução para envios fora da janela) ainda não está implementado no Hermes. Se você precisa dele, abra uma issue — está planejado, mas esperando um sinal claro de demanda.

Conversas em grupo​

A Cloud API tem suporte limitado a grupos (controlado por nível de capacidade pela Meta). O adaptador whatsapp_cloud do Hermes hoje trata apenas mensagens diretas na v1. Se você precisa de grupos, use a ponte Baileys.

Limite de taxa de saída​

A taxa padrão da Meta é de 80 mensagens por segundo por número de telefone comercial, com upgrades disponíveis. O Hermes hoje não impõe esse limite do lado do cliente — envios de volume muito alto podem bater no limite da Meta.


Resolução de problemas​

A verificação da configuração falha ("URL couldn't be validated") no painel da Meta​

Quase sempre é um destes:

  • URL do túnel errada ou velha — os túneis rápidos do cloudflared mudam de URL. Pegue uma URL nova e atualize tanto o .env quanto o painel da Meta.
  • Verify token divergente — o token em WHATSAPP_CLOUD_VERIFY_TOKEN, no ~/.hermes/.env, tem que bater exatamente com o que você digitou no painel da Meta. Rode o teste com curl acima para confirmar primeiro que o aperto de mão de verificação do gateway funciona localmente.
  • Gateway não está rodando — confira se o hermes gateway está de pé.
  • App Secret não definido — sem ele, o Hermes recusa os POSTs de entrada com 503. A Meta interpreta isso como "não consigo validar".

graph error 100: Object with ID '...' does not exist​

Você colou o seu número de telefone (10 ou 11 dígitos) em WHATSAPP_CLOUD_PHONE_NUMBER_ID em vez do Phone Number ID (o ID interno de 15 a 17 dígitos da Meta). Confira de novo a página API Setup — o Phone Number ID aparece abaixo do menu "From".

O assistente pega isso com um validador agora, mas vale saber se você estiver configurando na mão.

graph error 190: Authentication Error​

Seu token de acesso é inválido. Subcódigos:

  • subcode 463 — token expirado. Tokens temporários duram 24 h. Gere outro, ou troque por um token permanente de System User (veja acima).
  • subcode 467 — token invalidado (revogado ou senha alterada).
  • Outros 190 — o token não tinha as permissões necessárias quando foi gerado. Confirme que as três (business_management, whatsapp_business_messaging, whatsapp_business_management) foram selecionadas.

graph error 131047: Re-engagement message​

A janela de conversa de 24 horas expirou (veja "Limitações conhecidas"). Ou:

  • Peça para a pessoa mandar mensagem para o bot primeiro, para reabrir a janela.
  • Espere o suporte a templates chegar ao Hermes.

Mensagem de entrada: media metadata fetch failed (status=401)​

As mesmas causas de raiz do 401 na saída (graph error 190) — o token de acesso é inválido ou expirou. Conserte o token.

O bot responde com JSON cru / vazamento de chamada de ferramenta​

Causa comum: o conjunto de ferramentas configurado para whatsapp_cloud não tem as ferramentas que o agente quer chamar. Confira hermes tools list e verifique se a plataforma está usando hermes-whatsapp (o conjunto de ferramentas padrão do adaptador Cloud, o mesmo do Baileys).

Se o modelo emite texto com cara de chamada de ferramenta em vez de uma chamada estruturada, costuma significar que o conjunto de ferramentas estava efetivamente vazio. Veja hermes_cli/platforms.py para o mapeamento plataforma → conjunto de ferramentas padrão.

O STT (transcrição de nota de voz) volta vazio ou com "could not transcribe"​

O padrão stt.provider: local exige pip install faster-whisper. Se você é assinante da Nous, pode rotear o STT pelo gateway gerenciado em vez disso — selecione Nous Subscription para speech-to-text em hermes tools, ou defina diretamente:

hermes config set stt.provider nous
hermes gateway restart

Isso usa o seu token de acesso do Nous Portal em vez de exigir uma chave separada da OpenAI. (Documentações antigas sugeriam stt.use_gateway true — essa flag é legado; hoje só a seleção do provedor controla o roteamento.)


Notas de segurança​

  • Trate o App Secret como uma senha — quem tiver acesso a ele pode forjar payloads de webhook que o Hermes vai aceitar como autênticos.
  • O verify token é um segredo compartilhado — o vazamento tem menos consequências (no pior caso, alguém poderia reinscrever o webhook da Meta em outra URL dele), mas evite comitá-lo do mesmo jeito.
  • O token de acesso é a identidade do seu bot — tokens de System User equivalem a chaves de API de vida longa. Rotacione na hora se uma implantação for comprometida.
  • O endpoint de webhook só aceita requisições assinadas quando WHATSAPP_CLOUD_APP_SECRET está definido — deixe definido até em desenvolvimento. Sem ele, o gateway recusa a entrega de entrada com HTTP 503.
  • O endpoint /health não é autenticado — é seguro expô-lo porque ele só reporta booleanos de presença de configuração, não os valores em si. Mas se você preferir não deixá-lo à vista, restrinja o acesso na camada de proxy reverso ou de túnel.

Comparação com a ponte Baileys​

Baileys (hermes whatsapp)Cloud API (hermes whatsapp-cloud)
Tipo de contaPessoalComercial
ConfiguraçãoLeitura de QR codeApp da Meta + WABA + token
DependênciasNode.js + npmPython puro (httpx + aiohttp)
ProcessoSubprocesso Node gerenciadoServidor de webhook aiohttp
Precisa de URL pública?NãoSim
Risco de banimento de contaSim (API não oficial)Não (suportado oficialmente)
EntradaConsulta à ponte NodePOST de webhook da Meta
SaídaPonte local → BaileysHTTPS para graph.facebook.com
GruposSuporte completoSó mensagens diretas (v1)
Janela de 24 hSem restriçãoRegra rígida — templates obrigatórios depois
Notas de voz (saída)NativasNativas com ffmpeg, MP3 como reserva
Confirmações de leituraNãoSim (tiques duplos azuis)
Indicador de digitaçãoNãoSim (desaparece na resposta)
Botões interativosSó reserva em textoNativos (clarify, aprovação, confirmação de barra)
Uso em produçãoArriscado (a Meta pode banir)Feito para isso

A maioria de quem roda o Hermes em projetos pessoais prefere o Baileys. A maioria de quem roda bots voltados a clientes prefere a Cloud API.


Veja também​