On this page
On this page
Configuration
WhatsApp group messages
For the cross-channel groups model (Discord, iMessage, Matrix, Microsoft Teams, QQBot, Signal, Slack, Telegram, WhatsApp, Zalo), see Groups. This page covers the WhatsApp-specific behavior on top of that model: activation, group allowlists, per-group session keys, and pending-message context injection.
Goal: let OpenClaw sit in WhatsApp groups, wake up only when pinged, and keep that thread separate from the personal DM session.
Behavior
- Activation modes:
mention(default) oralways.mentionrequires a ping: a real WhatsApp @-mention (mentionedJids), a configured regex pattern, a delimited@<number>or@+<number>token containing the bot's full phone-number digits, or a quoted reply to one of the bot's messages (except shared-number self-chat setups).alwayswakes the agent on every admitted message and requires a reply by default. To permit selective silence for unaddressed messages, explicitly setsurfaces.whatsapp.silentReply.group: "allow". An entire final that trims to uppercaseNO_REPLYrequests silence; lowercase and wrapped forms remain visible. See Silent replies for the global setting and precedence. Activation defaults come from config (channels.whatsapp.groupsrequireMention) and can be overridden per group via/activation. - Group allowlist: when
channels.whatsapp.groupsis set, only listed group JIDs are admitted (include"*"to allow all); messages from unlisted groups are dropped with a log hint. - Group policy:
channels.whatsapp.groupPolicycontrols whether group messages are accepted (open|disabled|allowlist).allowlistuseschannels.whatsapp.groupAllowFrom(fallback: explicitchannels.whatsapp.allowFrom). Default isallowlist(blocked until you add senders). - Per-group sessions: session keys look like
agent:<agentId>:whatsapp:group:<jid>(non-default accounts append:thread:whatsapp-account-<accountId>), so directives such as/verbose on,/trace on, or/think high(sent as standalone messages) are scoped to that group; personal DM state is untouched. - Context injection: pending-only group messages (default 50) that did not trigger a run are prefixed under
[Chat messages since your last reply - for context], with the triggering line under[Current message - respond to this]. The pending window is cleared after the run; messages already in the session are not re-injected. - Sender attribution: each group line carries the sender label inside the message envelope, e.g.
[WhatsApp <groupJid> <timestamp>] Alice (+447700900123): text, and sender identity plus group subject/members ride along in the untrusted conversation-metadata block. - Ephemeral/view-once: wrappers are unwrapped before extracting text/mentions, so pings inside them still trigger.
- Group system prompt: the first turn of a group session (and any turn after
/activationchanges the mode) injects activation guidance into the system prompt (Activation: trigger-only ...orActivation: always-on ..., plus "address the specific sender"). Persistent group-chat delivery guidance ("You are in a WhatsApp group chat...") is always included.
Config example (WhatsApp)
Make display-name pings work even when WhatsApp strips the visual @ from the text body:
Notes:
- The regexes are case-insensitive and use the same safe-regex guardrails as other config regex surfaces; invalid patterns and unsafe nested repetition are ignored.
- WhatsApp still sends explicit mentions via
mentionedJidswhen someone taps the contact, so the text fallback is rarely needed. Bare phone numbers, longer numbers, email addresses, and digits scattered across the message do not trigger it; configured mention patterns still apply. - The pending-context window resolves as
channels.whatsapp.accounts.<id>.historyLimit→channels.whatsapp.historyLimit→messages.groupChat.historyLimit→ 50.
Activation command (owner-only)
Use the group chat command:
/activation mention/activation always
Only owner numbers (from channels.whatsapp.allowFrom, or the bot's own E.164 when unset) can change this; /activation from anyone else is ignored and stored as context only. Send /status as a standalone message in the group to see the current activation mode.
How to use
- Add your WhatsApp account (the one running OpenClaw) to the group.
- Mention the bot through WhatsApp, say
@openclaw ...when configured, or use@15555550123with the bot's number. Only allowlisted senders can trigger it unless you setgroupPolicy: "open". - The agent prompt includes the pending group context plus sender-labeled lines so it can address the right person.
- Session directives (
/verbose on,/trace on,/think high,/newor/reset,/compact) apply only to that group's session; send them as standalone messages so they register. Your personal DM session stays independent.
Testing / verification
- Manual smoke:
- Send an
@openclawping in the group and confirm a reply that references the sender name. - Send a second ping and verify the history block is included, then cleared on the next turn.
- Send an
- Check gateway logs (run with
--verbose) forinbound web messageentries showingfrom: <groupJid>and the sender-labeled body.
Known considerations
- Heartbeats run in the agent's main session; group sessions never get heartbeat runs.
- Echo suppression remembers the combined prompt (history + current message) per session so the bot's own delivered messages do not retrigger it; an identical repeated batch can be skipped as an echo.
- Session store entries appear as
agent:<agentId>:whatsapp:group:<jid>in the per-agent SQLite session store; a missing entry just means the group has not triggered a run yet. - Typing indicators follow
agents.entries.*.typingMode/agents.defaults.typingMode. When visible replies are opted into message-tool-only mode, typing starts immediately by default so group members can see the agent working even if no automatic final reply is posted. Explicit typing-mode config still wins.