Skip to main content
The WhatsApp adapter connects NanoClaw to a personal WhatsApp account as a linked device — no Meta business account, no API key. It’s a native adapter built directly on @whiskeysockets/baileys 7.0.0-rc.9 (pinned; the WhatsApp Web protocol), not the Chat SDK bridge. For Meta’s official Cloud API instead, use /add-whatsapp-cloud — see the channels overview. You can run it in two modes:
  • Shared number — the agent lives on your own WhatsApp account. Its replies are prefixed with the agent name (Andy: …) so they’re distinguishable from yours.
  • Dedicated number — a separate phone/SIM for the agent. Setting ASSISTANT_HAS_OWN_NUMBER=true drops the name prefix on outbound messages and switches bot-echo detection from prefix matching to sender identity.

Prerequisites

  • A phone with WhatsApp installed and online — you’ll link NanoClaw under Settings → Linked Devices
  • A working NanoClaw install (quickstart)
  • For pairing-code auth: the account’s phone number, digits only with country code (e.g. 14155551234)

Install

WhatsApp is offered in the first-run setup wizard, or add it later by running /add-whatsapp in Claude Code. Both flows do the same thing:
1

Pick an auth method

QR code (scan with your phone’s camera) or pairing code (enter an 8-character code on your phone — no camera needed). The pairing-code flow asks for your phone number first.
2

Adapter install

The skill copies src/channels/whatsapp.ts from the channels branch, wires it into the channel barrel, and installs the pinned Baileys, qrcode, and pino packages.
3

Link your phone

A QR code renders (terminal, or a local browser page via the skill) and rotates every ~60 seconds until scanned. Pairing codes also expire in ~60 seconds — enter them immediately under Linked Devices → Link a Device → Link with phone number instead. Credentials land in store/auth/, and the wizard restarts the service so the adapter picks them up.
4

Choose your mode

The wizard asks which number you’ll chat from. Same number as the one you linked = shared mode, and messages land in your “You” self-chat. A different number = dedicated mode — the wizard writes ASSISTANT_HAS_OWN_NUMBER=true to .env (and data/env/env for containers).
5

Name the agent and get the welcome DM

The wizard asks for an agent name (default Nano), wires your DM to the first agent group, and sends a welcome message.
To wire more chats or groups later, run /manage-channels.

Platform notes

  • Auth persistence — credentials live in store/auth/ (multi-file auth state). Restarts reuse the saved session; you only re-pair if WhatsApp logs the device out. On a server-side logout the adapter wipes store/auth/ so the next start prompts a fresh pair.
  • Activation — the adapter only starts when store/auth/creds.json exists, WHATSAPP_PHONE_NUMBER is set (pairing-code mode), or WHATSAPP_ENABLED=true (QR mode). Otherwise it’s skipped at startup.
  • Reconnection — on disconnect the adapter reconnects immediately (with one retry after 5s if that attempt throws) unless it was logged out. Messages sent while disconnected are queued in memory and flushed when the connection reopens.
  • No threads — the adapter sets supportsThreads: false; every inbound message has a null thread ID. Wirings with per-thread session mode behave like shared here — see the entity model.
  • DMs vs groups — DMs always count as addressed to the agent. In groups (…@g.us JIDs) the agent is by default only triggered by an explicit @-mention of the bot’s number, which the adapter also normalizes to @<agent name> for trigger matching. Group names sync from WhatsApp every 24 hours.
  • Media — inbound images, video, audio, and documents are downloaded to data/attachments/ and passed to the agent (unsafe attacker-controlled filenames are replaced). Outbound files are sent as native WhatsApp media by extension, with the reply text as the first file’s caption.
  • Formatting — the agent’s markdown is converted to WhatsApp formatting (**bold***bold*, headings → bold, links → text (url)); code blocks pass through untouched. @<phone> in replies becomes a real tappable mention.
  • Interactive questionsask_user_question renders as text with slash-command answers (/approve, /reject); the adapter matches your reply to the pending question. Editing and deleting sent messages isn’t supported (linked-device limitation).
  • Self-chat — in shared mode you can message the agent in your own “You” chat. The adapter tells your typed messages apart from its own echoes via a sent-message cache.

Troubleshooting

  • Logged out / re-pair loop — if logs show WhatsApp logged out followed by WhatsApp auth cleared, the account was unlinked server-side (often a 401). The adapter already wiped store/auth/; set WHATSAPP_ENABLED=true and restart (or re-run /add-whatsapp) to scan a fresh QR.
  • Could not fetch current WhatsApp Web version — Baileys’ hardcoded protocol version goes stale and WhatsApp rejects it (405), so the adapter fetches the current version at startup from wppconnect.io with web.whatsapp.com as fallback. This error means both fetches failed: check outbound network access to those hosts.
  • Agent silent, messages arrive late in a burst — the connection dropped; outbound messages were queued (WA disconnected, message queued in logs) and flushed on reconnect. Confirm the last Connected to WhatsApp log line and that only one NanoClaw process holds these credentials — a second instance causes “conflict” disconnect loops.
  • QR or pairing code expired — both rotate/expire in ~60 seconds. Re-run the auth step for a fresh code; for pairing codes, the number must be digits only with country code, no +. If pairing codes keep getting rejected, switch to the QR method — it’s more reliable.
For service-level checks (logs, restarts, wiring queries), see troubleshooting.
Last modified on June 10, 2026