Skip to main content
connic
Connectors

Telegram

Start agents from messages to a Telegram bot and send their replies to users and groups.

Last updated
ModesInbound, outbound
YAML typetelegram
CredentialsThe bot token, in config. connic generates the webhook secret.
BridgeNot supported
Custom domainNot supported
Linked agentsOne or more. An update starts every linked agent.
While pausedInbound updates get 200 with {"status": "ignored"} and start no runs, and Telegram doesn't send them again. Outbound sends nothing.

Set up

  1. In Telegram, message @BotFather, send /newbot, follow the prompts, and copy the bot token, such as 123456:ABC-DEF....

  2. Open the agent. In Connector Flow, click Add inbound connector for inbound or Add outbound connector for outbound. Then click Create New Connector and choose Telegram.

  3. Choose the mode, Inbound (Receive Messages) or Outbound (Send Messages), and paste the Bot Token. For inbound, optionally enter Allowed User IDs. For outbound, optionally enter a Default Chat ID.

  4. Click Create. connic checks the token with Telegram. An inbound connector registers its webhook with Telegram, so there is nothing to set up there. For outbound, choose how the agent uses the connector and click Link connector.

In code

Declare the connector in connectors/*.yaml. bot_token must reference a variable. In an allowed_user_ids list, quote each ID; connic lint rejects unquoted list items. chat_id can stay an unquoted number.

connectors/telegram-inbox.yaml
type: telegram
mode: inbound
config:
  bot_token: ${TELEGRAM_BOT_TOKEN}
  allowed_user_ids: ["123456789", "987654321"]
agents:
  - telegram-assistant
connectors/telegram-replies.yaml
type: telegram
mode: outbound
config:
  bot_token: ${TELEGRAM_BOT_TOKEN}
  chat_id: -1001234567890
agents:
  - name: telegram-assistant
    outbound: { usage: automatic }

Configuration

The fields of a Telegram connector, the same in connectors/*.yaml, the REST API, and connic MCP. The descriptions name the matching setting in the dashboard. Connectors in code describes the fields every connector shares, such as agents and environments.

FieldTypeStatusDescription
typestringRequiredtelegram.
modestringRequiredinbound or outbound. Dashboard: Mode.
configobjectRequiredTelegram settings.
bot_tokenstringRequiredInbound and outbound. The token from @BotFather. connic checks it with Telegram when the connector is created and when the token changes. Secret. In YAML, use a ${NAME} reference. Dashboard: Bot Token.
allowed_user_idsstring | listOptionalInbound. Numeric Telegram user IDs that may start runs, such as 123456789, separated by commas or line breaks, or as a YAML list of quoted strings. connic rejects an entry that isn't a user ID. Empty lets everyone who can reach the bot start runs. Dashboard: Allowed User IDs.
chat_idstringOptionalOutbound. The numeric ID of the chat for messages that don't name one. Group and channel IDs are negative, such as -1001234567890. A number or a string both work; connic stores it as text and rejects a value that isn't a chat ID. Dashboard: Default Chat ID.

Generated values

connic creates these when the connector is created and keeps them across updates and deploys. Leave them out of YAML files; connic lint rejects secret_token.

ValueModesDescription
Webhook URLInboundWhere Telegram sends the bot's updates. connic registers it with Telegram, so you don't need to copy it. The details drawer shows it.
Secret tokenInboundTelegram sends it with every update, and connic rejects updates without it. It isn't shown.

Agent input

Modes: Inbound

An inbound connector starts a run for every linked agent with each message, edited message, and callback query the bot receives. An edited message arrives like a new one, with the edited text. The payload has the most useful fields at the top level and the full Telegram update under raw:

payload.json
{
  "update_id": 123456789,
  "text": "What is the status of my order?",
  "chat_id": 987654321,
  "message": {
    "message_id": 42,
    "text": "What is the status of my order?",
    "date": 1760000000,
    "chat_id": 987654321,
    "chat_type": "private",
    "chat_title": null,
    "from_id": 987654321,
    "from_username": "janedoe",
    "from_first_name": "Jane",
    "from_last_name": "Doe"
  },
  "raw": {
    "update_id": 123456789,
    "message": { ... }
  }
}

text is the message text or the caption of a media message. For a callback query, such as a press on an inline keyboard button, text holds the button's callback data and callback_query replaces message:

payload.json
{
  "update_id": 123456790,
  "text": "order_status",
  "chat_id": 987654321,
  "callback_query": {
    "id": "4382bfdwdsb323b2d9",
    "data": "order_status",
    "chat_id": 987654321,
    "from_id": 987654321,
    "from_username": "janedoe"
  },
  "raw": { ... }
}

With Allowed User IDs set, updates from other senders get 200 and start no run; the connector's runs list them with user_not_allowed and the sender_user_id. To find a user's ID, have them message the bot and read message.from_id in the run's input, or sender_user_id in the connector's runs while an allowlist is set.

Files and albums

connic downloads photos, voice messages, audio, videos, video notes, documents, and animations, and lists them under files with name, mime_type, base64-encoded data, and size in bytes. For a photo, it takes the largest size. The model receives each file as its own part and the rest of the payload as text.

A message or album takes up to 50 files, at most 32 MiB combined. connic skips invalid or unavailable files one by one. At the first file over a limit, it keeps the files before it and omits that one and all later ones. file_issues lists each omission with a code, a message, and the limit. The run starts even when no file was accepted, unless Files required is on for the agent's link or files_required: true is set on it in YAML.

connic collects the items of an album until no new item has arrived for 2 seconds, then starts one run per linked agent with all items in message order. text joins the captions, messages and raw_updates hold the individual messages, and media_group_id identifies the album. Telegram's retries of an album item don't start another run. Items that arrive after the collection has ended are omitted, and the webhook response and the connector logs report them as album_closed.

Bot webhook

Modes: Inbound

When an inbound connector is created, connic registers its webhook URL with Telegram for messages, edited messages, and callback queries, together with a generated secret token. Telegram sends the token in the X-Telegram-Bot-Api-Secret-Token header, and connic rejects requests without it with 401. connic registers the webhook again when the bot token changes or the connector switches to inbound, and removes it when the connector switches to outbound or you delete it.

A bot has one webhook. If the bot already has one from another service, connic replaces it and writes the previous URL to the connector logs and to the project's audit log, which keeps it after the connector is deleted. A bot that another connic connector receives updates for can't be connected; remove that connector first. Two inbound connectors in code can't use the same bot either, even in different environments. Outbound connectors don't register a webhook, so they can use the same bot as an inbound connector.

Outbound delivery

Modes: Outbound

An outbound Telegram connector sends one message through the bot with sendMessage each time it's used: when a linked agent's run completes, when the model calls it as a tool, or when middleware calls it, depending on the link's usage.

The chat comes from chat_id in the output or payload, then the connector's Default Chat ID, then the chat of the Telegram update that started the run. Without any of these, the send fails with missing_chat_id. A bot can only message users who have started a chat with it and groups or channels it has been added to.

connic sends every message with parse_mode: HTML, so Telegram renders tags such as <b> and <a>. Escape <, >, and & that aren't part of a tag as HTML entities, or Telegram rejects the message.

Automatic output

An automatic link sends the run's final output. Plain text becomes the message. A JSON object sets the message from text, message, or body, and can name the chat in chat_id; without any of the three, the whole JSON is sent as text.

output.json
{
  "chat_id": 987654321,
  "text": "Your order <b>#12345</b> is on its way."
}

Agent-tool and middleware payload

The model or middleware passes text, which is required and can't be empty, and optionally chat_id as a string or an integer. Other fields are rejected. connic adds the bot token and the default chat, none of which the model sees.

connector-payload.json
{
  "text": "Your order <b>#12345</b> is on its way.",
  "chat_id": "987654321"
}

Delivery and retries

A failed send is tried 3 times in total, waiting 1 and then 2 seconds between attempts, each with a 30-second timeout. The connector's runs show each delivery with its error, such as Telegram's description of a rejected message.

Limits and errors

LimitValue
Inbound updates1,000 per minute per connector. Further updates get 429.
Files50 per message or album, at most 32 MiB combined
Album collectionEnds 2 seconds after the latest item; at most 10 items
Message lengthTelegram accepts up to 4,096 characters. connic doesn't split longer text, so the send fails.
Delivery3 attempts, 1 and then 2 seconds apart, each with a 30-second timeout
Active connectorsAt the plan's active connector limit, creating a connector of either mode fails with 403 instead of creating it paused. A deploy that would create the connector or bring it back at the limit fails.

Inbound requests with a missing or wrong secret token get 401 and appear in the connector logs. An update that connic can't read gets 400 and appears in the connector's runs as failed.