> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cogniagent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Telegram channel

> Connect a Telegram bot to your conversation flow. Users DM the bot and the flow replies in the same chat.

Telegram lets your flow live inside the world's most popular messaging app. You create a bot with **@BotFather**, connect it once, and any DM sent to that bot becomes a conversation in your flow.

## When to use Telegram

* Consumer-facing support or assistant bots where your audience already lives in Telegram.
* International / emerging-market audiences where Telegram has higher reach than Slack or Teams.
* Lightweight bots that don't need a website or login — just `t.me/your_bot` and people can chat.
* Group-channel companions where the bot answers questions when DM'd.

## Responder mode only

Telegram is a **responder-only** channel. The bot can reply to anyone who has messaged it, but it **cannot cold-start a conversation** with a user it has never met.

<Info>
  This is a Telegram platform restriction, not a CogniAgent one. Telegram's Bot API does not expose a way to look up users by `@username` for DM purposes — bots can only send messages to chats they have already received a message in. The standard workaround is a **deep link** like `t.me/your_bot?start=welcome`, which a user clicks first; once they tap **Start**, your bot has their `chat_id` and can talk.
</Info>

If you need a bot that proactively reaches out to users (a marketing blast, a scheduled reminder to a new lead), Telegram isn't the right channel — use **SMS**, **WhatsApp Business**, or **Email** instead.

## Before you start

You need two things:

