Skip to content
AgentDock

Integrations

Telegram

A bot for alerts and one-tap merge approvals.

AgentDock can send notifications to each person's private Telegram chat through a bot you create. One bot serves the whole instance; every user links their own chat and picks which kinds of notification reach it.

The bot uses long polling, so your server needs outbound HTTPS to api.telegram.org and nothing else. No public URL, no inbound port.

Before you start

  • APP_ENCRYPTION_KEY must be set in the API's environment. The bot token is stored encrypted (AES-256-GCM) under it. Without the key, the Telegram page shows No APP_ENCRYPTION_KEY on the server and refuses the token.
  • APP_URL should be the public web URL people open AgentDock at, for example https://agentdock.example.com. Every message links back to it. It falls back to WEB_URL.
VariableDefaultMeaning
APP_ENCRYPTION_KEYunset32 random bytes, base64 (openssl rand -base64 32). Required.
APP_URLhttp://localhost:3517Web URL used in message links.
TELEGRAM_POLL_TIMEOUT_S30Long-poll timeout for getUpdates, in seconds.
TELEGRAM_API_BASEhttps://api.telegram.orgBot API base. Only tests change it.

Set up the bot

  1. Create a bot with BotFather

    In Telegram, open a chat with @BotFather, send /newbot, choose a name and a username, and copy the token it gives you.

  2. Paste the token

    Go to Admin → Integrations → Telegram and use Set the bot token. The API verifies the token with Telegram's getMe, stores it encrypted and shows only the bot's username from then on. The stored token is never shown again.

  3. Check the poller

    The page shows Status, Polling (Running or Not running), Last poll and, if something failed, Last poller error. Once you have linked your own chat (next section), Send test message sends a message to it.

Replace the bot token with a token for a different bot and every linked user has to link again, because their chats belong to the old bot. Removing the bot stops Telegram delivery; notifications keep arriving in the app.

Each person links their own chat. An admin cannot link a chat for someone else.

  1. Open Account → Notifications and click Link Telegram.
  2. AgentDock creates a one-time code and opens https://t.me/<bot>?start=<code>.
  3. Press Start in the chat that opens. The bot receives /start <code> and binds that chat to your account.

The code is valid for 10 minutes and works once. Only private chats are accepted, each user has one chat, and a chat already linked to another user is refused.

To unlink, click Unlink on the same page or send /stop to the bot.

Which notifications go to Telegram is set per kind on Account → Notifications, next to the in-app switch. You can also mute a project there. See Notifications for the kinds and their defaults.

Why long polling

The first deployment target is a home server that may sit behind NAT with no public HTTPS endpoint. Long polling (getUpdates) needs only outbound HTTPS, so the bot works anywhere the API can reach the internet. Exactly one poller runs, guarded by a PostgreSQL advisory lock, which matches AgentDock's single-API-instance design. A webhook mode does not exist.

Approve from Telegram

A pr.awaiting_approval message can carry two inline buttons: Approve and Request changes.

  • Every press is checked again from scratch: the chat must be linked, the message must have been sent to that user, the account must be active, and the user must be an operator or admin of the project right now.
  • The decision is bound to the pull request's head commit that the message showed. If someone pushed since, the press is refused and you decide in AgentDock.
  • Request changes asks for a note. Reply to the bot's prompt with the text (at most 4 KB); the note goes to the worker.
  • Each outcome is audited as telegram.approval, and the approval itself is audited like one made in the web app.

If the pull request is unknown, not open, or the runner cannot be reached when the message is sent, the message goes out with its link only and no buttons.

Limits

RuleValue
Duplicate foldingThe same user, kind, project and slot within 15 minutes updates one notification instead of sending a new one
Rate limit20 Telegram messages per user per 10 minutes. Beyond that, items are collected into one digest sent at the end of the window
Telegram 429Retries honour Telegram's retry_after
Runner offlineOne runner.offline per runner after more than 5 minutes offline, to admins only

What a message contains

A message is plain text: the project, the slot or issue, a one-line reason and a link to the right page in AgentDock (APP_URL). It never includes pane text, prompts, code or secrets.

What AgentDock stores for Telegram: the chat id and username of each linked user, the delivery state of each message, and the encrypted bot token. Bot configuration, linking, unlinking and rule changes are audited.

Next steps