On this page

On this page

Mainstream messaging

Telegram

This page connects a Telegram bot to OpenClaw and sets who is allowed to message it.

Telegram is production-ready for bot DMs and groups via grammY. Long polling is the default transport. Webhook mode is optional.

What each page covers

Where each section moved

Every section heading from the previous single-page version keeps its anchor here, so an existing link such as /channels/telegram#troubleshooting still resolves. Each entry points at the page that now holds the content.

Configuration reference

Primary reference: Configuration reference - Telegram.

openclaw doctor --fix removes retired tuning settings (timeoutSeconds, mediaGroupFlushMs, pollingStallThresholdMs, retry, and errorCooldownMs) from their former configuration scopes. Account names and sender-specific tool-policy keys are preserved, even when they match a retired setting name.

High-signal Telegram fields
  • startup/auth: enabled, botToken, tokenFile (must be a regular file; symlinks are rejected), accounts.*
  • access control: dmPolicy, allowFrom, direct.*.tools, direct.*.toolsBySender, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, top-level bindings[] (type: "acp")
  • group introductions: joinIntro, accounts.*.joinIntro (default: true)
  • topic defaults: groups.<chatId>.topics."*" applies to unmatched forum topics; exact topic IDs override it
  • exec approvals: execApprovals, accounts.*.execApprovals
  • command/menu: commands.native, commands.nativeSkills, customCommands
  • threading/replies: replyToMode, threadBindings
  • streaming: streaming (modes off | partial | block | progress), streaming.preview.toolProgress
  • formatting/delivery: textChunkLimit, streaming.chunkMode, richMessages, markdown.tables (off | bullets | code | block), linkPreview, responsePrefix
  • media/network: mediaMaxMb, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
  • custom API root: apiRoot (Bot API root only; do not include /bot<TOKEN>), trustedLocalFileRoots (self-hosted Bot API absolute file_path roots)
  • webhook: webhookUrl, webhookSecret, webhookPath, webhookCertPath, legacyWebhook (optional explicit forwarding endpoint; omitted or false uses only the Gateway port)
  • actions/capabilities: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker|createForumTopic|editForumTopic
  • reactions: reactionNotifications, reactionLevel
  • errors: errorPolicy, silentErrorReplies
  • writes/history: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

Multi-agent account ownership

Each Telegram account needs a resolvable agent owner. To bind the default account to main, add this entry to the top-level bindings array:

json5
{ agentId: "main", match: { channel: "telegram", accountId: "default" } }

Use the configured agent and account IDs for your Gateway. A missing owner leaves that account blocked with the exact binding remediation in channel status; other accounts keep running. Add the binding and restart the Gateway.

When upgrading a legacy agents.list config, Doctor preserves the previous implicit account owner in a binding before saving explicit ownership. Doctor requires the original roster and never promotes a narrower conversation route to account-wide ownership. Missing historical ownership requires an operator choice; Doctor reports the exact binding to add without changing existing routes. See migration repairs.

Was this useful?