WhatsApp channel — developer reference
This page covers what plugin authors need to know when writing plugins that interact with thewhatsapp channel: channel identifier, hook filtering patterns, available message actions, and channel-specific behavior to account for in plugin code.
For building a new channel adapter from scratch, see Channel adapters. For the admin configuration reference, see Admin: WhatsApp.
Channel identifier
The WhatsApp channel registers under the id"whatsapp". Use this when filtering hooks by channel:
ctx.channelId is always "whatsapp" for messages, hooks, and tool calls that originate from the WhatsApp channel.
Available hooks (WhatsApp-relevant)
All standard plugin hooks fire for WhatsApp events. The most commonly used for channel-specific behavior:Filtering to a specific account
WhatsApp supports multiple linked accounts. Filter by account usingctx.accountId:
Message actions
WhatsApp supports the following message actions from agent tools or automation:
Gating:
channels.whatsapp.actions.reactions and channels.whatsapp.actions.polls must be true for those actions to be available.
Using message actions in a plugin tool
Direct message action dispatch from plugin tools is handled through the agent’s
response pipeline. Return structured action payloads from your tool and let the
channel adapter handle delivery.
Session keys
WhatsApp session keys follow these patterns:
Use
ctx.sessionKey in hook handlers — do not construct session keys manually.
Channel-specific behaviors to handle in plugins
Baileys dependency is lazy-loaded. Thewhatsapp bundled extension loads @whiskeysockets/baileys lazily at channel-activation time, not at gateway startup. Plugins that interact with the WhatsApp channel must not assume the Baileys library is available as a direct import — use only the openclaw/plugin-sdk surface.
Self-chat. When the linked number is in allowFrom, self-chat safeguards are active: read receipts are skipped and the agent does not trigger on its own outbound messages. Hooks on message_received will not fire for self-sent messages.
Socket lock. Only one Baileys socket can own an account’s credentials directory at a time (enforced by a .socket-owner.lock file). If a plugin attempts gateway-level WhatsApp operations, it must not open a second Baileys connection against the same credentials directory.
Media placeholders. Inbound media-only messages arrive normalized: <media:image>, <media:video>, <media:audio>, <media:document>, <media:sticker>. The raw Baileys message payload is not passed to hooks.
Status and broadcast chats are ignored. Messages from @status and @broadcast JIDs are dropped before routing. Hooks will not fire for these.
Async safety
Plugin tools and hook handlers run in the same Node.js event loop as the gateway. Do not use synchronous blocking I/O in toolexecute() functions or hook handlers.
Related
- Channel adapters — building a new channel from scratch
- Hooks — full hook reference
- Agent tools — registering plugin tools
- Admin: WhatsApp — configuration reference