WhatsApp (Web channel)
Status: production-ready via WhatsApp Web (Baileys). Gateway owns linked session(s).Quick setup
Deployment patterns
Dedicated number (recommended)
This is the cleanest operational mode:- separate WhatsApp identity for Datzi
- clearer DM allowlists and routing boundaries
- lower chance of self-chat confusion
Personal-number fallback
Onboarding supports personal-number mode and writes a self-chat-friendly baseline:dmPolicy: "allowlist"allowFromincludes your personal numberselfChatMode: true
allowFrom.
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).
Group access has two layers:
-
Group membership allowlist (
channels.whatsapp.groups)- if
groupsis omitted, all groups are eligible - if
groupsis present, it acts as a group allowlist ("*"allowed)
- if
-
Group sender policy (
channels.whatsapp.groupPolicy+groupAllowFrom)open: sender allowlist bypassedallowlist: sender must matchgroupAllowFrom(or*)disabled: block all group inbound
- explicit WhatsApp mentions of the bot identity
- configured mention regex patterns (
agents.list[].groupChat.mentionPatterns, fallbackmessages.groupChat.mentionPatterns) - implicit reply-to-bot detection
/activation mention/activation always
Personal-number and self-chat behavior
When the linked self number is also present inallowFrom, 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[datzi]
Message normalization and context
Incoming WhatsApp messages are wrapped in the shared inbound envelope. If a quoted reply exists, context is appended:<media:image><media:video><media:audio><media:document><media:sticker>
- default limit:
50 - config:
channels.whatsapp.historyLimit
[Chat messages since your last reply - for context][Current message - respond to this]
Delivery, chunking, and media
- default chunk limit:
channels.whatsapp.textChunkLimit = 4000 channels.whatsapp.chunkMode = "length" | "newline"newlinemode prefers paragraph boundaries (blank lines), then falls back to length-safe chunking- supports image, video, audio (PTT voice-note), and document payloads
- inbound media save cap:
channels.whatsapp.mediaMaxMb(default50) - outbound media cap for auto-replies:
agents.defaults.mediaMaxMb(default5MB) - images are auto-optimized (resize/quality sweep) to fit limits
Acknowledgment reactions
WhatsApp supports immediate ack reactions on inbound receipt viachannels.whatsapp.ackReaction.
- 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
Multi-account and credentials
- account ids come from
channels.whatsapp.accounts - default account selection:
defaultif present, otherwise first configured account id (sorted) - current auth path:
~/.datzi/credentials/whatsapp/<accountId>/creds.json
datzi channels logout --channel whatsapp [--account <id>] clears WhatsApp auth state for that account.
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
- Not linked (QR required): run
datzi channels login --channel whatsapp. - Linked but disconnected / reconnect loop: run
datzi doctoranddatzi logs --follow. If needed, re-link. - No active listener when sending: make sure gateway is running and the account is linked.
- Group messages unexpectedly ignored: check in order:
groupPolicy,groupAllowFrom/allowFrom,groupsallowlist, mention gating, duplicate keys indatzi.json. - Bun runtime warning: WhatsApp gateway runtime should use Node. Bun is flagged as incompatible.
Configuration reference pointers
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
