2025-12-23 03:00:27 +01:00
---
2026-02-11 12:31:56 -05:00
summary: "WhatsApp channel support, access controls, delivery behavior, and operations"
2025-12-23 03:00:27 +01:00
read_when:
2026-01-13 06:16:43 +00:00
- Working on WhatsApp/web channel behavior or inbox routing
2026-01-31 16:04:03 -05:00
title: "WhatsApp"
2025-12-23 03:00:27 +01:00
---
2026-02-11 12:31:56 -05:00
# WhatsApp (Web channel)
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
Status: production-ready via WhatsApp Web (Baileys). Gateway owns linked session(s).
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
< CardGroup cols = {3} >
< Card title = "Pairing" icon = "link" href = "/channels/pairing" >
Default DM policy is pairing for unknown senders.
< / Card >
< Card title = "Channel troubleshooting" icon = "wrench" href = "/channels/troubleshooting" >
Cross-channel diagnostics and repair playbooks.
< / Card >
< Card title = "Gateway configuration" icon = "settings" href = "/gateway/configuration" >
Full channel config patterns and examples.
< / Card >
< / CardGroup >
2026-01-31 21:13:13 +09:00
2026-02-21 11:18:29 -05:00
## Quick setup
2026-01-11 02:40:28 +01:00
2026-02-11 12:31:56 -05:00
< Steps >
< Step title = "Configure WhatsApp access policy" >
2026-01-31 21:13:13 +09:00
2026-01-11 02:40:28 +01:00
```json5
{
2026-01-13 06:16:43 +00:00
channels: {
whatsapp: {
2026-02-11 12:31:56 -05:00
dmPolicy: "pairing",
2026-01-31 21:13:13 +09:00
allowFrom: ["+15551234567"],
2026-02-11 12:31:56 -05:00
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
2026-01-31 21:13:13 +09:00
},
},
2026-01-11 02:40:28 +01:00
}
```
2026-02-11 12:31:56 -05:00
< / Step >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Step title = "Link WhatsApp (QR)" >
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
```bash
openclaw channels login --channel whatsapp
```
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
For a specific account:
2026-01-15 01:41:11 +00:00
2026-02-11 12:31:56 -05:00
```bash
openclaw channels login --channel whatsapp --account work
```
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< / Step >
< Step title = "Start the gateway" >
```bash
openclaw gateway
2026-01-15 01:41:11 +00:00
```
2026-02-11 12:31:56 -05:00
< / Step >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Step title = "Approve first pairing request (if using pairing mode)" >
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
```bash
openclaw pairing list whatsapp
openclaw pairing approve whatsapp < CODE >
```
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
Pairing requests expire after 1 hour. Pending requests are capped at 3 per channel.
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
< / Step >
< / Steps >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Note >
OpenClaw recommends running WhatsApp on a separate number when possible. (The channel metadata and onboarding flow are optimized for that setup, but personal-number setups are also supported.)
< / Note >
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
## Deployment patterns
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
< AccordionGroup >
< Accordion title = "Dedicated number (recommended)" >
This is the cleanest operational mode:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- separate WhatsApp identity for OpenClaw
- clearer DM allowlists and routing boundaries
- lower chance of self-chat confusion
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
Minimal policy pattern:
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< / Accordion >
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
< Accordion title = "Personal-number fallback" >
Onboarding supports personal-number mode and writes a self-chat-friendly baseline:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- `dmPolicy: "allowlist"`
- `allowFrom` includes your personal number
- `selfChatMode: true`
2026-01-09 00:19:44 +01:00
2026-02-11 12:31:56 -05:00
In runtime, self-chat protections key off the linked self number and `allowFrom` .
2026-01-09 16:39:32 +01:00
2026-02-11 12:31:56 -05:00
< / Accordion >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Accordion title = "WhatsApp Web-only channel scope" >
The messaging platform channel is WhatsApp Web-based (`Baileys` ) in current OpenClaw channel architecture.
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
There is no separate Twilio WhatsApp messaging channel in the built-in chat-channel registry.
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
< / Accordion >
< / AccordionGroup >
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
## Runtime model
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- Gateway owns the WhatsApp socket and reconnect loop.
- Outbound sends require an active WhatsApp listener for the target account.
- Status and broadcast chats are ignored (`@status` , `@broadcast` ).
- Direct chats use DM session rules (`session.dmScope` ; default `main` collapses DMs to the agent main session).
- Group sessions are isolated (`agent:<agentId>:whatsapp:group:<jid>` ).
2026-01-07 16:54:37 +01:00
2026-02-11 12:31:56 -05:00
## Access control and activation
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Tabs >
< Tab title = "DM policy" >
`channels.whatsapp.dmPolicy` controls direct chat access:
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
- `pairing` (default)
- `allowlist`
- `open` (requires `allowFrom` to include `"*"` )
- `disabled`
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
`allowFrom` accepts E.164-style numbers (normalized internally).
2026-01-07 20:49:44 +01:00
2026-02-14 21:09:01 +01:00
Multi-account override: `channels.whatsapp.accounts.<id>.dmPolicy` (and `allowFrom` ) take precedence over channel-level defaults for that account.
2026-02-11 12:31:56 -05:00
Runtime behavior details:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- pairings are persisted in channel allow-store and merged with configured `allowFrom`
- if no allowlist is configured, the linked self number is allowed by default
- outbound `fromMe` DMs are never auto-paired
2026-01-07 20:49:44 +01:00
2026-02-11 12:31:56 -05:00
< / Tab >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Tab title = "Group policy + allowlists" >
Group access has two layers:
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
1. **Group membership allowlist** (`channels.whatsapp.groups` )
- if `groups` is omitted, all groups are eligible
- if `groups` is present, it acts as a group allowlist (`"*"` allowed)
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
2. **Group sender policy** (`channels.whatsapp.groupPolicy` + `groupAllowFrom` )
- `open` : sender allowlist bypassed
- `allowlist` : sender must match `groupAllowFrom` (or `*` )
- `disabled` : block all group inbound
2026-01-15 06:21:05 +00:00
2026-02-11 12:31:56 -05:00
Sender allowlist fallback:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- if `groupAllowFrom` is unset, runtime falls back to `allowFrom` when available
2026-02-19 09:19:27 +01:00
- sender allowlists are evaluated before mention/reply activation
2026-02-11 12:31:56 -05:00
2026-02-22 12:17:44 +01:00
Note: if no `channels.whatsapp` block exists at all, runtime group-policy fallback is `allowlist` (with a warning log), even if `channels.defaults.groupPolicy` is set.
2026-02-11 12:31:56 -05:00
< / Tab >
< Tab title = "Mentions + /activation" >
Group replies require mention by default.
Mention detection includes:
- explicit WhatsApp mentions of the bot identity
- configured mention regex patterns (`agents.list[].groupChat.mentionPatterns` , fallback `messages.groupChat.mentionPatterns` )
- implicit reply-to-bot detection (reply sender matches bot identity)
2026-02-19 09:19:27 +01:00
Security note:
- quote/reply only satisfies mention gating; it does **not** grant sender authorization
- with `groupPolicy: "allowlist"` , non-allowlisted senders are still blocked even if they reply to an allowlisted user's message
2026-02-11 12:31:56 -05:00
Session-level activation command:
- `/activation mention`
- `/activation always`
`activation` updates session state (not global config). It is owner-gated.
< / Tab >
< / Tabs >
## Personal-number and self-chat behavior
When the linked self number is also present in `allowFrom` , WhatsApp self-chat safeguards activate:
- skip read receipts for self-chat turns
- ignore mention-JID auto-trigger behavior that would otherwise ping yourself
- if `messages.responsePrefix` is unset, self-chat replies default to `[{identity.name}]` or `[openclaw]`
## Message normalization and context
< AccordionGroup >
< Accordion title = "Inbound envelope + reply context" >
Incoming WhatsApp messages are wrapped in the shared inbound envelope.
If a quoted reply exists, context is appended in this form:
```text
[Replying to < sender > id:< stanzaId > ]
< quoted body or media placeholder >
[/Replying]
```
2026-01-15 06:21:05 +00:00
2026-02-11 12:31:56 -05:00
Reply metadata fields are also populated when available (`ReplyToId` , `ReplyToBody` , `ReplyToSender` , sender JID/E.164).
< / Accordion >
< Accordion title = "Media placeholders and location/contact extraction" >
Media-only inbound messages are normalized with placeholders such as:
- `<media:image>`
- `<media:video>`
- `<media:audio>`
- `<media:document>`
- `<media:sticker>`
Location and contact payloads are normalized into textual context before routing.
< / Accordion >
< Accordion title = "Pending group history injection" >
For groups, unprocessed messages can be buffered and injected as context when the bot is finally triggered.
- default limit: `50`
- config: `channels.whatsapp.historyLimit`
- fallback: `messages.groupChat.historyLimit`
- `0` disables
Injection markers:
- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
< / Accordion >
< Accordion title = "Read receipts" >
Read receipts are enabled by default for accepted inbound WhatsApp messages.
Disable globally:
```json5
{
channels: {
whatsapp: {
sendReadReceipts: false,
},
},
}
```
Per-account override:
```json5
{
channels: {
whatsapp: {
accounts: {
work: {
sendReadReceipts: false,
},
},
},
},
}
```
Self-chat turns skip read receipts even when globally enabled.
< / Accordion >
< / AccordionGroup >
## Delivery, chunking, and media
< AccordionGroup >
< Accordion title = "Text chunking" >
- default chunk limit: `channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.chunkMode = "length" | "newline"`
- `newline` mode prefers paragraph boundaries (blank lines), then falls back to length-safe chunking
< / Accordion >
< Accordion title = "Outbound media behavior" >
- supports image, video, audio (PTT voice-note), and document payloads
- `audio/ogg` is rewritten to `audio/ogg; codecs=opus` for voice-note compatibility
- animated GIF playback is supported via `gifPlayback: true` on video sends
- captions are applied to the first media item when sending multi-media reply payloads
- media source can be HTTP(S), `file://` , or local paths
< / Accordion >
< Accordion title = "Media size limits and fallback behavior" >
- inbound media save cap: `channels.whatsapp.mediaMaxMb` (default `50` )
2026-03-06 11:08:15 -05:00
- outbound media send cap: `channels.whatsapp.mediaMaxMb` (default `50` )
- per-account overrides use `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
2026-02-11 12:31:56 -05:00
- images are auto-optimized (resize/quality sweep) to fit limits
- on media send failure, first-item fallback sends text warning instead of dropping the response silently
< / Accordion >
< / AccordionGroup >
## Acknowledgment reactions
WhatsApp supports immediate ack reactions on inbound receipt via `channels.whatsapp.ackReaction` .
2026-01-31 21:13:13 +09:00
2026-01-15 06:21:05 +00:00
```json5
{
channels: {
whatsapp: {
2026-02-11 12:31:56 -05:00
ackReaction: {
emoji: "👀",
direct: true,
group: "mentions", // always | mentions | never
2026-01-31 21:13:13 +09:00
},
},
},
2026-01-15 06:21:05 +00:00
}
```
2026-02-11 12:31:56 -05:00
Behavior notes:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- sent immediately after inbound is accepted (pre-reply)
- failures are logged but do not block normal reply delivery
- group mode `mentions` reacts on mention-triggered turns; group activation `always` acts as bypass for this check
- WhatsApp uses `channels.whatsapp.ackReaction` (legacy `messages.ackReaction` is not used here)
2026-01-15 06:21:05 +00:00
2026-02-11 12:31:56 -05:00
## Multi-account and credentials
2026-01-11 23:13:35 +00:00
2026-02-11 12:31:56 -05:00
< AccordionGroup >
< Accordion title = "Account selection and defaults" >
- account ids come from `channels.whatsapp.accounts`
- default account selection: `default` if present, otherwise first configured account id (sorted)
- account ids are normalized internally for lookup
< / Accordion >
2026-01-11 23:13:35 +00:00
2026-02-11 12:31:56 -05:00
< Accordion title = "Credential paths and legacy compatibility" >
- current auth path: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- backup file: `creds.json.bak`
- legacy default auth in `~/.openclaw/credentials/` is still recognized/migrated for default-account flows
< / Accordion >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Accordion title = "Logout behavior" >
`openclaw channels logout --channel whatsapp [--account <id>]` clears WhatsApp auth state for that account.
2026-01-11 23:13:35 +00:00
2026-02-11 12:31:56 -05:00
In legacy auth directories, `oauth.json` is preserved while Baileys auth files are removed.
2026-01-12 01:25:53 +00:00
2026-02-11 12:31:56 -05:00
< / Accordion >
< / AccordionGroup >
2026-01-11 23:13:35 +00:00
2026-02-11 12:31:56 -05:00
## Tools, actions, and config writes
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
- Agent tool support includes WhatsApp reaction action (`react` ).
- Action gates:
- `channels.whatsapp.actions.reactions`
- `channels.whatsapp.actions.polls`
- Channel-initiated config writes are enabled by default (disable via `channels.whatsapp.configWrites=false` ).
2026-02-06 10:08:59 -05:00
2026-02-11 12:31:56 -05:00
## Troubleshooting
2026-02-06 10:08:59 -05:00
2026-02-11 12:31:56 -05:00
< AccordionGroup >
< Accordion title = "Not linked (QR required)" >
Symptom: channel status reports not linked.
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
Fix:
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
```bash
openclaw channels login --channel whatsapp
openclaw channels status
```
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
< / Accordion >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Accordion title = "Linked but disconnected / reconnect loop" >
Symptom: linked account with repeated disconnects or reconnect attempts.
2026-01-06 23:32:12 +00:00
2026-02-11 12:31:56 -05:00
Fix:
2026-01-10 00:54:49 +01:00
2026-02-11 12:31:56 -05:00
```bash
openclaw doctor
openclaw logs --follow
```
2026-01-10 00:54:49 +01:00
2026-02-11 12:31:56 -05:00
If needed, re-link with `channels login` .
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< / Accordion >
2026-01-10 00:54:49 +01:00
2026-02-11 12:31:56 -05:00
< Accordion title = "No active listener when sending" >
Outbound sends fail fast when no active gateway listener exists for the target account.
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
Make sure gateway is running and the account is linked.
2026-01-10 00:54:49 +01:00
2026-02-11 12:31:56 -05:00
< / Accordion >
2026-01-31 21:13:13 +09:00
2026-02-11 12:31:56 -05:00
< Accordion title = "Group messages unexpectedly ignored" >
Check in this order:
- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- `groups` allowlist entries
- mention gating (`requireMention` + mention patterns)
2026-02-19 09:19:27 +01:00
- duplicate keys in `openclaw.json` (JSON5): later entries override earlier ones, so keep a single `groupPolicy` per scope
2026-02-11 12:31:56 -05:00
< / Accordion >
< Accordion title = "Bun runtime warning" >
WhatsApp gateway runtime should use Node. Bun is flagged as incompatible for stable WhatsApp/Telegram gateway operation.
< / Accordion >
< / AccordionGroup >
2026-02-21 11:18:29 -05:00
## Configuration reference pointers
2026-02-11 12:31:56 -05:00
Primary reference:
- [Configuration reference - WhatsApp ](/gateway/configuration-reference#whatsapp )
High-signal WhatsApp fields:
- access: `dmPolicy` , `allowFrom` , `groupPolicy` , `groupAllowFrom` , `groups`
- delivery: `textChunkLimit` , `chunkMode` , `mediaMaxMb` , `sendReadReceipts` , `ackReaction`
- multi-account: `accounts.<id>.enabled` , `accounts.<id>.authDir` , account-level overrides
- operations: `configWrites` , `debounceMs` , `web.enabled` , `web.heartbeatSeconds` , `web.reconnect.*`
- session behavior: `session.dmScope` , `historyLimit` , `dmHistoryLimit` , `dms.<id>.historyLimit`
## Related
2026-01-10 00:54:49 +01:00
2026-02-11 12:31:56 -05:00
- [Pairing ](/channels/pairing )
- [Channel routing ](/channels/channel-routing )
2026-02-17 14:27:52 -06:00
- [Multi-agent routing ](/concepts/multi-agent )
2026-02-11 12:31:56 -05:00
- [Troubleshooting ](/channels/troubleshooting )