1. A **bot token** from [@BotFather](https://t.me/BotFather) on Telegram.
2. A **builtin Composio Telegram** connection in CogniAgent that holds the token.

### Create the bot with @BotFather

<Steps>
  <Step title="Open @BotFather in Telegram">
    Search for `@BotFather` and start a chat. It's the official bot for creating other bots.
  </Step>

  <Step title="Send /newbot">
    BotFather asks for:

    * A **display name** (what users see, e.g. "Acme Support").
    * A **username** ending in `bot` (e.g. `acme_support_bot`).
  </Step>

  <Step title="Copy the token">
    BotFather replies with a token of the form `1234567890:ABCdef...`. Keep this safe — anyone with the token can impersonate your bot.
  </Step>

  <Step title="(Optional) Configure the bot">
    While you're in BotFather you can also set:

    * `/setdescription` — the "About" blurb users see before they start the chat.
    * `/setuserpic` — a profile photo.
    * `/setprivacy` — `Disable` if you want the bot to read all messages in groups it's added to (not just `@mentions`). Default is `Enable` (only sees `@mentions`).
  </Step>
</Steps>

### Add the Telegram channel and connect the bot

The Telegram connection is created from inside the channel-add flow — there's no separate trip to the Integrations page first.

<Steps>
  <Step title="Open the flow's Channels configuration">
    Go to **Conversations** → open the flow → **Configuration** → **Channels** tab.
  </Step>

  <Step title="Add Channel → Telegram">
    Click **Add Channel** and pick **Telegram** from the channel picker.
  </Step>

  <Step title="Create (or pick) a Telegram connection">
    The channel form's **Connection** field lets you either pick an existing Telegram connection or create a new one inline. When creating new, the form asks for an **API Key** — paste the BotFather token here. The form's description text walks through the BotFather flow if you skipped it above.
  </Step>

  <Step title="Save and Deploy">
    Save the channel and deploy the flow. Within \~5 seconds your bot starts polling for new messages, and any DM to `@your_bot` creates a conversation.
  </Step>
</Steps>

Once created, the connection is reusable — you can pick it from the dropdown in any other flow's Telegram channel configuration.

[Manage integration connections →](/features/integrations)

## How conversations are scoped

Each conversation is keyed by **`chat_id : from_user_id`** — the chat the message arrived in *and* the user who sent it.

| Scenario                                                   | Conversation                                                         |
| ---------------------------------------------------------- | -------------------------------------------------------------------- |
| Sarah DMs the bot                                          | One conversation (her `chat_id` == her user id)                      |
| Sarah DMs the bot again next week                          | Same conversation (subject to session timeout)                       |
| Mike DMs the same bot                                      | A separate conversation                                              |
| Bot is added to a group; Sarah and Mike both `@mention` it | Two separate conversations (one per user) inside the same group chat |

This mirrors how Slack scoping works in DM mode.

## Outbound formatting (MarkdownV2)

The bot sends replies with `parse_mode: MarkdownV2`. The flow's actor prompt is auto-augmented to nudge the LLM toward MarkdownV2-safe output, but a few quirks are worth knowing:

* **Single-delimiter bold**: `*bold*` (not `**bold**`).
* **Single-delimiter italic**: `_italic_`.
* **Reserved characters** must be backslash-escaped when used as literal text:
  ```
  _  *  [  ]  (  )  ~  `  >  #  +  -  =  |  {  }  .  !
  ```
  So a literal `1.5` should be written `1\.5`, and `https://example.com/path` should escape the dot too.
* **Code spans** use backticks. Triple backticks for fenced code blocks (with an optional language tag) work the same as GitHub.

If a reply ever fails to render (you see escape characters in the message), it usually means the LLM forgot to escape a reserved character. This is rare with Sonnet, but possible — re-asking ("please re-send escaped properly") usually fixes it.

<Tip>
  Keep messages **short and chat-shaped**. Telegram DMs are scanned on a phone — a wall of markdown looks worse than a few short paragraphs. The system prompt steers the actor this way already.
</Tip>

## Rich content

| Element              | Telegram                            |
| -------------------- | ----------------------------------- |
| Plain text           | ✓                                   |
| Bold / italic        | ✓ (MarkdownV2)                      |
| Links                | ✓                                   |
| Bullet lists         | ✓ (rendered as plain text with `-`) |
| Code blocks          | ✓ (fenced)                          |
| Inline buttons       | not in v1                           |
| Images / attachments | links only in v1                    |
| Voice notes          | —                                   |

Inline keyboards, photo uploads, and audio replies are on the roadmap but not in the initial release.

## How polling works

There is no Telegram webhook to host — the platform polls Telegram's `getUpdates` API every **5 seconds** with an offset bookmark stored in Redis. Updates older than 24 hours that have never been claimed get garbage-collected by Telegram, so the worst-case delivery delay is bounded.

If you previously set a webhook on the same bot (via `setWebhook`), Telegram refuses to serve `getUpdates` and returns HTTP 409. The poller logs this as a warning. To resolve, call `https://api.telegram.org/bot<TOKEN>/deleteWebhook` once and the poller resumes.

## Per-user identity

Inbound messages carry the sender's:

* `from_id` — numeric Telegram user id.
* `from_username` — the `@handle`, if set (optional in Telegram).
* `from_first_name` / `from_last_name` — display name parts.

The flow sees a resolved `participantName` (e.g. `"Sarah Lee"` or `"@sarah_lee"` if no real name is set) which actors can reference in their prompts.

## Limitations

<Warning>
  * Bots cannot DM users who haven't started a chat with them. There is no "cold outreach" path on Telegram for bots.
  * Group chats: by default Telegram bots in groups only receive messages that `@mention` them. To see every message, toggle `/setprivacy` to **Disable** in BotFather — but expect higher inbound volume.
  * `@username` is not a stable destination identifier. Telegram only treats numeric `chat_id` as routable. The platform stores the numeric id internally.
  * A single bot token serves one bot. If you want a different persona, create a new bot in BotFather and a new connection in CogniAgent.
</Warning>

## Troubleshooting

| Symptom                                           | Likely cause                                                                                                                                                                                     |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| No conversations appear after deploy              | The bot hasn't received any DMs yet. Send `/start` from your own account to `@your_bot` to trigger the first one.                                                                                |
| Bot replies stop after a redeploy                 | A previously-set webhook is intercepting updates. Call `deleteWebhook` once.                                                                                                                     |
| Replies render as literal characters (`\.`, `\!`) | The model emitted text that doesn't satisfy MarkdownV2 escaping. Usually self-corrects on the next turn; consider tightening the actor's system prompt.                                          |
| Multiple users in one group share state           | Privacy mode is off but the actor wasn't designed for group context. Either turn privacy back on (so the bot only hears `@mentions`) or have the actor handle the multi-speaker case explicitly. |
| New session created on every message              | Session timeout is shorter than the gap between user messages. Increase it in Flow settings.                                                                                                     |

## Next

<CardGroup cols={2}>
  <Card title="Messaging channels" icon="comments" href="/conversation-flows/channels/messaging">
    Slack and Teams — the closest cousins of Telegram.
  </Card>

  <Card title="Deploy a flow" icon="rocket" href="/conversation-flows/operate/deploy">
    Schedule the Telegram listener.
  </Card>
</CardGroup>
