Telegram channel
This page shows how to operate the builtin Telegram channel: which environment variables it reads, how it names sessions, and how it debounces inbound messages.
The Telegram channel is registered under the name telegram. It uses long polling via python-telegram-bot, and it is enabled at runtime when BUB_TELEGRAM_TOKEN is set.
Before you begin
Section titled “Before you begin”- A bot exists in @BotFather and you have its token.
- For group chats, Privacy Mode is disabled in BotFather. Otherwise the bot only sees commands, and the inbound filter cannot decide whether to respond.
- Bub is configured with a working model — see Configure.
1. Set the token
Section titled “1. Set the token”BUB_TELEGRAM_TOKEN=123456:abcdef...
This single variable is the on/off switch. With it unset, the channel reports enabled=False and bub gateway skips it without error.
2. Restrict who can talk to the bot
Section titled “2. Restrict who can talk to the bot”Allowlists are comma-separated and case-sensitive on usernames:
BUB_TELEGRAM_ALLOW_USERS=123456789,your_username
BUB_TELEGRAM_ALLOW_CHATS=-1001234567890,-1009876543210
Behavior:
- If
BUB_TELEGRAM_ALLOW_CHATSis set, messages from any other chat are dropped silently. - If
BUB_TELEGRAM_ALLOW_USERSis set, messages from any other user receiveAccess denied. - A user matches when either their numeric id or their username appears in the list.
3. Optional: route through a proxy
Section titled “3. Optional: route through a proxy”BUB_TELEGRAM_PROXY=http://127.0.0.1:7890
# or socks5://user:pass@host:port
The same proxy is used for both the polling connection and outbound API calls.
4. Launch the gateway
Section titled “4. Launch the gateway”uv run bub gateway --enable-channel telegram
--enable-channel telegram pins the listener to one channel. Without it, bub gateway enables all channels (which excludes cli and includes Telegram if its token is set). On startup you should see:
telegram.start allow_users_count=2 allow_chats_count=1 proxy_enabled=False
telegram.start polling
5. How inbound messages are framed
Section titled “5. How inbound messages are framed”The Telegram channel uses telegram:<chat_id> as the session id. That keeps a private chat and a group chat separate even if the same user is in both.
Inbound handling:
/startis handled internally; the bot replies with a fixed greeting (or the “not allowed” message in disallowed chats)./bub <text>is normalized — the/bubprefix is stripped and the rest becomes the prompt content.- In private chats, every non-command message is ingested.
- In group chats, every non-command message reaches the Telegram channel. Messages that mention
@<bot_username>, contain the keywordbub, or reply to one of the bot’s own messages are marked active. Other group messages are ignored unless an active conversation for the same session is open withinBUB_ACTIVE_TIME_WINDOW, in which case they join that batch.
6. Debounce
Section titled “6. Debounce”The Telegram channel sets needs_debounce=True. Inbound messages are batched per session using BUB_DEBOUNCE_SECONDS, BUB_MAX_WAIT_SECONDS, and BUB_ACTIVE_TIME_WINDOW. See Channels overview for the values.
7. Outbound behavior
Section titled “7. Outbound behavior”Normal Telegram inbound messages set output_channel="null" before they enter the turn pipeline. That prevents a plain model return value from being sent back blindly. The bundled telegram skill is the canonical path for replies, progress updates, and edits.
Comma commands are different: they keep output_channel="telegram", so their tool output is sent back to the originating chat_id. If content routed to TelegramChannel.send(...) is JSON with a "message" field, only that field is sent; otherwise the raw content is sent. Empty payloads are dropped.
Next steps
Section titled “Next steps”- Channels overview — debounce,
enabled_channels, session ids. - Deploy — package the bot into a container with persistent state.
- Settings reference — every
BUB_TELEGRAM_*variable.