Moltis
Features

Telegram

Moltis can connect to Telegram as a bot, letting you chat with your agent from any Telegram conversation. The integration uses Telegram’s Bot API with long polling — no public URL or webhook endpoint is required.

How It Works

┌──────────────────────────────────────────────────────┐
│                 Telegram Bot API                      │
│            (api.telegram.org/bot...)                  │
└──────────────────┬───────────────────────────────────┘
                   │  long polling (getUpdates)

┌──────────────────────────────────────────────────────┐
│              moltis-telegram crate                    │
│  ┌────────────┐  ┌────────────┐  ┌────────────────┐  │
│  │  Handler   │  │  Outbound  │  │     Plugin     │  │
│  │ (inbound)  │  │ (replies)  │  │  (lifecycle)   │  │
│  └────────────┘  └────────────┘  └────────────────┘  │
└──────────────────┬───────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│                 Moltis Gateway                        │
│         (chat dispatch, tools, memory)                │
└──────────────────────────────────────────────────────┘

The bot connects outward to Telegram’s servers via polling. No port forwarding, public domain, or TLS certificate is needed. This makes it easy to run on a home machine or behind a NAT.

Prerequisites

Before configuring Moltis, create a Telegram bot:

  1. Open Telegram and message @BotFather
  2. Send /newbot and follow the prompts to choose a name and username
  3. Copy the bot token (e.g. 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)

Configuration

Add a [channels.telegram.<account-id>] section to your moltis.toml:

[channels.telegram.my-bot]
token = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"

Make sure "telegram" is included in channels.offered so the Web UI shows the Telegram option:

[channels]
offered = ["telegram"]

Configuration Fields

FieldRequiredDefaultDescription
tokenyesBot token from @BotFather
dm_policyno"allowlist"Who can DM the bot: "open", "allowlist", or "disabled"
group_policyno"open"Who can talk to the bot in groups: "open", "allowlist", or "disabled"
mention_modeno"mention"When the bot responds in groups: "always", "mention" (only when @mentioned), or "none"
allowlistno[]User IDs or usernames allowed to DM the bot (when dm_policy = "allowlist")
group_allowlistno[]Group/chat IDs allowed to interact with the bot
modelnoOverride the default model for this channel
model_providernoProvider for the overridden model
agent_idnoDefault agent ID for this bot’s sessions
reply_to_messagenofalseSend bot responses as Telegram replies to the user’s message
otp_self_approvalnotrueEnable OTP self-approval for non-allowlisted DM users
otp_cooldown_secsno300Cooldown in seconds after 3 failed OTP attempts
stream_modeno"edit_in_place"Streaming mode: "edit_in_place" or "off"
edit_throttle_msno2000Minimum milliseconds between streaming edit updates
stream_notify_on_completenofalseSend the final answer as a notifying message instead of silently reusing the progress message
stream_min_initial_charsno30Minimum characters before sending the first temporary progress message
stream_progress_max_charsno3500Maximum recent progress characters kept visible in the temporary streamed message

Full Example

[channels]
offered = ["telegram"]

[channels.telegram.my-bot]
token = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
dm_policy = "allowlist"
group_policy = "open"
mention_mode = "mention"
allowlist = ["123456789", "alice_username"]
group_allowlist = ["-1001234567890"]
reply_to_message = true
model = "claude-sonnet-4-20250514"
model_provider = "anthropic"
agent_id = "research"
otp_self_approval = true
stream_mode = "edit_in_place"
edit_throttle_ms = 2000

Per-User and Per-Channel Model and Agent Overrides

You can override the model or agent for specific users or group chats:

[channels.telegram.my-bot]
token = "..."
model = "claude-sonnet-4-20250514"
model_provider = "anthropic"

[channels.telegram.my-bot.channel_overrides."-1001234567890"]
model = "gpt-4o"
model_provider = "openai"
agent_id = "triage"

[channels.telegram.my-bot.user_overrides."123456789"]
model = "claude-opus-4-20250514"
model_provider = "anthropic"
agent_id = "research"

User overrides take priority over channel overrides, which take priority over the account default, for both model selection and agent selection.

Access Control

Telegram uses the same gating system as Discord and other channels.

DM Policy

Controls who can send direct messages to the bot.

ValueBehavior
"allowlist"Only users listed in allowlist can DM (default)
"open"Anyone who can find the bot can DM it
"disabled"DMs are silently ignored

Group Policy

Controls who can interact with the bot in group chats.

ValueBehavior
"open"Bot responds in any group (default)
"allowlist"Only groups listed in group_allowlist are allowed
"disabled"Group messages are silently ignored

