@smithers-orchestrator/telegramfor bots that run inside serverless functions, workflow tasks, or tests without owning a long-lived polling process (this page’s first half).@smithers-orchestrator/integrations/telegramfor workflows that wait on Telegram durably: listen for messages, and approve gated steps from the chat with inline buttons or a Mini App (Approve from the chat).
fetch
instead of Telegraf so Vercel Functions, Cloudflare Workers, and Sandbox tasks
can call the Bot API without starting a local polling loop.
Install
Send messages
createTelegramClient retries Bot API 429 and 5xx responses plus transient
network/read failures. 429 honors Telegram’s retry_after parameter; other
retryable failures use exponential backoff. Permanent 4xx responses are not
retried.
Verify webhooks
normalizeTelegramUpdate handles message, edited_message, channel_post,
and edited_channel_post updates and ignores bot-authored messages by default.
isTelegramChatAllowed follows Eliza’s fail-closed access-control shape:
missing or blank TELEGRAM_ALLOWED_CHATS allows all chats, a JSON array of chat
ids restricts processing to those ids, and malformed values block all chats until
the configuration is fixed.
Test with a fake
Approve from the chat
<Telegram.Approval> turns a workflow approval into inline Approve and Reject
buttons in a chat and resolves it from the button press, using the durable
long-poll source. No web server, no gateway wiring. The decision has the same
shape as the core <Approval> component:
{ approved, note, decidedBy, decidedAt }.
Register the two internal node schemas with telegramApprovalSchemas, then drop
the component in:
mode="select" with options;
the decision becomes { selected, notes }.
For the run to receive the press, a Telegram source must be polling. Run one
next to your workflow:
WaitForEvent wakes on the first callback query for the chat, so run one
interactive approval per chat at a time, or pass threadId (a forum topic) to
isolate concurrent approvals. Any chat member can press a button, so keep
approvals in a private or allowlisted chat.
Mini App approvals
For a richer decision (read a diff, pick an option, add a note) inside Telegram, add a Mini App button.miniApp opens a web_app page in the chat alongside the
plain buttons:
initData string. Your backend must verify it
before trusting the user. Never trust initDataUnsafe.
secret = HMAC_SHA256(key="WebAppData", message=botToken), and the data is authentic when
hex(HMAC_SHA256(key=secret, message=dataCheckString)) equals the hash field,
where dataCheckString is every field except hash, formatted key=value,
sorted, and newline-joined. It runs on Web Crypto, so the same call works in the
Smithers runtime and in a Cloudflare Worker. verifyTelegramWebAppInitDataSignature
verifies the newer Ed25519 signature from a third party with only the numeric
bot id.
A runnable reference (a static Mini App page plus a Worker endpoint that verifies
initData for real) ships in apps/telegram-site: site/approve.html and
src/handleApprove.ts.