Workflow Operator on Telegram
Workflow Operator on Telegram uses a Telegram bot to map each Telegram chat to a persistent Dagu AI agent session. Messages sent in Telegram are forwarded to the built-in AI agent, and agent responses are sent back to Telegram. When a DAG run completes, Workflow Operator can also send AI-generated notifications so follow-up stays in the same conversation.
Prerequisites
Before setting up Workflow Operator on Telegram, configure the AI agent in the Web UI. Go to Agent Settings (/agent-settings) and set up the agent model, tool policy, and other defaults first. The Telegram bot forwards messages to the built-in agent, so it must be configured before Telegram can use it. Start with Agent Settings, then use Models & Providers and Tool Permissions & Bash Policy for the concrete setup pieces.
Creating a Telegram Bot
Before configuring Dagu, you need to create a bot on Telegram and get its token.
Open Telegram and search for
@BotFather, or go to https://t.me/BotFather.Send
/newbot.BotFather will ask for a display name (e.g.,
My Dagu Bot). Send it.BotFather will ask for a username. This must end in
bot(e.g.,my_dagu_bot). Send it.BotFather replies with a message containing your bot token. It looks like this:
Done! Congratulations on your new bot. You will find it at t.me/my_dagu_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. Use this token to access the HTTP API: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11Copy the token (
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11in this example). This is the value forbots.telegram.tokenin Dagu config or theDAGU_BOTS_TELEGRAM_TOKENenvironment variable.Open a chat with your new bot in Telegram (search for
@my_dagu_bot) and send any message. This is needed so the bot has a chat to respond to, and so you can retrieve your chat ID (see Finding your chat ID below).
Running
The Telegram connector for Workflow Operator starts automatically when bots.provider is set to telegram and you run either:
dagu serveror
dagu start-allIn both modes, the connector shares the server's agent API instance.
Configuration
Set provider: telegram under bots and configure the Telegram-specific fields. Only one connector can be active at a time. Set these in the Dagu config file (~/.config/dagu/config.yaml or the path set by DAGU_HOME):
bots:
provider: telegram
safe_mode: true
telegram:
token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
allowed_chat_ids:
- 123456789
- 987654321bots fields
| Field | Type | Default | Description |
|---|---|---|---|
provider | string | "" (disabled) | Which connector to run. Set to "telegram" for Telegram. If empty, no bot starts. Only one provider can be active at a time. |
safe_mode | bool | true | Passed to the agent's ChatRequest.SafeMode field. Applies to all bot connectors. |
bots.telegram fields
| Field | Type | Default | Description |
|---|---|---|---|
token | string | (required) | Bot token from Telegram's @BotFather |
allowed_chat_ids | []int64 | (required) | Telegram chat IDs authorized to use the bot. Messages from other chats are rejected. |
Environment variables
| Variable | Config equivalent |
|---|---|
DAGU_BOTS_PROVIDER | bots.provider |
DAGU_BOTS_SAFE_MODE | bots.safe_mode |
DAGU_BOTS_TELEGRAM_TOKEN | bots.telegram.token |
DAGU_BOTS_TELEGRAM_ALLOWED_CHAT_IDS | bots.telegram.allowed_chat_ids |
The environment variable takes precedence over the config file value for the token.
Finding your chat ID
Send a message to your bot, then call the Telegram API to see the chat.id:
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates" | jq '.result[0].message.chat.id'Telegram Commands
| Command | Behavior |
|---|---|
/start | Prints a welcome message listing available commands |
/new | Resets the chat state and clears the current agent session |
/cancel | Cancels the currently active agent session |
Any non-command text message is forwarded to the agent. If no session exists, one is created. If a session already exists, the message is sent to it.
Agent Prompts
When the agent asks the user a question (a UserPrompt), the bot renders it in Telegram:
- If the prompt has predefined options, they appear as inline keyboard buttons. Tapping a button submits that option.
- If the prompt allows free text (
AllowFreeText: true), the user can also reply with a regular text message. - If the prompt includes a
Commandfield, it is shown in the message as`command text`.
Only prompts that are currently pending in the session are shown. Prompts that were already answered are not re-displayed.
Session Rotation
When the current session is idle and has no pending prompt, Dagu checks the latest assistant-reported prompt token count. If it reaches 80% of the model context window, Dagu compacts the session. If the model does not declare a context window, Dagu uses a fallback of 200,000 tokens.
- Builds a transcript from prior user, assistant, error, and prompt messages.
- Asks the model for a handoff summary.
- Creates a continuation session and stores that summary as an assistant message prefixed with
Session handoff summary:\n. - Switches the chat to the new session.
The stored handoff summary is marked as already delivered for chat bridges, so Telegram does not replay it as a visible message.
DAG Run Notifications
When the centralized event store is available (the default in both server and start-all modes), the bot starts a DAG run monitor that reads persisted DAG-run events and sends notifications. If the event store is disabled or unavailable, Telegram chat works normally but DAG-run notifications stay disabled.
Monitored statuses
Notifications are sent for these DAG run statuses:
succeededfailedabortedpartially_succeededrejectedwaiting(for human approval requests)
How notifications work
- The monitor polls the event store every 10 seconds and reads only new DAG-run events, using durable on-disk state so restarts do not lose pending notifications.
- On first startup, it seeds its cursor at the current event-store head, so existing chats only receive future events.
- For each destination, it batches pending DAG-run notifications. Urgent single-run batches try to generate the message with the agent; all other batches use deterministic formatting. Batch delivery uses a 30-second flush timeout.
- The notification message is appended to the chat-scoped session. If the chat does not have an active session yet, Dagu creates an empty session first. Follow-up messages continue in that same chat session.
- Delivered entries are retained for 2 hours to suppress duplicate event replays, while failed deliveries remain pending and are retried.
Fallback
If the agent API is unavailable or times out, the bot sends a plain text fallback:
<emoji> DAG '<name>' <status>
Error: <error message if any>Where the emoji is: ✅ succeeded/partial, ❌ failed/rejected, ⚠️ aborted, ⏳ waiting.
Polling Behavior
The bot subscribes to agent session updates by polling GetSessionDetail. Polling starts at 1 second intervals. When there are no new messages and the agent is not working, the interval doubles up to 5 seconds. When new messages arrive, it resets to 1 second. Polling stops when the agent is not working and no new messages have appeared for 3+ consecutive polls.
