WhatsApp (canal Web)

Status: pronto para produção via WhatsApp Web (Baileys). O Gateway gerencia sessão(ões) vinculada(s).

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ão main consolida 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.responsePrefix nã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 mentions reage em turnos acionados por menção; ativação de grupo always funciona como bypass para esta verificação
  • WhatsApp usa channels.whatsapp.ackReaction (o legado messages.ackReaction nã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.reactions
    • channels.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

Relacionados