WhatsApp as a data source and action surface — the agent reads and sends messages and downloads media as a capability. It connects through the WhatsApp Web linked-device protocol, not a chat the agent talks over.
What the agent can do
- Orient → read → act — list recent chats with previews and unread counts, look up a conversation by name or number, then read, send, or download.
- Media — messages show a placeholder with an id; the agent downloads media to staging, and sends media by writing to staging first.
- Persistent history — messages stream into a local store and survive restarts; WhatsApp delivers the historical backfill once, at pairing.
Pairing your phone
Pairing happens in the admin dashboard, on this agent's WhatsApp extension page — there are no credentials to paste. The agent links to your account as a device, the same way WhatsApp Web does, and the session is stored under ext/whatsapp/auth/. Under Pairing Status on that page:
- Optionally choose how much history to sync — Standard (~3 months) or Extended (~1 year). It only takes effect at pairing.
- Enter your phone number with country code (e.g.
+1 415 555 0142) and click Pair Device. - A 6-digit code appears. On your phone, open WhatsApp → Settings → Linked Devices → Link a Device → Link with phone number, and enter it.
- The page polls for up to two minutes and flips to Paired once linked, syncing recent history into a local store.
Once paired, the same page shows the linked status and synced-chat count, with an Unpair button to clear the session.
Configuration
capabilities.json
{
"extensions": {
"whatsapp": {
"enabled": true,
"read_mode": "approval",
"send_mode": "disabled"
}
}
}| Field | Type | Default | Effect |
|---|---|---|---|
| read_mode | disabled | approval | open | approval | Default policy for reading chats, messages, and media. |
| send_mode | disabled | approval | direct | disabled | Default policy for sending. direct sends without prompting. |
| chats | Record<jid, overrides> | {} | Per-chat overrides — allow or deny read and send independently for a specific contact. |
pairing_history_depth (standard or extended) sets how much history WhatsApp delivers, and applies only at pairing time — changing it means unpairing and pairing again.
Tools
whatsapp__chats(limit?)
List recent WhatsApp chats with names, last-message previews, unread counts, and group status.
Parameters
- optional
limit[integer 1–50, default 20]Max chats to return.
Returns
CHAT_NAME (group) [N unread] CHAT_NAME …
No chats yet.
Reading is disabled.
whatsapp__messages(chat, count?, query?)
Read messages from a WhatsApp chat by contact name, phone number, or JID. Optionally filter by keyword.
Parameters
chat[string]Chat identifier — name, phone number, or JID.- optional
count[integer 1–100, default 20]Number of messages to return. - optional
query[string]Keyword to filter messages — returns only those containing this text.
Returns
[YYYY-MM-DD HH:MM] SENDER: TEXT (ID: MESSAGE_ID)
[YYYY-MM-DD HH:MM] SENDER: [image|video|voice note|audio|document: FILENAME|sticker] [optional CAPTION] (ID: MESSAGE_ID)
No messages available for this chat yet.
No messages matching "QUERY" in this chat.
Multiple chats match "QUERY". Please specify: CHAT_NAME — JID (group) …
No chat found matching "QUERY".
Access to this chat is restricted.
WhatsApp not paired. Link a device in the admin panel first.
WhatsApp not ready — connection timeout. Try again in a moment.
whatsapp__download(message_id, chat)
Download media from a WhatsApp message to /staging/in/ for inspection with the Read tool.
Parameters
message_id[string]Message ID from whatsapp__messages output.chat[string]Chat identifier (name, phone, or JID) containing the message.
Returns
Downloaded to /staging/in/FILENAME. Use the Read tool to view it.
Message not found or no longer in buffer.
Media download failed — the file may have expired. ERROR
Access to this chat is restricted.
WhatsApp not paired. Link a device in the admin panel first.
whatsapp__send(chat, text?, file?)
Send a text or media message to a WhatsApp chat. Media is read from /staging/out/ with an optional caption.
Parameters
chat[string]Chat identifier (name, phone, or JID).- optional
text[string]Message text. Required for text-only sends; used as caption when file is set. - optional
file[string]Filename in /staging/out/ to send as media.
Returns
Message sent.
Provide at least text or file to send.
File not found: /staging/out/FILENAME
No routable address for this contact.
Sending to this chat is disabled.
Send failed: ERROR
WhatsApp not connected.
WhatsApp not paired. Link a device in the admin panel first.
whatsapp__watch(chat, instructions, id?)
Monitor a WhatsApp chat for new messages. Each new message is forwarded to the agent's channel with the configured instructions.
Parameters
chat[string]Chat identifier (name, phone, or JID).instructions[string]Instructions delivered with each forwarded batch.- optional
id[string]Custom watch ID. Auto-generated as watch_<random> if omitted.
Returns
Watch "ID" created for CHAT_NAME. New messages will be forwarded with your instructions.
Instructions are required.
Multiple chats match "QUERY". Please specify: CHAT_NAME — JID (group) …
No chat found matching "QUERY".
Access to this chat is restricted.
Watches require a participant context.
WhatsApp not paired.
Caveats
Delivery format: each fired batch arrives as a turn in the agent's channel — New WhatsApp messages in "CHAT_NAME": [YYYY-MM-DD HH:MM] SENDER: TEXT [YYYY-MM-DD HH:MM] SENDER: [media placeholder] CAPTION … Watch instructions: INSTRUCTIONS
whatsapp__unwatch(id)
Remove an active WhatsApp watch by ID.
Parameters
id[string]Watch ID to remove. List with whatsapp__list_watches.
Returns
Watch "ID" removed.
Watch "ID" not found.
whatsapp__list_watches()
List all active WhatsApp watches with their chat, instructions, and creation timestamps.
Returns
ID: ID Chat: CHAT_NAME Instructions: INSTRUCTIONS Created: ISO_TIMESTAMP
No active watches.
Watches
With a dedicated channel, the agent can watch a chat in real time and have new messages forwarded to that channel with standing instructions, so it reacts as they arrive. Without a channel, the watch tools are hidden and the on-demand tools still work.
Notes & gotchas
send_mode: direct lets the agent message contacts autonomously, as you — recipients see it from your number. Prefer approval (or disabled) and grant direct only to trusted chats via the per-chat overrides.