Telegram Voice
@tuttiai/telegram — give agents a bot that can read, post, and moderate messages on Telegram, plus the shared bot client used by @tuttiai/inbox
The Telegram voice gives agents a bot account they can use to send and edit messages on Telegram.
Write tools (post_message, edit_message, delete_message, send_photo) are marked destructive: true, so HITL-enabled runtimes gate them behind human approval before anything is sent.
The same package also exports TelegramClientWrapper, a token-keyed reference-counted bot wrapper that @tuttiai/inbox reuses for its inbound Telegram adapter. Telegram does not allow two simultaneous polling sessions per bot token, so sharing the underlying bot is mandatory when both surfaces are active.
Installation
npx tutti-ai add telegram
Required permissions
permissions: ["network"]
Required environment variables
| Var | Description |
|---|---|
TELEGRAM_BOT_TOKEN | Bot token from @BotFather |
Add to your .env:
TELEGRAM_BOT_TOKEN=123456789:AA…your-token…
Bot setup
- Open @BotFather in Telegram and send
/newbot. Pick a display name and a username — it must end inbot(e.g.my_tutti_bot). BotFather replies with the bot token. - (Inbox use only.) If the bot needs to read non-mention messages in groups, send
/setprivacy, choose your bot, and select Disable. - Add the bot to a chat or channel you want it to post in. For channels, the bot must be made an administrator with Post messages rights.
Score example
import { TelegramVoice } from "@tuttiai/telegram";
import { defineScore } from "@tuttiai/core";
export default defineScore({
agents: {
support: {
name: "support",
system_prompt: "You are a Telegram support agent.",
voices: [new TelegramVoice()],
permissions: ["network"],
},
},
});
Tools
| Tool | Description |
|---|---|
post_message | Send a text message to a chat or channel. Up to 4096 chars. |
edit_message | Edit a message the bot previously sent (< 48h old). |
delete_message | Delete a message. The bot can always delete its own; deleting others requires admin rights. |
send_photo | Send a photo by URL or file_id. Optional caption (1024 chars). |
All four tools accept either a numeric chat_id (e.g. 12345, -1001234567890 for supergroups) or a @channel_username string.
Lifecycle
The bot is created lazily on the first tool call. For outbound-only use, no polling loop is started — the Telegram REST API works without one.
When @tuttiai/inbox adds a Telegram adapter against the same token, the wrapper installs a single shared getUpdates poll that fans out to both the voice and the inbox handler. Call voice.teardown() (or TuttiRuntime.teardown()) on shutdown to release the wrapper’s reference. The bot is only stopped when the last holder releases.