FabricFabric
Messaging

WhatsApp

Connect WhatsApp to Fabric Agents — scan a QR code with your phone, then drive sessions by messaging yourself or routing a contact via /pair.

WhatsApp uses an unofficial Web API (Baileys). You pair your account by scanning a QR code — same flow as WhatsApp Web — and then drive sessions by messaging yourself ("self-chat"). That avoids the need for a separate bot number.

Unofficial Web API

Baileys emulates a WhatsApp Web client. It works well, but WhatsApp can throttle or suspend numbers they detect as automated. Use a personal account you don't mind risking, and don't spam. Meta's terms of service only formally cover the Business Cloud API, which isn't what this is.

Prerequisites

  • A phone with WhatsApp installed and signed in.
  • Node.js installed on the machine running the server (for packaged desktop builds this is handled automatically; for headless server builds, see the env vars below).

1. Connect WhatsApp in Fabric Agents

  1. Open Fabric Agents → Settings → Messaging.
  2. Click Connect on the WhatsApp row.
  3. A dialog opens showing a QR code.
  4. On your phone, open WhatsApp → Settings → Linked Devices → Link a Device.
  5. Point your phone at the QR code.
  6. The dialog switches to "Connected as <your name>". Done.

Your Baileys session state is saved at ~/.fabric-agent/workspaces/{workspace-id}/messaging/whatsapp-auth/. Subsequent launches reconnect automatically — you only scan once.

First connection sometimes shows your number instead of your name

Immediately after scanning, the linked-device record hasn't fully propagated yet. If the status card shows just your phone number, click Reconfigure → Reconnect once and it'll resolve to your name. This also populates the self-chat identifier that WhatsApp uses for privacy- preserving chats — self-chat messages won't be recognised until it's set.

2. Test with self-chat

The easiest way to test — and the default driving surface — is messaging yourself. On WhatsApp Desktop or your phone:

  1. Open your own chat (the "You" chat, or type your own name in the search box).

  2. Send:

    /help
  3. A 🤖-prefixed reply should arrive listing the available commands. That confirms the full round-trip: your phone → WhatsApp servers → Baileys worker → session manager → renderer → back out.

  4. Create a session:

    /new quick test

    A new session appears in your workspace sidebar. Every subsequent message you send to yourself drives that agent; replies come back in the same chat.

The 🤖 prefix on bot replies lets you visually distinguish them from your own messages in the self-chat. You can turn self-chat off in Settings → Messaging → ⋯ on the WhatsApp row → Self-chat if you only want other contacts driving sessions.

3. Drive a session from another contact

To let someone else drive a specific session:

  1. In the Fabric Agents app, open the session you want to share → session menu (⋯) → Pair over WhatsApp. A 6-digit code appears and is valid for ~5 minutes.

  2. On the other person's phone, they message your WhatsApp number with:

    /pair 123456
  3. Their chat is now bound to that session. Their subsequent messages drive the agent; replies come back to them.

Codes are single-use and rate-limited per sender (a handful of attempts per minute) to prevent brute force.

4. Attachments

WhatsApp supports sending files to the agent. The bot accepts:

TypeMax sizeDelivered to the agent as
Photo20 MBImage attachment on the next turn
Document20 MBFile attachment (raw bytes + filename)
Voice note20 MBAudio file
Video20 MBVideo file
Audio20 MBAudio file

Caption text sent with a media message becomes the user's text for that turn.

5. Response modes

Default is progress — one evolving message per run. WhatsApp does support message editing (recent versions of the protocol), so streaming mode does live-edit a single message as tokens arrive.

Change the mode per-binding from Settings → Messaging → ⋯ on the binding row → Response mode.

See Messaging overview — response modes.

Headless server

When Fabric Agents runs as a headless server (packages/server/src/index.ts), the WhatsApp worker is spawned as a Node subprocess. Bun can't run Baileys' crypto dependencies directly, so a real Node binary must be reachable.

Env varDefaultNotes
FABRIC_MESSAGING_WA_WORKER$FABRIC_BUNDLED_ASSETS_ROOT/packages/messaging-whatsapp-worker/dist/worker.cjsAbsolute path to the built worker bundle. The worker is CJS + Node target.
FABRIC_MESSAGING_NODE_BINnodeCommand used to spawn the worker. Override if Node isn't on PATH under a non-default name.

The Docker image (ghcr.io/fabric-pro/fabric-agents-server) installs Node 20 alongside Bun and ships the worker bundle at the default path, so out-of-box it just works.

Reconnect or disconnect

  • ReconnectSettings → Messaging → ⋯ on WhatsApp row → Reconnect. Reloads the persisted session, usually without a re-scan.
  • Reconfigure — same menu → Reconfigure. Forces a fresh QR scan (e.g. if you switched phones).
  • Disconnect — same menu → Disconnect. Logs out on the WhatsApp side and clears local auth state. Next connect is a fresh QR scan.

Troubleshooting

Nothing happens when I send a message — check the messaging log at ~/.fabric-agent/logs/messaging-gateway.log. If you see upsert skip: own_outbound, WhatsApp is routing your self-chat messages under your LID (a newer privacy-preserving identity) and Baileys hasn't learnt your self-LID yet. Reconfigure → Reconnect populates it.

Worker exited with code 1 / "Cannot find module worker.cjs" — the WhatsApp worker bundle wasn't built. For dev builds run bun run build:wa-worker once; for packaged apps this is part of bun run electron:build.

QR scan gets stuck / disconnects with statusCode=515 — WhatsApp sometimes forces a reconnect right after the first pair. The worker retries automatically within a second or two; the status card transitions from "QR received" to "connected" when it settles.

/help doesn't respond — the bot might be connected but the self-chat check is failing. Check ~/.fabric-agent/logs/messaging-gateway.log for lines like upsert skip: own_outbound remoteJid=...@lid selfLid=?. If selfLid is ?, reconnect once — the self-LID populates on the second session.

I want to force a fresh pair — delete ~/.fabric-agent/workspaces/{workspace-id}/messaging/whatsapp-auth/ and reconnect.

On this page