Telegram¶
Receive and send messages via a Telegram bot. Supports text, photos, documents, audio/voice, video, status-card streaming, custom slash commands, and message reactions.
1. Create a bot¶
- Open @BotFather in Telegram and send
/newbot. - Choose a display name and a username ending in
bot. - Save the bot token BotFather returns (e.g.
1234567890:ABCdefGHIjklMNOpqrsTUVwxyz).
2. Configure¶
{
"channels": {
"telegram": {
"enabled": true,
"token": "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",
"allowFrom": ["123456789"],
"streaming": true,
"feedback": "normal",
"rootDir": "",
"proxy": ""
}
}
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false |
Master toggle. |
token |
string | — | Bot token from BotFather. Must match ^\d+:[A-Za-z0-9_-]+$. |
allowFrom |
[]string | [] (all) |
Numeric user IDs allowed to message the bot. |
streaming |
bool | false |
Stream model output progressively. Private DMs use Bot API sendMessageDraft; groups/supergroups use editMessageText. |
feedback |
string | "normal" |
Inbound feedback: debug (reaction + typing + verbose card), normal (reaction + typing), minimal (typing only), silent. |
rootDir |
string | "" |
Telegram assets directory. Empty means <workspace>/.telegram. |
proxy |
string | "" |
Per-channel proxy (http://, https://, socks5://). Empty uses HTTPS_PROXY env. |
3. Find your user ID¶
Message @userinfobot on Telegram — it replies with your numeric ID. Add it to allowFrom so only you can talk to the bot.
4. Run¶
You should see:
INFO telegram authorized username=maven_bot
INFO telegram polling started
INFO telegram bot commands registered count=4
Open a chat with the bot in Telegram and send a message.
Streaming¶
When streaming: true and your LLM provider returns SSE chunks:
- Private chats use Bot API
sendMessageDraft(slot id 1) for the content message andeditMessageTextfor the status card. Drafts allow text up to ~4096 runes. - Groups / supergroups fall back to placeholder +
editMessageTextfor both becausesendMessageDraftis private-only.
The status card shows iteration counts, each tool call with a brief input summary, and streamed subprocess output for DelegateTask. On completion, the final reply is sent as a normal message and the intermediate placeholders are deleted.
If the model does not stream (provider returns one chunk at the end), you still get the streaming pipeline — just with a single delta at the end.
Slash commands¶
The Telegram channel supports three sources:
/new— built-in routing hint that rotates the session.- Workspace slashes under
<workspace>/.telegram/slashes/*.md— markdown with YAML frontmatter (see Guides: Slash commands). - Plugin slashes like
/compact,/status,/memory,/jobs— registered automatically viaSetMyCommandson gateway start (merged with workspace defs; workspace overrides description and handling when names collide). Commands with hyphens (e.g./cron-add) still work when typed but are omitted from the Telegram menu because Bot API names must match[a-z0-9_]{1,32}.
SetMyCommands registers the merged list with Telegram so users see autocomplete.
Files and media¶
Inbound media is handled differently per type:
| Type | Behavior |
|---|---|
| Photo | Downloaded; largest size attached as multimodal image block. |
| Document with image MIME | Downloaded; attached as image block. |
| Document (other) | Saved to <workspace>/uploads/<ms>_<sanitized-name>; the prompt gets [File saved to: …]. |
| Voice / Audio / Video | Saved to <workspace>/uploads/<ms>_<name>; prompt gets a […saved to:…] line. |
| Media group (album) | Buffered 500 ms then flushed as one inbound with combined caption text + image blocks. |
| Reply context | Extracted into a [Replying to <user>] block. |
| Forwarded | [Forwarded from <origin>] line; "Summarize or process" hint if there's no caption. |
| External reply / quoted | Extracted with optional photo download. |
Reactions and typing¶
PreProcessFeedback reacts to the user's message with 👀 or 👍 depending on the feedback setting and sends a chat action so users see the bot is "typing". Reactions are best-effort; failures are logged at warn.
Region restrictions / proxy¶
Set proxy per channel or HTTPS_PROXY for the whole process. Both work. See Deployment: Proxy.
Troubleshooting¶
| Symptom | Check |
|---|---|
| No reply | [telegram] authorized as @… in logs? LLM key valid? Sender in allowFrom? |
| "Sorry, I encountered an error" | Logs at error; usually LLM provider auth or model id. |
| Streaming flickers in groups | Telegram's editMessageText rate limits; the channel respects retry_after automatically. |
| 429 from Bot API | The channel parses retry-after and waits; persistent rate-limits suggest too-aggressive streaming or invalid HTML in content (the channel retries the final send as plaintext). |
| File download fails | Check workspace write permission; size limits enforced by Telegram (~50 MB). |