WhatsApp (Web channel)
Status: production-ready via WhatsApp Web (Baileys). Gateway owns linked session(s).
Pairing
Default DM policy is pairing for unknown senders.
Channel troubleshooting
Cross-channel diagnostics and repair playbooks.
Gateway configuration
Full channel config patterns and examples.
Quick setup
Configure WhatsApp access policy
json5{ channels: { whatsapp: { dmPolicy: "pairing", allowFrom: ["+15551234567"], groupPolicy: "allowlist", groupAllowFrom: ["+15551234567"], }, }, }
Link WhatsApp (QR)
bashmayros channels login --channel whatsapp
For a specific account:
bashmayros channels login --channel whatsapp --account work
Start the gateway
bashmayros gateway
Approve first pairing request (if using pairing mode)
bashmayros pairing list whatsapp mayros pairing approve whatsapp <CODE>
Pairing requests expire after 1 hour. Pending requests are capped at 3 per channel.
Mayros 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.)
Deployment patterns
Runtime model
- 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; defaultmaincollapses DMs to the agent main session). - Group sessions are isolated (
agent:<agentId>:whatsapp:group:<jid>).
Access control and activation
channels.whatsapp.dmPolicy controls direct chat access:
pairing(default)allowlistopen(requiresallowFromto include"*")disabled
allowFrom 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:
- 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
fromMeDMs are never auto-paired
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.responsePrefixis unset, self-chat replies default to[{identity.name}]or[mayros]
Message normalization and context
Delivery, chunking, and media
Acknowledgment reactions
WhatsApp supports immediate ack reactions on inbound receipt via channels.whatsapp.ackReaction.
json5{ channels: { whatsapp: { ackReaction: { emoji: "👀", direct: true, group: "mentions", // always | mentions | never }, }, }, }
Behavior notes:
- sent immediately after inbound is accepted (pre-reply)
- failures are logged but do not block normal reply delivery
- group mode
mentionsreacts on mention-triggered turns; group activationalwaysacts as bypass for this check - WhatsApp uses
channels.whatsapp.ackReaction(legacymessages.ackReactionis not used here)
Multi-account and credentials
Tools, actions, and config writes
- Agent tool support includes WhatsApp reaction action (
react). - Action gates:
channels.whatsapp.actions.reactionschannels.whatsapp.actions.polls
- Channel-initiated config writes are enabled by default (disable via
channels.whatsapp.configWrites=false).
Troubleshooting
Configuration reference pointers
Primary reference:
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