Skip to content

WhatsApp Channel

WhatsApp Channel Setup

Monitor WhatsApp groups via your OpenClaw agent to provide daily summaries, react to messages, and flag urgent items.

How It Works

Your personal WhatsApp is linked as a device to the agent Mac via the OpenClaw WhatsApp plugin (Baileys/WhatsApp Web). Everything the agent does on WhatsApp appears as you.

Flow:

  1. Messages flow into the group
  2. Groups with requireMention: false pass all messages to the agent session. Groups with requireMention: true only pass messages where the agent is @mentioned — all others are silently dropped before reaching the session.
  3. Every heartbeat cycle (~1h), the agent reviews messages in the session
  4. The agent occasionally reacts to a message with an emoji
  5. If something urgent is detected -> immediate ping to owner via iMessage
  6. Once daily (evening) -> agent sends a summary of the day’s chat via iMessage

Setup Steps

1. Enable WhatsApp Plugin

The WhatsApp plugin ships with OpenClaw but is disabled by default:

Terminal window
openclaw plugins enable whatsapp
Terminal window
openclaw channels login

Scan the QR code using WhatsApp -> Settings -> Linked Devices on your phone. This links the agent Mac as a WhatsApp Web device.

3. Gateway Config

Add to ~/.openclaw/openclaw.json under channels:

"whatsapp": {
"dmPolicy": "disabled",
"selfChatMode": true,
"groupPolicy": "allowlist",
"groupAllowFrom": [
"+1XXXXXXXXXX",
"+1XXXXXXXXXX"
],
"groups": {
"*": {
"requireMention": true
}
},
"sendReadReceipts": true
}

Key settings:

  • dmPolicy: “disabled” — no WhatsApp DMs, only group monitoring. Change to "allowlist" with allowFrom to enable DMs for testing.
  • selfChatMode: true — this is your own phone number
  • groupPolicy: “allowlist” — only accept messages from explicitly allowed senders in groups (prevents prompt injection escalation via elevated tools)
  • groupAllowFrom — E.164 phone numbers of senders whose group messages should reach the agent. Use ["*"] to allow all group participants. This must contain phone numbers, not group JIDs — the gateway matches each sender’s phone number against this list.
  • requireMention: trueapplyGroupGating drops all messages where the agent is not @mentioned. Messages that don’t mention the agent never reach the session — the agent can’t see them, react to them, or include them in summaries. Override per-group with requireMention: false for groups where the agent should passively monitor (see below)
  • sendReadReceipts: true — mark messages as read

Per-group requireMention override:

To let the agent passively monitor a specific group (see all messages, react, summarize) while keeping other groups mention-gated:

"groups": {
"*": {
"requireMention": true
},
"requireMention": false
}
}

The * wildcard applies to all groups not explicitly listed. Groups with requireMention: false will have every message flow into the agent’s session — the agent can see message IDs, sender info, and content, enabling reactions and summaries.

4. Agent Binding

Route all WhatsApp traffic to a dedicated WhatsApp agent. This isolates WhatsApp-specific issues from iMessage and other channels:

{
"agentId": "wa-agent",
"match": {
"channel": "whatsapp",
"peer": {
"kind": "group",
}
}
}

Add a catch-all for remaining WhatsApp traffic (DMs and other groups):

{
"agentId": "wa-agent",
"match": {
"channel": "whatsapp"
}
}

Why a separate agent? A dedicated WhatsApp agent provides better isolation — channel-specific failures stay contained and don’t affect iMessage DMs or group chats.

5. Agent Config Updates

HEARTBEAT.md — Add WhatsApp monitoring tasks:

  • Group check (2-3x/day): review group history, react to 1-2 messages
  • Daily summary (1x/day, evening): send summary to owner via iMessage
  • Urgent items: immediate iMessage ping for health/safety/time-sensitive items

AGENTS.md — Add group chat guidelines:

  • Listen-mostly role
  • React naturally with heartfelt emoji
  • Never respond unless @mentioned
  • Route all summaries/pings via iMessage, not WhatsApp

Shadow Mode (sendPolicy)

To prevent the agent from sending text replies into group chats while still allowing observation and reactions, add a session.sendPolicy deny rule:

"session": {
"sendPolicy": {
"rules": [
{
"action": "deny",
"match": {
"channel": "whatsapp",
"chatType": "group"
}
}
],
"default": "allow"
}
}

