Telegram
Expose agents, teams, or workflows as Telegram bots with webhook endpoints.
The Telegram interface exposes an Agno Agent, Team, or Workflow on Telegram via FastAPI webhook endpoints. It handles inbound messages (text, photos, audio, video, documents, stickers) and streams responses back to the originating chat.
Setup
Follow the Telegram setup guide to set up your bot.
Install dependencies: uv pip install 'agno[os,telegram]' google-genai openai
Required configuration:
TELEGRAM_TOKEN(bot token from @BotFather)TELEGRAM_WEBHOOK_SECRET_TOKEN. Required in production and skipped whenAPP_ENV=developmentGOOGLE_API_KEYfor the Gemini model in the interface exampleOPENAI_API_KEYfor the default model in theTelegramToolsexample- An ngrok tunnel (for local development) and webhook pointing to
/telegram/webhook
Example Usage
Create an agent, expose it with the Telegram interface, and serve via AgentOS:
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.google import Gemini
from agno.os.app import AgentOS
from agno.os.interfaces.telegram import Telegram
agent_db = SqliteDb(session_table="telegram_sessions", db_file="tmp/telegram_basic.db")
telegram_agent = Agent(
name="Telegram Bot",
model=Gemini(id="gemini-2.5-pro"),
db=agent_db,
instructions=[
"You are a helpful assistant on Telegram.",
"Keep responses concise and friendly.",
],
add_history_to_context=True,
num_history_runs=3,
add_datetime_to_context=True,
markdown=True,
)
agent_os = AgentOS(
agents=[telegram_agent],
interfaces=[Telegram(agent=telegram_agent)],
)
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve(app="basic:app", port=7777, reload=True)See the Telegram examples for more usage patterns including streaming, teams, workflows, and multiple instances.
Parameters
Provide agent, team, or workflow. Call get_router() to get the FastAPI APIRouter with all endpoints attached.
| Parameter | Type | Default | Description |
|---|---|---|---|
agent | Optional[Union[Agent, RemoteAgent]] | None | Agno Agent or RemoteAgent instance. |
team | Optional[Union[Team, RemoteTeam]] | None | Agno Team or RemoteTeam instance. |
workflow | Optional[Union[Workflow, RemoteWorkflow]] | None | Agno Workflow or RemoteWorkflow instance. |
prefix | str | "/telegram" | Custom FastAPI route prefix for the Telegram interface. |
tags | Optional[List[str]] | None | FastAPI route tags for API documentation. Defaults to ["Telegram"] if not provided. |
token | Optional[str] | None | Bot token. Falls back to TELEGRAM_TOKEN environment variable. |
streaming | bool | True | Enable token-by-token streaming with live message edits. |
show_reasoning | bool | False | Send the model's reasoning as a separate message before the response. Non-streaming mode only. |
reply_to_mentions_only | bool | True | When True (default), bot responds to @mentions and replies in groups, and all messages in DMs. When False, responds to all messages in groups. |
reply_to_bot_messages | bool | True | When True, also responds when users reply to the bot's own messages in groups. |
start_message | str | "Hello! I'm ready to help. Send me a message to get started." | Message sent in response to the /start command. |
help_message | str | "Send me text, photos, voice notes, videos, or documents and I'll help you with them." | Message sent in response to the /help command. |
error_message | str | "Sorry, there was an error processing your message. Send /new to start a fresh conversation." | Message sent when processing fails. |
new_message | str | "New conversation started. How can I help you?" | Message sent when a user starts a new session with /new. |
commands | Optional[List[Dict[str, str]]] | None | List of bot commands to register with Telegram. Each dict has command and description keys. Defaults to /start, /help, and /new when not provided. |
register_commands | bool | True | Automatically register commands with the Telegram Bot API on first message. |
quoted_responses | bool | False | Quote the user's message in private chats. Group replies are always quoted. |
Endpoints
Mounted under the /telegram prefix (customizable via prefix):
GET /telegram/status
Health/status check for the interface. Returns {"status": "available"}.
POST /telegram/webhook
Receives Telegram updates (messages, edited messages).
- Validates the
X-Telegram-Bot-Api-Secret-Tokenheader; bypassed whenAPP_ENV=development. - Deduplicates updates by
update_id. - Processes text, photos, voice notes, audio, video, documents, stickers, and animations.
- Streams or sends responses back to the originating chat (splits long messages at Telegram's 4096 character limit).
- Responses:
200 {"status": "processing"},{"status": "ignored"}, or{"status": "duplicate"};403invalid secret token;500errors.
Behavior
Session Management
Sessions are scoped by chat and entity. The entity_id is the agent, team, or workflow ID (falls back to name, then type).
- DMs and basic groups:
tg:telegram-bot:123456789 - Supergroup threads and forum topics:
tg:telegram-bot:123456789:42
When a database is configured on the agent, team, or workflow, the /new command creates a fresh session. Without a database, /new has no persisted session to replace. History and memory are not persisted.
The /new command requires a database. Without a database, there is no persisted session to replace.
Streaming
When streaming=True (the default), the bot edits the response message in real time as tokens arrive. Edits are throttled to roughly once per second to stay within Telegram's rate limits. The user sees incremental output instead of waiting for the full response.
For workflows, streaming also surfaces step progress (e.g., which agent in the workflow is currently running).
Group Chat Support
By default, the bot only responds when mentioned (@your_bot) or replied to in group chats. This is controlled by two parameters:
reply_to_mentions_only=True(default): only respond to @mentions and direct repliesreply_to_bot_messages=True(default): also respond when users reply to the bot's own messages
To have the bot respond to all messages in a group, set reply_to_mentions_only=False.
BotFather privacy mode: By default, Telegram bots in groups only receive messages that mention them or are commands. To let the bot see all group messages (required for reply_to_mentions_only=False), message @BotFather, send /setprivacy, select your bot, and choose Disable.
Media Support
Inbound (user sends to bot): photos, stickers, voice notes, audio files, video, video notes, animations (GIFs), and documents. Media is downloaded and passed to the agent as images, audio, video, or file inputs.
Outbound (agent sends to user): images, audio, video, and files generated by agent tools, such as OpenAITools with GPT Image 2 or ElevenLabsTools. Media is sent as native Telegram media messages alongside the text response.
TelegramTools
TelegramTools is a standalone toolkit that lets agents proactively send messages and media to Telegram chats. It is independent from the Telegram interface. The interface handles inbound webhooks; the toolkit gives agents outbound actions.
from agno.agent import Agent
from agno.tools.telegram import TelegramTools
agent = Agent(
tools=[TelegramTools(chat_id="123456789", all=True)],
)Toolkit Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
chat_id | Optional[str] | None | Default chat ID. Falls back to TELEGRAM_CHAT_ID env var. |
token | Optional[str] | None | Bot token. Falls back to TELEGRAM_TOKEN env var. |
output_directory | Optional[str] | None | Directory for saved file downloads. |
save_downloads | bool | False | Save downloads locally when output_directory is also set. |
enable_send_message | bool | True | Enable send_message tool. |
enable_send_photo | bool | False | Enable send_photo tool. |
enable_send_document | bool | False | Enable send_document tool. |
enable_send_video | bool | False | Enable send_video tool. |
enable_send_audio | bool | False | Enable send_audio tool. |
enable_send_animation | bool | False | Enable send_animation tool (GIFs). |
enable_send_sticker | bool | False | Enable send_sticker tool. |
enable_edit_message | bool | False | Enable edit_message tool. |
enable_delete_message | bool | False | Enable delete_message tool. |
enable_react_with_emoji | bool | False | Enable message reactions. |
enable_pin_message | bool | False | Enable pinning messages. |
enable_get_chat | bool | False | Enable chat metadata retrieval. |
enable_get_file | bool | False | Enable file retrieval. |
all | bool | False | Enable all tools. Overrides individual flags. |
Toolkit Methods
| Method | Description |
|---|---|
send_message | Send a text message to a chat. |
send_photo | Send a photo (bytes) with optional caption. |
send_document | Send a document (bytes) with filename and optional caption. |
send_video | Send a video (bytes) with optional caption. |
send_audio | Send an audio file (bytes) with optional caption and title. |
send_animation | Send an animation/GIF (bytes) with optional caption. |
send_sticker | Send a sticker (bytes). |
edit_message | Edit a previously sent message by message_id. |
delete_message | Delete a message by message_id. |
react_with_emoji | Add an emoji reaction to a message. |
pin_message | Pin a message in a chat. |
get_chat | Retrieve chat information. |
get_file | Retrieve file metadata and base64 content, or save to the configured download directory. |
Message-sending methods return a JSON string with {"status": "success", "message_id": ...} on success or {"status": "error", "message": ...} on failure. delete_message returns {"status": "success", "deleted": true}. Chat and file retrieval return their own data fields; pinning returns the pinned state and message ID.
For the full toolkit reference, see TelegramTools.
Testing the Integration
-
Run the app locally:
python <my-app>.py(ensure ngrok is running) -
Register the webhook with the same secret configured on the server:
curl -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/setWebhook" \ --data-urlencode "url=${NGROK_URL}/telegram/webhook" \ --data-urlencode "secret_token=${TELEGRAM_WEBHOOK_SECRET_TOKEN}" -
Open your bot in Telegram and send
/startor any message -
In a group: add the bot and mention it with
@your_bot hello
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| 403 errors on webhook | Running in production mode without a webhook secret | Set APP_ENV=development for local testing, or set TELEGRAM_WEBHOOK_SECRET_TOKEN and register the webhook with the matching secret_token |
| No response from the bot | Server not running or webhook not set | Check server: curl http://localhost:7777/telegram/status. Check webhook: curl "https://api.telegram.org/bot${TELEGRAM_TOKEN}/getWebhookInfo" |
| Bot ignores group messages | Privacy mode enabled (default) | Message @BotFather, send /setprivacy, select your bot, choose Disable |
/new has no effect | No database configured | Add a SqliteDb (or other DB) to the agent, team, or workflow. Without a DB, /new has no persisted session to replace. |
TELEGRAM_TOKEN environment variable is not set | Missing env var | Export TELEGRAM_TOKEN before running |