Messaging
Drive Fabric Agents sessions from Telegram and WhatsApp — inbound chat messages run the agent, agent replies stream back into the chat.
Messaging bridges an external chat (Telegram DM or WhatsApp contact) to a Fabric Agents session. When the bridged contact sends a message, the agent runs. When the agent replies, the response lands back in the chat. Sessions show up in the desktop UI exactly as if you'd driven them locally — the two are live-linked.
Typical uses:
- Phone-away control — trigger a long-running task from the road; the agent keeps working on your workstation or remote server.
- Push notifications that talk back — the agent summarises a PR review, you reply "merge it", the next turn runs.
- Teammates driving your setup — share access to a single session with a collaborator over WhatsApp without them needing the desktop app.
Platforms
| Platform | Auth | Where it runs | Notes |
|---|---|---|---|
| Telegram | Bot token from @BotFather | Directly in-process | Official Bot API. Photo / document / voice / video / audio attachments up to 20 MB. |
| QR pairing (scan from your phone) | Separate Node subprocess, built on Baileys | Unofficial Web API. Self-chat (DM yourself) is the recommended testing channel. |
Both platforms support the same command set — /new, /bind, /pair, /status, /stop, /unbind, /help — and the same three response modes (see below).
Response modes
Each binding picks how agent output lands in the chat. Default is progress.
| Mode | Behaviour |
|---|---|
| progress (default) | One evolving bubble per run. Starts as 💭 thinking…, edits to 🔧 <tool>… while tools run, then replaces itself with the final text on completion. Intermediate assistant text is dropped. |
| streaming | Live edits as tokens arrive. Each text_complete finalises a message, so one agent run with multiple turns produces multiple messages. On platforms without message-editing (WhatsApp), degrades to one message per turn at text_complete. |
| final_only | Silent until the agent finishes, then one message with the full final text. |
Change the mode per-binding from Settings → Messaging → ⋯ menu on the binding row → Response mode.
Where bindings live
Every binding is workspace-scoped. A single session can only be bound to one chat per platform at a time; a single chat can only drive one session at a time.
Bindings and platform credentials persist at:
~/.fabric-agent/workspaces/{workspace-id}/messaging/
├── bindings.json
├── config.json # per-platform config (responseMode, selfChatMode, …)
├── whatsapp-auth/ # Baileys session state (QR-login keys)
└── telegram/ # Telegram token (encrypted via OS keychain)If you wipe whatsapp-auth/, the next connect will trigger a fresh QR scan.
Headless / remote server
The same messaging stack runs inside the headless server (packages/server/src/index.ts) when you point the desktop app at a remote workspace. The WhatsApp worker is spawned as a Node subprocess by the server; paths are controlled with:
| Env var | Default | What it does |
|---|---|---|
FABRIC_MESSAGING_WA_WORKER | $FABRIC_BUNDLED_ASSETS_ROOT/packages/messaging-whatsapp-worker/dist/worker.cjs | Absolute path to the worker bundle |
FABRIC_MESSAGING_NODE_BIN | node | Node binary used to spawn the worker (Bun can't run the Baileys worker directly) |
The Docker image (ghcr.io/fabric-pro/fabric-agents-server) ships both. See Workspaces — remote workspaces for the remote setup flow.
Related
- Telegram setup — create a bot, paste the token, drive your first session
- WhatsApp setup — QR pair your phone, test with self-chat
- Command reference — every slash command you can send from a chat
- Workspaces — messaging is workspace-scoped; each workspace has its own bindings