Telegram
Telegram integration uses the standard Bot API via a bot token you create with @BotFather. There’s no account linking — you talk to your bot, and the bot drives a Craft Agent session.
Create a Bot
Section titled “Create a Bot”Open @BotFather in Telegram
Search for @BotFather and start a chat.
Create a new bot
Send /newbot and follow the prompts. Give it a display name and a username (must end in bot, e.g. my_craft_agent_bot).
Copy the token
BotFather replies with a line like:
1234567890:ABCdefGHIjklMNOpqrsTUVwxyz-0123456789This is your bot token. Treat it like a password — anyone with it can impersonate your bot.
(Optional) Disable privacy mode for group support
If you want your bot to work in groups, send /setprivacy → choose your bot → Disable. For 1-on-1 use (the supported and recommended mode), you can skip this.
Connect in the App
Section titled “Connect in the App”Open Settings → Messaging
In Craft Agent, open Settings → Messaging. You’ll see a tile for each supported platform.
Click Connect on the Telegram tile
A dialog opens asking for the bot token.
Paste the token and click Test
Craft Agent calls Telegram’s getMe endpoint. On success you’ll see the bot’s name and username; on failure you’ll see Telegram’s error message verbatim.
Click Save
The token is persisted to your workspace keychain and the Telegram adapter starts listening.
First Conversation
Section titled “First Conversation”Open your bot in Telegram
Tap the t.me/<your_bot_username> link BotFather sent you, or search for your bot’s username.
Send /new
This creates a new session in your active workspace and binds the chat to it. You’ll get a reply like:
Created "abc123" — you're connected. Just type to start.Type anything
Your message is forwarded to the agent. Replies come back as messages in the chat according to your response mode (default: progress).
Attachments
Section titled “Attachments”Send a photo, document, voice message, video, or audio file and the gateway downloads the blob, wraps it as a FileAttachment, and forwards it to the session alongside your caption.
| Type | Forwarded as |
|---|---|
| Photo | Image attachment (original resolution) |
| Document | File attachment with original MIME type |
| Voice | Audio attachment (ogg/opus) |
| Video | Video attachment |
| Audio | Audio attachment |
Hard cap: 20 MB per attachment. Oversize files or failed downloads trigger a user-visible reply in the chat instead of being silently dropped.
Inline Buttons
Section titled “Inline Buttons”Telegram supports inline keyboard buttons, so flows like /bind render a tappable list of recent sessions instead of a numbered text list:
Recent sessions:[ Morning standup ][ Release v0.8.10 ][ Debug session ]Tap a button → bound. The gateway clears the keyboard on the posted message so stale buttons don’t pile up.
Access control
Section titled “Access control”Bots are addressable by anyone who knows the username, so by default a fresh
workspace ships with owner-only access for Telegram. Only senders on the
workspace’s allowed-users list can run pre-binding commands (/new, /bind,
/unbind, /status, /stop) or route messages to a bound session.
First-pair rule. When you redeem a pairing code from a fresh workspace,
your Telegram user_id is captured automatically and added as the first owner.
You don’t have to type any numeric ids — the bot learns them from your
/pair message.
Adding more users. When someone else messages the bot, they get a “Bot is private” reply and appear under Settings → Messaging → Pending requests with a one-click Allow button. No numeric ids needed.
Per-binding allow-list. Each session-channel binding can override the workspace policy with one of three modes:
| Mode | Meaning |
|---|---|
| Inherits workspace | Default. Falls back to the workspace allowed-users list. |
| Custom allow-list | Only the explicitly checked users can use this binding. Useful for sharing one session with a guest without giving them access to everything. |
| Open to anyone | Anyone in an accepted chat can use this binding. Use only for genuinely public bots. |
Migration. Workspaces that paired Telegram before access control existed
stay in open mode until you click Lock down in Settings → Messaging.
Existing bindings keep their current behaviour to avoid breaking traffic.
Why no group-message gating? Group/channel messages are rejected at the adapter boundary unless you’ve paired a workspace supergroup. Inside a paired supergroup, sender-level rules apply identically to DMs.
Webhook vs Long-Poll
Section titled “Webhook vs Long-Poll”- In-app (desktop Electron): the adapter uses long-poll (grammY’s built-in updater). No public URL needed.
- Headless server: the adapter uses webhook mode. You configure a public URL (e.g.,
https://your-server.tld/telegram/webhook), register it withsetWebhook, and Telegram posts updates to it. The server verifies theX-Telegram-Bot-Api-Secret-Tokenheader.
See Server → Headless for the webhook deployment path.
Troubleshooting
Section titled “Troubleshooting”Bot replies with 'No session bound to this chat'
This is expected on the first message to a fresh bot. Send /new to create and bind a session, or /pair <code> to redeem a pairing code from the app.
Test fails with '401 Unauthorized'
The bot token is wrong or was revoked in BotFather. Run /token in @BotFather to get a fresh one, or /revoke then /newbot if you want a clean slate.
Bot receives messages but nothing happens
Check that the workspace the bot is configured in is the active workspace in the app. Each workspace has its own messaging config — a bot registered under workspace A won’t drive sessions in workspace B.
Messages in a group don't work
By design — only private DMs with the bot can drive a session. Group and channel messages are rejected at the adapter boundary.
Attachment 'too large' reply
Telegram’s Bot API caps file downloads at 20 MB. Upload the file via the app’s attachment picker instead, or split it.