92 lines
4.0 KiB
Markdown
92 lines
4.0 KiB
Markdown
# Telegram Channel
|
||
|
||
Connect a Telegram bot to an agent so the agent can read incoming messages and
|
||
reply. Telegram is the only channel implemented today; the machinery lives in
|
||
`backend/src/app_mixins/channel.py` (logic) and `backend/src/server/telegram.py`
|
||
(webhook route).
|
||
|
||
An agent that owns a `channel`/`telegram` resource *is* the agent that answers.
|
||
You can bind the same bot token to several agents, and one agent can be bound to
|
||
several bots.
|
||
|
||
## 1. Create a bot
|
||
|
||
Talk to [@BotFather](https://t.me/BotFather), create a bot, and copy its token
|
||
(looks like `123456:ABC-DEF...`). Treat the token as a secret.
|
||
|
||
## 2. Choose a delivery mode
|
||
|
||
Telegram can push updates to a webhook, or the hub can pull them with long
|
||
polling. The choice is driven entirely by the `HUB_HOST` environment variable:
|
||
|
||
- **Webhook** — set `HUB_HOST` to a publicly reachable host. Telegram requires
|
||
HTTPS on ports 443, 80, 88 or 8443, so the hub must be reachable there.
|
||
- **Long polling** — leave `HUB_HOST` unset. The hub prints a warning and polls
|
||
`getUpdates` instead. No public endpoint or TLS certificate is needed.
|
||
|
||
The `POST /channel/telegram/<agent_id>` route is always served regardless of
|
||
mode; in polling mode it simply never receives traffic.
|
||
|
||
Webhooks and polling are mutually exclusive. A webhook is never registered when
|
||
`HUB_HOST` is unset, and the poller clears any existing webhook (`deleteWebhook`)
|
||
before it starts.
|
||
|
||
## 3. Bind the bot to an agent
|
||
|
||
Add a resource to the responding agent (via the resources UI or the
|
||
`save-agent-resource` action):
|
||
|
||
```
|
||
kind = "channel"
|
||
key = "telegram"
|
||
value = {"token": "<bot token>", "secret": "<random webhook secret>", "name": "<display>"}
|
||
```
|
||
|
||
- `token` — the BotFather token. Required.
|
||
- `secret` — a random string of `A-Z a-z 0-9 _ -`, 1–256 characters. Optional,
|
||
and only meaningful in webhook mode. When present, Telegram sends it back on
|
||
every request in the `X-Telegram-Bot-Api-Secret-Token` header and the route
|
||
rejects mismatches with `403`.
|
||
- `name` — a display label. Optional.
|
||
|
||
This is the only state the channel persists. Conversations are **not** stored —
|
||
no `Chat`, `Thread` or `Message` rows are created. The rolling transcript is
|
||
held in memory on the hub and discarded when the process exits.
|
||
|
||
## 4. Restart the hub
|
||
|
||
On startup the hub queries all `channel`/`telegram` resources and reconciles the
|
||
provider:
|
||
|
||
- **Webhook mode**: it calls `getWebhookInfo` for each binding and, when the
|
||
registered URL does not match `https://<HUB_HOST>/channel/telegram/<agent_id>`,
|
||
calls `setWebhook` with that URL, the `secret_token`, and
|
||
`allowed_updates=["message"]`. Verify with `getWebhookInfo`.
|
||
- **Polling mode**: it starts one background task per binding. Confirm the bot is
|
||
reachable with `getMe`, then send a test message.
|
||
|
||
## 5. Talk to the bot
|
||
|
||
Message the bot. On each text message the hub:
|
||
|
||
1. Appends the message to the conversation's in-memory transcript.
|
||
2. Runs the agent with a flattened input — an instruction, a status message
|
||
(channel, chat id/title/type, current time, sender), and the rendered
|
||
conversation.
|
||
3. The agent replies by calling the `send_message` tool, which issues a
|
||
`sendMessage` call to Telegram.
|
||
|
||
Non-text updates (edited messages, media, callbacks) are ignored. Messages
|
||
authored by other bots are ignored.
|
||
|
||
## 6. Troubleshooting
|
||
|
||
| Symptom | Cause |
|
||
|---|---|
|
||
| Webhook not set | `HUB_HOST` unset, or the host is not reachable over HTTPS. Check the startup log. |
|
||
| Polling active when you expected a webhook | `HUB_HOST` is unset. |
|
||
| `403` from the webhook route | `X-Telegram-Bot-Api-Secret-Token` does not match the resource's `secret`. |
|
||
| `404` from the webhook route | No `channel`/`telegram` resource on that agent. |
|
||
| No reply | The agent has no model/tool configuration, or the run errored — check the hub log for `[channel]` lines. |
|
||
| `Conflict: can't use getUpdates method while webhook is active` | A stale webhook from a previous deployment. Remove it (`deleteWebhook`) or set `HUB_HOST` so webhook mode takes over. |
|