Telegram Managed Bots

One Telegram contact per user-character relationship.

Use this path when your product wants every user-character relationship to have its own Telegram contact and chat history.

Managed Bots are different from connecting one existing BotFather token to one character. You connect a manager bot once, then LoreOS creates or reuses a child bot contact for each relationship.

1. Prepare the manager bot

In Telegram:

  1. Open @BotFather.
  2. Create or select the manager bot.
  3. Open BotFather’s Mini App.
  4. Open the manager bot settings.
  5. Enable Bot Management Mode.

Then copy the manager bot token.

2. Connect the manager

The hosted console has a Telegram Managed Bots panel. Paste an app runtime API key, paste the manager bot token, and click Connect manager.

Or call the API:

$curl -X POST https://api.loreos.app/v1/apps/$APP_ID/delivery-channels/telegram \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "bot_token": "'"$TELEGRAM_MANAGER_BOT_TOKEN"'",
> "telegram_role": "manager",
> "routing_mode": "developer_user_link"
> }'

The response includes non-secret status:

1{
2 "schema_version": "v0",
3 "data": {
4 "channel_id": "chn_...",
5 "bot_username": "YourManagerBot",
6 "telegram_role": "manager",
7 "routing_mode": "developer_user_link",
8 "status": "active",
9 "webhook_status": "registered",
10 "command_menu_status": "registered",
11 "can_manage_bots": true,
12 "management_mode_status": "enabled"
13 }
14}

Status meanings:

  • enabled: Telegram confirmed can_manage_bots=true.
  • disabled: enable Bot Management Mode in BotFather and verify again.
  • unknown: verify again after enabling Bot Management Mode.
  • not_required: ordinary character bots do not use management mode.

Verify again after changing BotFather settings:

$curl -X POST https://api.loreos.app/v1/delivery-channels/$CHANNEL_ID/verify \
> -H "Authorization: Bearer $LOREOS_KEY"

3. Create a relationship session

$curl -X POST https://api.loreos.app/v1/sessions \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "character": "theo",
> "external_user_ref": "user_123",
> "display_name": "Test User"
> }'

Save data.session_id.

4. Create or reuse the Telegram contact

$curl -X POST https://api.loreos.app/v1/sessions/$SESSION_ID/telegram/managed-child-bot \
> -H "Authorization: Bearer $LOREOS_KEY"

Response:

1{
2 "schema_version": "v0",
3 "data": {
4 "session_id": "sess_...",
5 "telegram": {
6 "status": "pending",
7 "request_id": "req_...",
8 "bot_username": "lo_theo_ab12cd_bot",
9 "deep_link": "https://t.me/newbot/YourManagerBot/lo_theo_ab12cd_bot?name=Theo",
10 "expires_at": "2026-06-19T12:30:00+00:00"
11 }
12 }
13}

Open data.telegram.deep_link from the end user’s Telegram account. Telegram guides the user through creating or confirming the child bot. When Telegram sends the managed-bot update to LoreOS, LoreOS fetches the child token, stores it in Vault, registers the webhook, and binds the child bot to the existing session.

Calling the endpoint again after linking returns:

1{
2 "telegram": {
3 "status": "linked",
4 "bot_username": "lo_theo_ab12cd_bot",
5 "deep_link": "https://t.me/lo_theo_ab12cd_bot"
6 }
7}

5. Check child contact status

The console shows Recent child contacts in the Telegram Managed Bots panel. Use it to see whether the web handoff is still waiting for Telegram, already linked to a child bot, expired, or failed.

You can also call the API:

$curl "https://api.loreos.app/v1/delivery-channels/telegram/managed-bot-requests?limit=20" \
> -H "Authorization: Bearer $LOREOS_KEY"

Response fields are non-secret:

1{
2 "schema_version": "v0",
3 "data": {
4 "requests": [
5 {
6 "request_id": "req_...",
7 "status": "linked",
8 "session_id": "sess_...",
9 "character_fixture_id": "theo",
10 "manager_bot_username": "YourManagerBot",
11 "suggested_bot_username": "lo_theo_ab12cd_bot",
12 "managed_bot_username": "lo_theo_ab12cd_bot",
13 "child_channel_id": "chn_...",
14 "telegram_owner_present": true,
15 "created_at": "2026-06-19T12:00:00+00:00",
16 "expires_at": "2026-06-19T12:30:00+00:00",
17 "updated_at": "2026-06-19T12:02:00+00:00"
18 }
19 ]
20 }
21}

Possible request statuses:

  • pending: LoreOS created the request and is waiting for Telegram’s managed-bot update.
  • linked: the child bot token was fetched, stored in Vault, and bound to the session.
  • expired: the short-lived request was not completed before expires_at.
  • failed: LoreOS received enough information to try linking, but child setup failed. Check error_code and error_message.

The response does not include manager tokens, child tokens, webhook secrets, raw Telegram update payloads, or raw Telegram owner user IDs.

6. Read replies from the event log

Telegram delivery and web delivery share one session event log.

$curl "https://api.loreos.app/v1/sessions/$SESSION_ID/events?since=0" \
> -H "Authorization: Bearer $LOREOS_KEY"

Render message.created, character.initiated, and image.ready events. Do not wait for delivery-attempt delivered status before showing a reply in your own UI.

Troubleshooting

SymptomCheck
Child contact creation says manager unavailableGET /v1/delivery-channels has an active telegram_role=manager channel
BotFather link failsmanagement_mode_status is enabled; if not, enable Bot Management Mode and verify
User created the bot but no link happenscheck GET /v1/delivery-channels/telegram/managed-bot-requests; manager webhook should be registered and allowed updates include managed_bot
Telegram messages reach the bot but no reply appearsread GET /v1/observability/sessions/{session_id}/telegram, then inspect /trace and /runs for the same trace_id
User blocked the botdelivery attempts show Telegram 403 and future sends are suppressed

Security model

  • Raw manager and child bot tokens are never returned by the API.
  • Tokens are stored in Vault, not in delivery-channel config.
  • Console and API responses expose only non-secret status fields.
  • One child bot maps to one user-character relationship, so Telegram chat history stays natural for the user.