whatsapp bundled extension owns platform dependencies, login, session inspection, outbound delivery, polls, and reactions.
Prerequisites
- A WhatsApp-capable phone number (a dedicated number is recommended — see Deployment patterns)
- Node.js 24+ on the gateway host
- The phone holding the linked number online during linking
Installation
The WhatsApp plugin ships bundled but requires its runtime dependency (@whiskeysockets/baileys) to be installed separately:
openclaw plugins list shows deps missing for the whatsapp plugin and the gateway emits a PLUGIN_DEPS_MISSING warning at boot.
If the automated install fails, navigate to
~/.openclaw/extensions/whatsapp and run npm install --omit=dev manually.Quick setup
Link the WhatsApp number
openclaw channels login --channel whatsapp --account work.If the gateway is already running for this account, use the gateway’s login flow — a direct CLI login against the same auth directory will refuse to start while the gateway owns the socket lock.Start the gateway and approve pairing
Deployment patterns
Dedicated number (recommended)
Dedicated number (recommended)
A separate WhatsApp number for WednesdayAI gives cleaner routing, clearer
allowFrom lists, and avoids self-chat confusion:Personal number
Personal number
Supported but adds operational complexity. The onboarding wizard sets a self-chat-friendly baseline when you choose personal-number mode:With
selfChatMode: true (or when the linked self number is in allowFrom), self-chat read receipts are skipped and self-mention triggers are suppressed. If messages.responsePrefix is unset, self-chat replies default to [WednesdayAI].Access control
DM policy
dmPolicy | Effect |
|---|---|
"pairing" | New senders get a one-time pairing code; ignored until approved (default) |
"allowlist" | Only numbers in allowFrom can initiate DMs |
"open" | Any sender allowed (requires allowFrom: ["*"]) |
"disabled" | Bot ignores all DMs |
allowFrom accepts E.164-style numbers. Approved pairings are persisted in the allow-store and merged with configured allowFrom at runtime. If no allowFrom is configured, the linked self number is allowed by default.
Per-account override: channels.whatsapp.accounts.<id>.dmPolicy and accounts.<id>.allowFrom take precedence over channel-level defaults for that account.
Group policy
- Group membership — if
groupsis present, it acts as an allowlist; omit it to allow all groups."*"allows all. - Sender policy —
groupPolicy+groupAllowFrom. IfgroupAllowFromis unset, the runtime falls back toallowFrom.
Mention gating
Group messages require a mention by default. To allow responses without a mention:mentionPatterns, and reply-to-bot detection. Per-session activation: /activation mention or /activation always (owner-gated).
Security note: a quote/reply satisfies mention gating but does not grant sender authorization. Non-allowlisted senders are still blocked with groupPolicy: "allowlist" even if they reply to an allowlisted user.
Message handling
Group history injection
When the bot is triggered in a group after a gap, unprocessed messages are injected as context:[Chat messages since your last reply - for context] / [Current message - respond to this] markers.
Inbound media
Media-only messages are normalized to placeholders:<media:image>, <media:video>, <media:audio>, <media:document>, <media:sticker>. Location and contact payloads are converted to text before routing.
Delivery settings
sendReadReceipts:
Acknowledgment reactions
React to inbound messages before the reply is sent:group: "mentions" reacts only on mention-triggered turns; session activation always bypasses this check.
Actions and config writes
Gate outbound actions per channel:Multi-account setup
default if present, otherwise the first configured account id (sorted). Per-account dmPolicy, allowFrom, sendReadReceipts, and other overrides are supported.
Credentials and storage
WhatsApp credentials live at~/.openclaw/credentials/whatsapp/<accountId>/creds.json. A recent mtime indicates an active session; a stale or missing file means the account is logged out.
Active sockets create a .socket-owner.lock next to credentials to prevent cross-process collisions. Stale locks from dead processes are removed automatically via PID checks.
To log out an account:
oauth.json and unrelated state are preserved.
Disabling without removing config
systemctl --user restart openclaw-gateway.
Troubleshooting
Not linked / QR code not working
Not linked / QR code not working
Linked but disconnected / reconnect loop
Linked but disconnected / reconnect loop
Repeated disconnects or reconnect attempts after a successful link:If the account shows a reconnect loop, re-link:
openclaw channels logout --channel whatsapp && openclaw channels login --channel whatsapp.Status codes 409–515 in logs
Status codes 409–515 in logs
A conflicting WhatsApp Web session is open in a browser. Close all other WhatsApp Web browser sessions, then relink. Status 515 auto-retries once after pairing — this is normal.
Group messages not routing to the agent
Group messages not routing to the agent
Check in this order:
groupPolicyallows the groupgroupAllowFromincludes the sender (or falls back toallowFrom)groupsallowlist includes the group JID (or is omitted to allow all)- Mention gating:
requireMention: false, or the message mentions the bot - No duplicate keys in
openclaw.json(openclaw doctor) — later entries override earlier ones silently
No active listener when sending
No active listener when sending
Outbound sends fail when no active gateway listener exists for the target account:
deps missing / PLUGIN_DEPS_MISSING warning
deps missing / PLUGIN_DEPS_MISSING warning
Run
openclaw plugins install whatsapp to reinstall the plugin and its dependencies. If that fails, navigate to ~/.openclaw/extensions/whatsapp and run npm install --omit=dev manually.Configuration reference
Full field reference for all WhatsApp config options (access, delivery, multi-account, operations, session): High-signal fields:dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, textChunkLimit, chunkMode, mediaMaxMb, sendReadReceipts, ackReaction, historyLimit, actions, configWrites, accounts.<id>.*