Mention Mode

Controls when the bot responds in groups (does not apply to DMs).

ValueBehavior
"mention"Bot only responds when @mentioned (default)
"always"Bot responds to every message in allowed groups
"none"Bot never responds in groups (useful for DM-only bots)

Allowlist Matching

Allowlist entries support:

  • Exact match (case-insensitive): "alice", "123456789"
  • Glob wildcards: "admin_*", "*_bot", "user_*_vip"

Both the user’s numeric Telegram ID and their username are checked against the allowlist. For example, if a user has ID 123456789 and username alice, either "123456789" or "alice" in the allowlist grants access.

OTP Self-Approval

When dm_policy = "allowlist" and otp_self_approval = true (the default), unknown users who DM the bot receive a verification challenge:

  1. User sends a DM to the bot
  2. Bot responds with a challenge prompt (the 6-digit code is not shown to the user)
  3. The code appears in the Moltis web UI under Channels > Senders
  4. The bot owner shares the code with the user out-of-band
  5. User replies with the 6-digit code
  6. On success, the user is automatically added to the allowlist

After 3 failed attempts, the user is locked out for otp_cooldown_secs seconds (default: 300). Codes expire after 5 minutes.

Set otp_self_approval = false if you want to manually approve every user from the web UI.

Streaming

By default (stream_mode = "edit_in_place"), Telegram shows temporary progress while a turn is running. The bot sends a silent progress message after stream_min_initial_chars characters (default: 30), edits that progress message at most once every edit_throttle_ms milliseconds (default: 2000), and keeps only the latest stream_progress_max_chars progress characters visible.

When the final answer is ready, the progress message is cleaned up or reused and the final answer is delivered separately from intermediate progress. With stream_notify_on_complete = false (default), Moltis may silently reuse the existing progress message for the final answer. With stream_notify_on_complete = true, Moltis deletes the progress message where possible and sends the final answer as a new notifying message.

Session Commands

Telegram supports the standard channel session commands:

CommandDescription
/newStart a fresh session for the current chat
/sessionsList or switch among sessions already bound to the current chat
/attachList existing non-cron sessions and rebind one to the current chat
/agentList or switch chat agents
/modeList or switch temporary session modes
/modelList or switch models
/approvalsList pending exec approvals for the current session
/approve NApprove the numbered exec request from /approvals
/deny NDeny the numbered exec request from /approvals

/sessions is intentionally scoped to the current chat. If you want to bring a different existing session into the chat, use /attach instead. Reattaching a session moves that session’s channel binding to the current chat, it is not a copy.

Set stream_mode = "off" to disable streaming and send the full response as a single message.

When stream_notify_on_complete = true, the bot sends a short non-silent message after streaming finishes. This can trigger a Telegram push notification on the user’s device (since silent edits don’t always trigger notifications).

Finding Your Telegram User ID

To find your numeric Telegram user ID (for the allowlist):

  1. Message @userinfobot on Telegram
  2. It replies with your user ID, first name, and username
  3. Use the numeric ID as a string in your config: allowlist = ["123456789"]

Alternatively, use your Telegram username (without the @): allowlist = ["your_username"].

Web UI Setup

You can also configure Telegram through the web interface:

  1. Open Settings > Channels
  2. Click Connect Telegram
  3. Enter an account ID (any alias) and your bot token
  4. Adjust DM policy, mention mode, and allowlist as needed
  5. Click Connect

The same form is available during onboarding when Telegram is in channels.offered.

Troubleshooting

Bot doesn’t respond

  • Verify the bot token is correct (ask @BotFather for /token if unsure)
  • Check dm_policy — if set to "allowlist", make sure your user ID or username is listed in allowlist
  • An empty allowlist with dm_policy = "allowlist" blocks all DMs
  • Check group_policy — if "disabled", group messages are ignored
  • Look at logs: RUST_LOG=moltis_telegram=debug moltis

”allowed_users” doesn’t work

The field name is allowlist, not allowed_users. If you’re migrating from OpenClaw, note that the field was renamed. Values must also be strings (e.g. ["123456789"]), not integers.

Bot responds to everyone

  • Check that dm_policy = "allowlist" is set (it’s the default)
  • Verify you have entries in allowlist — an empty allowlist with dm_policy = "allowlist" blocks everyone, but dm_policy = "open" allows everyone

Bot doesn’t respond in groups

  • Check mention_mode — if set to "mention", you must @mention the bot
  • Check group_policy — if "disabled", group messages are ignored
  • Check group_allowlist — if non-empty, the group must be listed