Set up Telegram
Telegram needs one Bot API token for triggers, messages, approvals, and lifecycle notifications. It does not need an app token or a public callback URL; WOML receives messages through long polling.
Create the bot
- Open Telegram and start a conversation with the verified @BotFather account.
- Send
/newbot. - Choose a display name.
- Choose a unique username ending in
bot, such asmy_woml_bot. - Copy the Bot API token returned by BotFather. Treat it like a password.
Store and verify the token
woml secrets set TELEGRAM_BOT_TOKEN
woml telegram doctorThe doctor command verifies that Telegram accepts the token without exposing it in workflow source or terminal output.
Test a Telegram trigger and reply
Save this as telegram-test.woml:
<woml>
<workflow
id="telegram-test"
name="Telegram Test"
description="Replies to every message received by the bot."
version="1.0.0"
>
<triggers>
<telegram
id="messageReceived"
events="message"
bot-token="{{secrets.TELEGRAM_BOT_TOKEN}}"
/>
</triggers>
<steps>
<step id="reply" name="Reply in Telegram">
<script>
return services.telegram.send({
botToken: secrets.TELEGRAM_BOT_TOKEN,
conversationId: context.payload.conversationId,
replyToMessageId: context.payload.messageId,
text: `WOML received: ${context.payload.text}`
}, { name: "telegram-test-reply" });
</script>
</step>
</steps>
</workflow>
</woml>Run it:
woml check telegram-test.woml
woml run telegram-test.womlOpen the bot in Telegram, press Start or send /start, then send hello. WOML should accept the message and the bot should reply with WOML received: hello.
The run output includes the normalized conversationId. Use that numeric value as a notification destination. You can verify it before using approvals:
woml telegram doctor --destination <conversationId>An approval notification then looks like this:
<approval id="review" timeout="24h" on-timeout="reject">
<notify>
<telegram
chats="<conversationId>"
bot-token="{{secrets.TELEGRAM_BOT_TOKEN}}"
/>
</notify>
<when-approved />
<when-rejected />
</approval>For groups and channels, the ID is commonly negative. Copy the exact value; do not remove the minus sign.
Configure group messages when needed
Telegram bots use privacy mode in groups by default. In that mode they receive commands, replies directed to them, and other explicitly relevant messages, but not every ordinary group message. If the workflow genuinely needs all group messages:
- Open BotFather and send
/setprivacy. - Select the bot and disable privacy mode.
- Remove and re-add the bot to the group so Telegram applies the change.
Only disable privacy when the automation requires it; narrower access is safer and less noisy.
Diagnose Telegram setup failures
Unauthorized: replaceTELEGRAM_BOT_TOKENwith the current BotFather token.- Nothing happens in a private chat: press Start first; bots cannot begin a conversation with a user.
- The trigger repeatedly rejects the same update: stop other processes using the same bot token. Only one long-polling consumer should own that bot.
- Group messages are missing: mention/reply to the bot or review privacy mode.
- Notification delivery fails: verify the numeric chat ID with
woml telegram doctor --destination ...and make sure the bot is still a member of the group or channel.