feat: Telegram Channel
This commit is contained in:
1 parent
3238c059f6
commit
9a85c61781
7 files changed
+540
-4
No files matched your search
@@ -0,0 +1,91 @@
|
||||
# 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. |
|
||||
Reference in new issue
Block a user