> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.loreos.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.loreos.app/_mcp/server.

# Telegram Managed Bots

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

> **Info**
>
> 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:

```bash
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:

```json
{
  "schema_version": "v0",
  "data": {
    "channel_id": "chn_...",
    "bot_username": "YourManagerBot",
    "telegram_role": "manager",
    "routing_mode": "developer_user_link",
    "status": "active",
    "webhook_status": "registered",
    "command_menu_status": "registered",
    "can_manage_bots": true,
    "management_mode_status": "enabled"
  }
}
```

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:

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

## 3. Create a relationship session

```bash
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

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

Response:

```json
{
  "schema_version": "v0",
  "data": {
    "session_id": "sess_...",
    "telegram": {
      "status": "pending",
      "request_id": "req_...",
      "bot_username": "lo_theo_ab12cd_bot",
      "deep_link": "https://t.me/newbot/YourManagerBot/lo_theo_ab12cd_bot?name=Theo",
      "expires_at": "2026-06-19T12:30:00+00:00"
    }
  }
}
```

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:

```json
{
  "telegram": {
    "status": "linked",
    "bot_username": "lo_theo_ab12cd_bot",
    "deep_link": "https://t.me/lo_theo_ab12cd_bot"
  }
}
```

## 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:

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

Response fields are non-secret:

```json
{
  "schema_version": "v0",
  "data": {
    "requests": [
      {
        "request_id": "req_...",
        "status": "linked",
        "session_id": "sess_...",
        "character_fixture_id": "theo",
        "manager_bot_username": "YourManagerBot",
        "suggested_bot_username": "lo_theo_ab12cd_bot",
        "managed_bot_username": "lo_theo_ab12cd_bot",
        "child_channel_id": "chn_...",
        "telegram_owner_present": true,
        "created_at": "2026-06-19T12:00:00+00:00",
        "expires_at": "2026-06-19T12:30:00+00:00",
        "updated_at": "2026-06-19T12:02:00+00:00"
      }
    ]
  }
}
```

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.

```bash
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

| Symptom                                              | Check                                                                                                                                             |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Child contact creation says manager unavailable      | `GET /v1/delivery-channels` has an active `telegram_role=manager` channel                                                                         |
| BotFather link fails                                 | `management_mode_status` is `enabled`; if not, enable Bot Management Mode and verify                                                              |
| User created the bot but no link happens             | check `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 appears | read `GET /v1/observability/sessions/{session_id}/telegram`, then inspect `/trace` and `/runs` for the same `trace_id`                            |
| User blocked the bot                                 | delivery 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.