WhatsApp (canal Web)
Status: pronto para produção via WhatsApp Web (Baileys). O Gateway gerencia sessão(ões) vinculada(s).
- Pareamento — A política de DM padrão é pareamento para remetentes desconhecidos.
- Solução de problemas de canais — Diagnósticos e guias de reparo entre canais.
- Configuração do gateway — Padrões completos de configuração de canais e exemplos.
Configuração rápida
Passo 1: Configure a política de acesso do WhatsApp
{
channels: {
whatsapp: {
dmPolicy: "pairing",
allowFrom: ["+15551234567"],
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
},
},
}
Passo 2: Vincule o WhatsApp (QR)
openclaw channels login --channel whatsapp
Para uma conta específica:
openclaw channels login --channel whatsapp --account work
Passo 3: Inicie o gateway
openclaw gateway
Passo 4: Aprove a primeira solicitação de pareamento (se estiver usando modo de pareamento)
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
Solicitações de pareamento expiram após 1 hora. Solicitações pendentes são limitadas a 3 por canal.
Nota: O OpenClaw recomenda rodar o WhatsApp em um número separado sempre que possível. (Os metadados do canal e o fluxo de onboarding são otimizados para essa configuração, mas setups com número pessoal também são suportados.)
Padrões de implantação
Número dedicado (recomendado)
Este é o modo operacional mais limpo:
- identidade WhatsApp separada para o OpenClaw
- listas de permitidos de DM e limites de roteamento mais claros
- menor chance de confusão com self-chat
Padrão de política mínima:
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
Fallback com número pessoal
O onboarding suporta modo com número pessoal e grava uma configuração base compatível com self-chat:
- `dmPolicy: "allowlist"`
- `allowFrom` inclui seu número pessoal
- `selfChatMode: true`
Em runtime, as proteções de self-chat se baseiam no número self vinculado e no `allowFrom`.
Escopo de canal exclusivo WhatsApp Web
O canal da plataforma de mensagens é baseado em WhatsApp Web (`Baileys`) na arquitetura atual de canais de chat do OpenClaw.
Não existe um canal separado de mensagens Twilio WhatsApp no registro nativo de canais de chat.
Modelo de runtime
- O Gateway gerencia o socket do WhatsApp e o loop de reconexão.
- Envios de saída exigem um listener ativo do WhatsApp para a conta de destino.
- Chats de status e broadcast são ignorados (
@status,@broadcast). - Chats diretos usam regras de sessão de DM (
session.dmScope; o padrãomainconsolida DMs na sessão principal do agente). - Sessões de grupo são isoladas (
agent:<agentId>:whatsapp:group:<jid>).
Controle de acesso e ativação
Política de DM
`channels.whatsapp.dmPolicy` controla o acesso a chats diretos:
- `pairing` (padrão)
- `allowlist`
- `open` (requer que `allowFrom` inclua `"*"`)
- `disabled`
`allowFrom` aceita números no formato E.164 (normalizados internamente).
Sobrescrita por conta: `channels.whatsapp.accounts.<id>.dmPolicy` (e `allowFrom`) têm precedência sobre os padrões de nível de canal para aquela conta.
Detalhes de comportamento em runtime:
- pareamentos são persistidos no allow-store do canal e mesclados com o `allowFrom` configurado
- se nenhuma lista de permitidos estiver configurada, o número self vinculado é permitido por padrão
- DMs de saída `fromMe` nunca são auto-pareadas
Política de grupo + listas de permitidos
O acesso a grupos tem duas camadas:
1. **Lista de permitidos de membros do grupo** (`channels.whatsapp.groups`)
- se `groups` for omitido, todos os grupos são elegíveis
- se `groups` estiver presente, funciona como lista de permitidos de grupo (`"*"` é aceito)
2. **Política de remetentes de grupo** (`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
- `open`: lista de permitidos de remetentes é ignorada
- `allowlist`: remetente deve corresponder a `groupAllowFrom` (ou `*`)
- `disabled`: bloqueia todo tráfego de entrada de grupo
Fallback de lista de permitidos de remetentes:
- se `groupAllowFrom` não estiver definido, o runtime recorre ao `allowFrom` quando disponível
- listas de permitidos de remetentes são avaliadas antes da ativação por menção/resposta
Observação: se não existir nenhum bloco `channels.whatsapp`, o fallback de política de grupo em runtime é `allowlist` (com log de aviso), mesmo que `channels.defaults.groupPolicy` esteja definido.
Menções + /ativação
Respostas em grupo exigem menção por padrão.
A detecção de menção inclui:
- menções explícitas do WhatsApp à identidade do bot
- padrões regex de menção configurados (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`)
- detecção implícita de resposta ao bot (remetente da resposta corresponde à identidade do bot)
Observação de segurança:
- citação/resposta apenas satisfaz o filtro de menção; **não** concede autorização de remetente
- com `groupPolicy: "allowlist"`, remetentes fora da lista continuam bloqueados mesmo se responderem à mensagem de um usuário autorizado
Comando de ativação por sessão:
- `/activation mention`
- `/activation always`
`activation` atualiza o estado da sessão (não a configuração global). É restrito ao proprietário.
Comportamento de número pessoal e self-chat
Quando o número self vinculado também está presente em allowFrom, as proteções de self-chat do WhatsApp são ativadas:
- pular confirmações de leitura para turnos de self-chat
- ignorar comportamento de auto-acionamento por JID de menção que normalmente faria ping em você mesmo
- se
messages.responsePrefixnão estiver definido, respostas de self-chat usam[{identity.name}]ou[openclaw]por padrão
Normalização de mensagens e contexto
Envelope de entrada + contexto de resposta
Mensagens de entrada do WhatsApp são encapsuladas no envelope compartilhado de entrada.
Se uma resposta citada existir, o contexto é anexado neste formato:
```text
[Replying to <sender> id:<stanzaId>]
<quoted body or media placeholder>
[/Replying]
```
Campos de metadados de resposta também são preenchidos quando disponíveis (`ReplyToId`, `ReplyToBody`, `ReplyToSender`, JID/E.164 do remetente).
Placeholders de mídia e extração de localização/contato
Mensagens de entrada somente com mídia são normalizadas com placeholders como:
- `<media:image>`
- `<media:video>`
- `<media:audio>`
- `<media:document>`
- `<media:sticker>`
Payloads de localização e contato são normalizados em contexto textual antes do roteamento.
Injeção de histórico pendente de grupo
Para grupos, mensagens não processadas podem ser armazenadas em buffer e injetadas como contexto quando o bot é finalmente acionado.
- limite padrão: `50`
- config: `channels.whatsapp.historyLimit`
- fallback: `messages.groupChat.historyLimit`
- `0` desabilita
Marcadores de injeção:
- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
Confirmações de leitura
Confirmações de leitura são habilitadas por padrão para mensagens de entrada aceitas do WhatsApp.
Desabilitar globalmente:
```json5
{
channels: {
whatsapp: {
sendReadReceipts: false,
},
},
}
```
Sobrescrita por conta:
```json5
{
channels: {
whatsapp: {
accounts: {
work: {
sendReadReceipts: false,
},
},
},
},
}
```
Turnos de self-chat pulam confirmações de leitura mesmo quando habilitadas globalmente.
Entrega, fragmentação e mídia
Fragmentação de texto
- limite padrão de fragmento: `channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.chunkMode = "length" | "newline"`
- modo `newline` prioriza limites de parágrafo (linhas em branco), depois recorre à fragmentação segura por comprimento
Comportamento de mídia de saída
- suporta payloads de imagem, vídeo, áudio (nota de voz PTT) e documento
- `audio/ogg` é reescrito para `audio/ogg; codecs=opus` para compatibilidade com notas de voz
- reprodução de GIF animado é suportada via `gifPlayback: true` em envios de vídeo
- legendas são aplicadas ao primeiro item de mídia ao enviar payloads de resposta com múltiplas mídias
- a fonte de mídia pode ser HTTP(S), `file://` ou caminhos locais
Limites de tamanho de mídia e comportamento de fallback
- limite de salvamento de mídia de entrada: `channels.whatsapp.mediaMaxMb` (padrão `50`)
- limite de envio de mídia de saída: `channels.whatsapp.mediaMaxMb` (padrão `50`)
- sobrescritas por conta usam `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
- imagens são otimizadas automaticamente (redimensionamento/varredura de qualidade) para caber nos limites
- em caso de falha no envio de mídia, o fallback do primeiro item envia um aviso em texto em vez de descartar a resposta silenciosamente
Reações de confirmação
O WhatsApp suporta reações imediatas de confirmação no recebimento de entrada via channels.whatsapp.ackReaction.
{
channels: {
whatsapp: {
ackReaction: {
emoji: "👀",
direct: true,
group: "mentions", // always | mentions | never
},
},
},
}
Observações de comportamento:
- enviada imediatamente após a entrada ser aceita (antes da resposta)
- falhas são registradas nos logs mas não bloqueiam a entrega normal da resposta
- modo de grupo
mentionsreage em turnos acionados por menção; ativação de grupoalwaysfunciona como bypass para esta verificação - WhatsApp usa
channels.whatsapp.ackReaction(o legadomessages.ackReactionnão é usado aqui)
Múltiplas contas e credenciais
Seleção de conta e padrões
- IDs de conta vêm de `channels.whatsapp.accounts`
- seleção de conta padrão: `default` se presente, caso contrário o primeiro ID de conta configurado (ordenado)
- IDs de conta são normalizados internamente para consulta
Caminhos de credenciais e compatibilidade legada
- caminho de autenticação atual: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- arquivo de backup: `creds.json.bak`
- autenticação legada padrão em `~/.openclaw/credentials/` ainda é reconhecida/migrada para fluxos de conta padrão
Comportamento de logout
`openclaw channels logout --channel whatsapp [--account <id>]` limpa o estado de autenticação do WhatsApp para aquela conta.
Em diretórios de autenticação legados, `oauth.json` é preservado enquanto arquivos de autenticação do Baileys são removidos.
Ferramentas, ações e escritas de configuração
- O suporte a ferramentas do agente inclui ação de reação do WhatsApp (
react). - Controles de ação:
channels.whatsapp.actions.reactionschannels.whatsapp.actions.polls
- Escritas de configuração iniciadas pelo canal são habilitadas por padrão (desabilite via
channels.whatsapp.configWrites=false).
Solução de problemas
Não vinculado (QR necessário)
Sintoma: o status do canal reporta não vinculado.
Solução:
```bash
openclaw channels login --channel whatsapp
openclaw channels status
```
Vinculado mas desconectado / loop de reconexão
Sintoma: conta vinculada com desconexões ou tentativas de reconexão repetidas.
Solução:
```bash
openclaw doctor
openclaw logs --follow
```
Se necessário, vincule novamente com `channels login`.
Sem listener ativo ao enviar
Envios de saída falham imediatamente quando não existe listener ativo do gateway para a conta de destino.
Certifique-se de que o gateway está rodando e a conta está vinculada.
Mensagens de grupo ignoradas inesperadamente
Verifique nesta ordem:
- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- entradas da lista de permitidos de `groups`
- filtro de menção (`requireMention` + padrões de menção)
- chaves duplicadas no `openclaw.json` (JSON5): entradas posteriores sobrescrevem anteriores, então mantenha um único `groupPolicy` por escopo
Aviso de runtime do Bun
O runtime do gateway WhatsApp deve usar Node. O Bun é sinalizado como incompatível para operação estável do gateway WhatsApp/Telegram.
Referência de configuração
Referência principal:
Campos de alto impacto do WhatsApp:
- acesso:
dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups - entrega:
textChunkLimit,chunkMode,mediaMaxMb,sendReadReceipts,ackReaction - múltiplas contas:
accounts.<id>.enabled,accounts.<id>.authDir, sobrescritas por conta - operações:
configWrites,debounceMs,web.enabled,web.heartbeatSeconds,web.reconnect.* - comportamento de sessão:
session.dmScope,historyLimit,dmHistoryLimit,dms.<id>.historyLimit