Telegram Bot Integration for OpenClaw: Status and Access Control

Learn how to attach a Telegram bot to OpenClaw and control who can message it. Covers production readiness, long polling, webhook mode, and DM pairing defaults.

Read this when

  • Working on Telegram features or webhooks

This page explains how to attach a Telegram bot to OpenClaw and how to control who may send it messages.

For bot DMs and groups, Telegram is production-ready through grammY. The transport defaults to long polling. Webhook mode is available but not required.

What each page covers

Where each section moved

Anchors for all section headings from the earlier single-page version are preserved on this page, so links already in use, such as /channels/telegram#troubleshooting, still resolve. Every entry below leads to the page where that content now lives.

Configuration reference

For the authoritative settings list, see Configuration reference - Telegram.

openclaw doctor --fix strips retired tuning settings (timeoutSeconds, mediaGroupFlushMs, pollingStallThresholdMs, retry, and errorCooldownMs) out of the configuration scopes where they used to live. Account names and sender-specific tool-policy keys survive the cleanup, including any whose name happens to match a retired setting.

High-signal Telegram fields

  • startup/auth: enabled, botToken, tokenFile (a regular file is required; 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."*" is used for forum topics that match nothing else; an exact topic ID takes precedence over 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 (applies to the Bot API root only; leave out /bot<TOKEN>), trustedLocalFileRoots (absolute file_path roots for a self-hosted Bot API)
  • webhook: webhookUrl, webhookSecret, webhookPath, webhookCertPath, legacyWebhook (an optional endpoint for explicit forwarding; if omitted or set to false, only the Gateway port is used)
  • 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

mediaMaxMb accepts fractional limits. When a limit is too large, warnings show the effective limit in binary units, so mediaMaxMb: 0.5 is displayed as 512KB.

Note

Multi-account precedence: when two or more account IDs are configured, make default routing explicit by setting channels.telegram.defaultAccount (or by including channels.telegram.accounts.default). If you do not, OpenClaw falls back to the first normalized account ID and openclaw doctor warns. Account fields left out, namely dmPolicy, groupPolicy, allowFrom, and groupAllowFrom, inherit the channel root rather than accounts.default.*. Explicit account policies take priority; when neither scope sets them, DMs use pairing and groups use allowlist.

Multi-agent account ownership

Every Telegram account requires an agent owner that can be resolved. To bind the default account to main, append this entry to the top-level bindings array:

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

Use the agent and account IDs you configured for your Gateway. If the owner is missing, that account stays blocked, and channel status shows the exact binding remediation; the remaining accounts continue to run. Add the binding, then restart the Gateway.

When a legacy agents.list config is upgraded, Doctor keeps the previous implicit account owner in a binding before it saves explicit ownership. Doctor needs the original roster and never widens a narrower conversation route into account-wide ownership. If historical ownership is missing, the operator must choose; Doctor reports the exact binding to add and leaves existing routes untouched. See migration repairs.

1,046 words · updated Oct 25, 2026