Pairing
Pairing — Default DM policy is pairing for unknown senders.
Status: production-ready via WhatsApp Web (Baileys). Gateway owns linked session(s).
Pairing
Pairing — Default DM policy is pairing for unknown senders.
Channel troubleshooting
Channel troubleshooting — Cross-channel diagnostics and repair playbooks.
Gateway configuration
Gateway configuration — Full channel config patterns and examples.
Configure WhatsApp access policy
{ channels: { whatsapp: { dmPolicy: "pairing", allowFrom: ["+15551234567"], groupPolicy: "allowlist", groupAllowFrom: ["+15551234567"], }, },}Link WhatsApp (QR)
remoteclaw channels login --channel whatsappFor a specific account:
remoteclaw channels login --channel whatsapp --account workStart the gateway
remoteclaw gatewayApprove first pairing request (if using pairing mode)
remoteclaw pairing list whatsappremoteclaw pairing approve whatsapp <CODE>Pairing requests expire after 1 hour. Pending requests are capped at 3 per channel.
RemoteClaw 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.)
This is the cleanest operational mode:
Minimal policy pattern:
{ channels: { whatsapp: { dmPolicy: "allowlist", allowFrom: ["+15551234567"], }, },}Onboarding supports personal-number mode and writes a self-chat-friendly baseline:
dmPolicy: "allowlist"allowFrom includes your personal numberselfChatMode: trueIn runtime, self-chat protections key off the linked self number and allowFrom.
The messaging platform channel is WhatsApp Web-based (Baileys) in current RemoteClaw channel architecture.
There is no separate Twilio WhatsApp messaging channel in the built-in chat-channel registry.
@status, @broadcast).session.dmScope; default main collapses DMs to the agent main session).agent:<agentId>:whatsapp:group:<jid>).channels.whatsapp.dmPolicy controls direct chat access:
pairing (default)allowlistopen (requires allowFrom to include "*")disabledallowFrom accepts E.164-style numbers (normalized internally).
Multi-account override: channels.whatsapp.accounts.<id>.dmPolicy (and allowFrom) take precedence over channel-level defaults for that account.
Runtime behavior details:
allowFromfromMe DMs are never auto-pairedGroup access has two layers:
Group membership allowlist (channels.whatsapp.groups)
groups is omitted, all groups are eligiblegroups is present, it acts as a group allowlist ("*" allowed)Group sender policy (channels.whatsapp.groupPolicy + groupAllowFrom)
open: sender allowlist bypassedallowlist: sender must match groupAllowFrom (or *)disabled: block all group inboundSender allowlist fallback:
groupAllowFrom is unset, runtime falls back to allowFrom when availableNote: 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.
Group replies require mention by default.
Mention detection includes:
agents.list[].groupChat.mentionPatterns, fallback messages.groupChat.mentionPatterns)Security note:
groupPolicy: "allowlist", non-allowlisted senders are still blocked even if they reply to an allowlisted user’s messageSession-level activation command:
/activation mention/activation alwaysactivation updates session state (not global config). It is owner-gated.
When the linked self number is also present in allowFrom, WhatsApp self-chat safeguards activate:
messages.responsePrefix is unset, self-chat replies default to [{identity.name}] or [remoteclaw]Incoming WhatsApp messages are wrapped in the shared inbound envelope.
If a quoted reply exists, context is appended in this form:
[Replying to <sender> id:<stanzaId>]<quoted body or media placeholder>[/Replying]Reply metadata fields are also populated when available (ReplyToId, ReplyToBody, ReplyToSender, sender JID/E.164).
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.
For groups, unprocessed messages can be buffered and injected as context when the bot is finally triggered.
50channels.whatsapp.historyLimitmessages.groupChat.historyLimit0 disablesInjection markers:
[Chat messages since your last reply - for context][Current message - respond to this]Read receipts are enabled by default for accepted inbound WhatsApp messages.
Disable globally:
{ channels: { whatsapp: { sendReadReceipts: false, }, },}Per-account override:
{ channels: { whatsapp: { accounts: { work: { sendReadReceipts: false, }, }, }, },}Self-chat turns skip read receipts even when globally enabled.
channels.whatsapp.textChunkLimit = 4000channels.whatsapp.chunkMode = "length" | "newline"newline mode prefers paragraph boundaries (blank lines), then falls back to length-safe chunkingaudio/ogg is rewritten to audio/ogg; codecs=opus for voice-note compatibilitygifPlayback: true on video sendsfile://, or local pathschannels.whatsapp.mediaMaxMb (default 50)agents.defaults.mediaMaxMb (default 5MB)WhatsApp supports immediate ack reactions on inbound receipt via channels.whatsapp.ackReaction.
{ channels: { whatsapp: { ackReaction: { emoji: "👀", direct: true, group: "mentions", // always | mentions | never }, }, },}Behavior notes:
mentions reacts on mention-triggered turns; group activation always acts as bypass for this checkchannels.whatsapp.ackReaction (legacy messages.ackReaction is not used here)channels.whatsapp.accountsdefault if present, otherwise first configured account id (sorted)~/.remoteclaw/credentials/whatsapp/<accountId>/creds.jsoncreds.json.bak~/.remoteclaw/credentials/ is still recognized/migrated for default-account flowsremoteclaw channels logout --channel whatsapp [--account <id>] clears WhatsApp auth state for that account.
In legacy auth directories, oauth.json is preserved while Baileys auth files are removed.
react).channels.whatsapp.actions.reactionschannels.whatsapp.actions.pollschannels.whatsapp.configWrites=false).Symptom: channel status reports not linked.
Fix:
remoteclaw channels login --channel whatsappremoteclaw channels statusSymptom: linked account with repeated disconnects or reconnect attempts.
Fix:
remoteclaw doctorremoteclaw logs --followIf needed, re-link with channels login.
Outbound sends fail fast when no active gateway listener exists for the target account.
Make sure gateway is running and the account is linked.
Check in this order:
groupPolicygroupAllowFrom / allowFromgroups allowlist entriesrequireMention + mention patterns)remoteclaw.json (JSON5): later entries override earlier ones, so keep a single groupPolicy per scopeWhatsApp gateway runtime should use Node. Bun is flagged as incompatible for stable WhatsApp/Telegram gateway operation.
Primary reference:
High-signal WhatsApp fields:
dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groupstextChunkLimit, chunkMode, mediaMaxMb, sendReadReceipts, ackReactionaccounts.<id>.enabled, accounts.<id>.authDir, account-level overridesconfigWrites, debounceMs, web.enabled, web.heartbeatSeconds, web.reconnect.*session.dmScope, historyLimit, dmHistoryLimit, dms.<id>.historyLimit