Skip to content

Connect a Telegram bot and one of your agents will reply to direct messages and group chats. The agent uses every tool, skill, and memory it would in the web UI.

What you need

  • A bot created with @BotFather on Telegram
  • The bot's API token (issued by BotFather, looks like 123456:ABC-DEF...)
  • A publicly reachable URL for the engine. See server.external_url. For local development, ngrok works.

Creating the bot

  1. Open a chat with @BotFather.
  2. Send /newbot and follow the prompts to set the name and username.
  3. Copy the API token from the confirmation message.
  4. (Optional) Send /setprivacy and disable privacy mode if you want the bot to read every message in groups, not just ones that mention it.

Connecting the channel

  1. In Frona, open Settings → Channels and click Add channel.
  2. Pick Telegram Bot.
  3. Choose the space the conversation will live in and the agent that will respond.
  4. Paste the bot token into bot_token.
  5. Save.

Frona registers a webhook with Telegram pointing at your engine, and the channel transitions to Connected. Send the bot a message from your Telegram account and the conversation will appear in the chosen space.

Configuration fields

FieldRequiredDescription
bot_tokenYesThe token issued by BotFather. Stored encrypted at rest.

How messages flow

  • Direct messages to the bot land in a chat tagged as direct.
  • Group messages that the bot can see (mentions, replies, or any message if privacy mode is disabled) land in a chat tagged as group.
  • Replies are sent back to the same Telegram chat. The adapter renders Markdown into Telegram's MarkdownV2 format when possible and falls back to plain text otherwise.
  • Tool calls are streamed as separate Telegram messages so you can watch progress, then the final reply is sent as one bubble.

Allowlisting senders

By default only paired-address senders pass receive_message. For a personal bot this means just you. To open the bot up to specific contacts or groups, add a policy. For example, allowing one Telegram username:

cedar
permit(
  principal == Policy::Agent::"assistant",
  action == Policy::Action::"receive_message",
  resource in Policy::Channel::"telegram"
) when { resource.sender.address == "@friend_username" };

See Policies for more patterns (channel-wide allows, blocking spammers, quiet mode).

Tips

  • One bot per agent. Telegram tokens cannot be shared across applications, and giving each agent its own bot keeps personalities clean.
  • Disable privacy mode for group bots. Otherwise the bot only sees @mentions and replies to its own messages.
  • Use Markdown in agent prompts. The adapter renders standard Markdown (bold, italic, links, code blocks) into Telegram's format.
  • Public URL is required. Telegram won't deliver webhooks to localhost. Use ngrok for local testing.

Troubleshooting

SymptomLikely cause
Channel marked Failed right after creationBad token, the token already in use elsewhere, or the engine's external URL isn't reachable from Telegram
Bot receives messages but you don't see themThe agent doesn't have receive_message permission for that sender. Check the agent's policies.
Bot doesn't reply in groupsPrivacy mode is on. Disable it via /setprivacy in BotFather.

Next steps

  • Channels. How channels work in general.
  • Policies. Allow specific senders or groups.