In shadow mode, the agent:

  • Observes all group messages (they flow into the session normally)
  • Reacts to messages with emoji (reactions bypass sendPolicy)
  • Cannot send text replies or auto-reply error messages into groups
  • Can still reply in WhatsApp DMs (sendPolicy only blocks group chatType)

The main agent monitors WhatsApp group activity by reading the WhatsApp agent’s session via sessions_history during heartbeat check-ins.

Reactions

WhatsApp reactions are supported via the gateway’s react action. During heartbeat, the agent can:

  1. Fetch group history to see messages with IDs
  2. Call the react action with chatJid, messageId, and emoji
  3. Reactions appear in WhatsApp as you

Preferred emoji palette: ❤️, 😂, 👍, 🙌, 🥰

Reactions are delayed by up to the heartbeat interval (~1h), which actually feels natural — like you checked your phone later and hearted something.

Identity Rules

With selfChatMode: true, everything the agent does on WhatsApp appears as you:

  • NEVER use the agent’s emoji prefix or branding
  • NEVER sign messages or hint that an AI is writing
  • Send EXACTLY what the owner approves — no paraphrasing

Gap Recovery with wacli

OpenClaw’s Baileys connection occasionally times out (408 errors), missing messages. wacli provides a separate WhatsApp device link for gap recovery.

Installation

Terminal window
brew install steipete/tap/wacli

Usage

Terminal window
# Fetch group history
wacli messages list --chat "[email protected]" --limit N
# Search all messages
wacli messages search "query"
# Continuous sync (run in background)
wacli sync --follow
# Check auth status
wacli auth status

Important: Store locks if multiple wacli processes run simultaneously. Don’t run wacli sync while manually querying.

Cross-Channel Access (from BlueBubbles)

When the agent is in a BlueBubbles-bound session (e.g., chatting with the owner via iMessage), the message tool is constrained to BlueBubbles. To interact with WhatsApp from that session, use sessions_send:

  1. sessions_list — find WhatsApp session keys (filter by channel: "whatsapp")
  2. sessions_send — send the instruction to the WhatsApp session key (e.g., “Read recent messages from the family group” or “React with a heart to the last message from Mom”)
  3. The run executes in the WhatsApp-bound session where message works for WhatsApp
  4. The reply comes back via the ping-pong loop

Required config (already set in Lobster’s config):

  • session.dmScope: "per-channel-peer" — BlueBubbles and WhatsApp have separate sessions
  • tools.sessions.visibility: "all" — agent can see all sessions
  • sessions_send in the agent’s allowed tools

This works for reads, reactions, and message history — not just sends. The WhatsApp outbound restriction (no individual messages) still applies even via sessions_send.

Resilience and Recovery

Channel Health Monitor

Enable the gateway health monitor to auto-restart channels that go stale:

"gateway": {
"channelHealthCheckMinutes": 5
}

The health monitor checks every 5 minutes. If no inbound events arrive within 30 minutes (default stale threshold), the gateway auto-restarts the channel. Cap: 10 restarts/hour.

Important: The health monitor alone does not fix the jiti VM realm isolation bug (see below). Apply the listener patch first, then enable the health monitor — otherwise restarts will cycle without recovering the listener.

Listener Realm Isolation (Patch Required)

After a Baileys WebSocket disconnect/reconnect (e.g., DNS outage, WhatsApp server maintenance), the listener may re-register in a new jiti VM realm while the delivery code reads from the old realm’s empty Map. Symptoms:

  • Outbound sends fail with “No active WhatsApp Web listener”
  • openclaw channels status --probe still reports “connected” (false positive)
  • Inbound messages stop flowing silently

Fix: Apply openclaw-patch-wa-listeners (bridges the listener Map via process.__openclawWaWebListeners). Must be re-applied after every openclaw update.

Upstream: #50208

SecretRef Crash on Inbound Messages

If the WhatsApp embedded agent crashes with unresolved SecretRef errors, the agent is reading raw config instead of the gateway’s resolved runtime snapshot. Inline the affected secret values directly in openclaw.json as a workaround.

Upstream: #49427

Notes

  • WhatsApp does not support the read message action — sendReadReceipts may behave differently than BlueBubbles
  • WhatsApp does not support the resolve command — group JIDs can’t be looked up by name
  • selfChatMode means messages the owner sends won’t appear as inbound — only messages from other group members trigger events
  • WhatsApp group messages route to their own session — use sessions_history to check, not message poll