Skip to main content
Who this is for. You want to talk to Craft Agent from your phone, keep a conversation going while away from your desktop, or trigger the agent from a chat without opening the app.
Messaging lets you bind an external chat (a Telegram DM, a WhatsApp contact, or a Lark/Feishu chat) to a Craft Agent session. Messages you send in that chat drive the agent; the agent’s output is rendered back into the same chat.

Supported Platforms

Telegram

Bot token (via @BotFather) — works over in-process long-poll or webhook. Supports inline buttons, photos, documents, voice, and video attachments up to 20 MB.

WhatsApp

QR-code or code pairing via a Baileys-based worker subprocess. Supports text, media attachments, and a “self-chat” mode so you don’t need a second phone to test.

Lark / Feishu

App ID + App Secret pairing via Lark Open Platform (international) or Feishu Open Platform (China). Use the “Built for agents” Create button on the app-creation page to skip the scope and event-subscription setup. Long-connection mode, rich-text via Lark post, interactive cards, image/file attachments.

How It Works

1

Enable a platform in Settings

Open Settings → Messaging and configure Telegram (paste a bot token) or WhatsApp (scan a QR code). Each workspace has its own messaging config.
2

Bind a chat to a session

From the external chat, send /new to create a fresh session, /bind to pick from recent sessions, or /pair <code> to redeem a pairing code generated from the app.
3

Chat drives the agent

Once bound, everything you type is forwarded to the agent as a prompt. The agent’s reply is rendered back into the chat using your chosen response mode.

Commands

Available inside any chat — the gateway treats any message starting with / as a command.
Binding is workspace-scoped. Each messaging binding lives inside one workspace — you can bind the same chat to different sessions in different workspaces, and the gateway only accepts commands/pairing codes originating from the current workspace.

Response Modes

How the agent’s output is rendered back to the chat. Response mode is configured per binding — you can have one chat on progress and another on final_only in the same workspace.
Telegram edit interval. To stay within Telegram’s rate limits, the renderer batches edits on a ~3.5 s interval (≈ 20 edits/min). WhatsApp doesn’t support message editing, so progress mode on WhatsApp posts only the final “thinking” bubble and replaces it with the answer.

Pairing Codes

When you already have a session open in the app and want to continue it from your phone, use a pairing code instead of typing the session ID:
1

Generate a code from the session menu

In the app, open the session you want to bind, click the three-dot menu, and choose Pair to messaging…. A 6-digit code is shown.
2

Redeem it from the chat

In the external chat, send /pair 123456 (use your real code). The gateway validates the code, binds the chat, and confirms.
Security:
  • Codes expire after a short TTL.
  • The /pair command is rate-limited per sender — wrong guesses still consume the budget.
  • Codes only work inside the workspace that issued them.

Attachments

Supported on Telegram: photos, documents, voice messages, video, and audio. Files are downloaded to a temp location and forwarded to the session as FileAttachment objects — the same way uploads from the app are handled. Hard cap: 20 MB per attachment. WhatsApp attachment forwarding follows the same pattern; platform-specific limits and MIME handling are documented in the WhatsApp page.

Approval Channel

When the bound session is in Ask permission mode, the agent asks for approval before running a bash command. The approvalChannel per binding decides where that prompt appears: The session’s own permission mode is still authoritative — approvalChannel only controls where the prompt is shown, not whether it happens.

Plan Submission

When the agent submits a plan in Explore mode, Telegram bindings get inline ✅ Accept plan / ♻️ Accept & compact buttons (plus the plan content inline or as a plan.md attachment). WhatsApp bindings get a text pointer telling you to open the desktop app — plans can’t be accepted from WhatsApp yet. See WhatsApp → Plan Submission for the reasons.

Security & Scope

  • Per-workspace. Each workspace has its own messaging config, bindings, and pairing codes. Binding in workspace A never accepts codes issued by workspace B.
  • Plan-token revocation. Plan tokens (used for bash-approval flows) are keyed by binding — rebinding a chat invalidates outstanding tokens for the old binding.
  • Rate limiting. /pair is throttled per sender. Inbound messages are routed through a per-binding queue so spam doesn’t back-pressure other bindings.
  • No group/channel chats. Telegram group and channel messages are rejected at the adapter boundary — only private DMs can drive a session.

Configuration Location

Messaging config is persisted per workspace:
Edits to bindings.json take effect on the next inbound message. Deleting whatsapp-session/ forces a re-pair.

Headless Server

The gateway also runs inside the standalone headless Bun server (packages/server). Telegram uses webhook mode on the server (you configure a webhook URL), while WhatsApp still runs its Baileys worker subprocess. See Server for deployment details.