Mensagens de grupo (canal web WhatsApp)

Objetivo: deixar o Clawd em grupos de WhatsApp, acordando apenas quando mencionado, e mantendo aquela conversa separada da sessão pessoal de DM.

Nota: agents.list[].groupChat.mentionPatterns agora é usado por Telegram/Discord/Slack/iMessage também; esta documentação foca no comportamento específico do WhatsApp. Para configurações multi-agente, defina agents.list[].groupChat.mentionPatterns por agente (ou use messages.groupChat.mentionPatterns como fallback global).

O que está implementado (2025-12-03)

  • Modos de ativação: mention (padrão) ou always. mention exige um ping (menções reais do WhatsApp via mentionedJids, padrões regex, ou o E.164 do bot em qualquer lugar no texto). always acorda o agente em cada mensagem, mas ele deve responder apenas quando puder agregar valor; caso contrário retorna o token silencioso NO_REPLY. Padrões podem ser definidos no config (channels.whatsapp.groups) e sobrescritos por grupo via /activation. Quando channels.whatsapp.groups é definido, também funciona como allowlist de grupo (inclua "*" para permitir todos).
  • Política de grupo: channels.whatsapp.groupPolicy controla se mensagens de grupo são aceitas (open|disabled|allowlist). allowlist usa channels.whatsapp.groupAllowFrom (fallback: channels.whatsapp.allowFrom explícito). O padrão é allowlist (bloqueado até você adicionar remetentes).
  • Sessões por grupo: chaves de sessão seguem o formato agent:<agentId>:whatsapp:group:<jid>, então comandos como /verbose on ou /think high (enviados como mensagens avulsas) ficam restritos àquele grupo; o estado da DM pessoal não é afetado. Heartbeats são ignorados para threads de grupo.
  • Injeção de contexto: mensagens de grupo pendentes (padrão 50) que não acionaram uma execução são prefixadas sob [Chat messages since your last reply - for context], com a linha acionadora sob [Current message - respond to this]. Mensagens já na sessão não são reinjetadas.
  • Identificação do remetente: cada lote de grupo agora termina com [from: Nome do Remetente (+E164)] para que o Pi saiba quem está falando.
  • Efêmero/visualização única: desempacotamos antes de extrair texto/menções, então pings dentro deles ainda acionam.
  • Prompt de sistema de grupo: no primeiro turno de uma sessão de grupo (e sempre que /activation muda o modo), injetamos uma breve explicação no prompt de sistema como You are replying inside the WhatsApp group "<assunto>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context. Se os metadados não estiverem disponíveis, ainda informamos ao agente que é um chat de grupo.

Exemplo de configuração (WhatsApp)

Adicione um bloco groupChat em ~/.openclaw/openclaw.json para que pings por nome de exibição funcionem mesmo quando o WhatsApp remove o @ visual no corpo do texto:

{
  channels: {
    whatsapp: {
      groups: {
        "*": { requireMention: true },
      },
    },
  },
  agents: {
    list: [
      {
        id: "main",
        groupChat: {
          historyLimit: 50,
          mentionPatterns: ["@?openclaw", "\\+?15555550123"],
        },
      },
    ],
  },
}

Observações:

  • Os regexes são case-insensitive; cobrem um ping por nome de exibição como @openclaw e o número bruto com ou sem +/espaços.
  • O WhatsApp ainda envia menções canônicas via mentionedJids quando alguém toca no contato, então o fallback por número raramente é necessário mas serve como rede de segurança.

Comando de ativação (apenas dono)

Use o comando no chat de grupo:

  • /activation mention
  • /activation always

Apenas o número do dono (de channels.whatsapp.allowFrom, ou o E.164 do próprio bot quando não definido) pode alterar isso. Envie /status como mensagem avulsa no grupo para ver o modo de ativação atual.

Como usar

  1. Adicione sua conta do WhatsApp (a que roda o OpenClaw) ao grupo.
  2. Diga @openclaw … (ou inclua o número). Apenas remetentes na allowlist podem acioná-lo, a menos que defina groupPolicy: "open".
  3. O prompt do agente incluirá o contexto recente do grupo mais o marcador [from: …] ao final para que ele possa responder à pessoa certa.
  4. Diretivas de nível de sessão (/verbose on, /think high, /new ou /reset, /compact) se aplicam apenas à sessão daquele grupo; envie-as como mensagens avulsas para que sejam registradas. Sua sessão pessoal de DM permanece independente.

Testes / verificação

  • Smoke test manual:
    • Envie um ping @openclaw no grupo e confirme uma resposta que referencia o nome do remetente.
    • Envie um segundo ping e verifique se o bloco de histórico é incluído e depois limpo no próximo turno.
  • Verifique os logs do gateway (execute com --verbose) para ver entradas inbound web message mostrando from: <groupJid> e o sufixo [from: …].

Considerações conhecidas

  • Heartbeats são intencionalmente ignorados para grupos a fim de evitar broadcasts ruidosos.
  • A supressão de eco usa a string combinada do lote; se você enviar texto idêntico duas vezes sem menções, apenas a primeira receberá resposta.
  • Entradas do session store aparecerão como agent:<agentId>:whatsapp:group:<jid> no session store (~/.openclaw/agents/<agentId>/sessions/sessions.json por padrão); uma entrada ausente apenas significa que o grupo ainda não acionou uma execução.
  • Indicadores de digitação em grupos seguem agents.defaults.typingMode (padrão: message quando não mencionado).