OpenClaw Manual OpenClaw
Integrations 10 min read

Complete Guide to OpenClaw Telegram Integration

Learn how to create a Telegram bot and connect it to OpenClaw. Full tutorial covering bot creation, configuration, commands, and group chat setup.

O

OpenClaw Manuals

Tutorial Authors

Overview

Telegram integration lets you interact with OpenClaw through a dedicated Telegram bot. OpenClaw uses the grammY framework for long-polling by default, with optional webhook support for production deployments.

Prerequisites

  • OpenClaw installed and running
  • A Telegram account

Step 1: Create a Telegram Bot

Talk to BotFather

  1. Open Telegram and search for @BotFather
  2. Start a chat and send /newbot
  3. Follow the prompts:
You: /newbot

BotFather: Alright, a new bot. How are we going to call it?
           Please choose a name for your bot.

You: My OpenClaw Assistant

BotFather: Good. Now let's choose a username for your bot.
           It must end in `bot`. Like this, for example:
           TetrisBot or tetris_bot.

You: myopenclaw_bot

BotFather: Done! Congratulations on your new bot. You will find it at
           t.me/myopenclaw_bot. You can now add a description, about
           section and profile picture for your bot.

           Use this token to access the HTTP API:
           123456789:ABCdefGHIjklMNOpqrsTUVwxyz

           Keep your token secure and store it safely.

Save the bot token — you'll need it in the next step.

If you plan to use the bot in group chats, disable privacy mode so it can read all messages:

/setprivacy
@myopenclaw_bot
Disable

After changing privacy mode, you must remove and re-add the bot to existing groups for the change to take effect. Alternatively, promote the bot to group admin — admin bots always receive all messages.

Step 2: Configure OpenClaw

Token Storage

You can store the bot token in two ways. Config takes precedence over the environment variable.

Option A — Environment variable:

bash
# Add to ~/.openclaw/.env
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz

Option B — Direct in config:

json5
// ~/.openclaw/openclaw.json
{
  channels: {
    telegram: {
      botToken: "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
    }
  }
}

Minimal Configuration

Edit ~/.openclaw/openclaw.json :

json5
{
  channels: {
    telegram: {
      // Token from env TELEGRAM_BOT_TOKEN or set botToken directly
    }
  }
}

That's all you need — OpenClaw starts long-polling automatically when a Telegram channel is configured.

Step 3: Test Your Bot

  1. Open Telegram and search for your bot username
  2. Start a chat with /start
  3. Send any message to test

Access Control — DM Policy

Control who can message your bot in private chats via dmPolicy :

| Policy | Behavior | |--------|----------| | "pairing" (default) | Unknown senders get an expiring pairing code; you approve via CLI | | "allowlist" | Only user IDs / @usernames in allowFrom can message | | "open" | Anyone can message the bot | | "disabled" | DMs are turned off entirely |

Pairing Mode (Default)

When a new user messages the bot, they receive a pairing code. Approve it with:

bash
# List pending pairing requests
openclaw pairing list telegram

# Approve a specific code
openclaw pairing approve telegram 

Pairing codes expire after 1 hour.

Allowlist Mode

json5
{
  channels: {
    telegram: {
      dmPolicy: "allowlist",
      allowFrom: [123456789, "@trusted_user"]
    }
  }
}

Open Mode

json5
{
  channels: {
    telegram: {
      dmPolicy: "open"
    }
  }
}

Group Chat Support

Enable Group Access

Add group IDs to the groups object. Use "*" to allow all groups:

json5
{
  channels: {
    telegram: {
      groups: {
        "-1001234567890": {},           // specific group with defaults
        "-1009876543210": {             // specific group with overrides
          groupPolicy: "open",
          requireMention: false,
          systemPrompt: "You are a helpful coding assistant."
        }
      }
    }
  }
}

Or allow all groups:

json5
{
  channels: {
    telegram: {
      groups: "*"
    }
  }
}

Group Policy

Control who can interact with the bot within groups:

| Setting | Description | |---------|-------------| | groupPolicy: "open" | Any group member can message the bot | | groupPolicy: "allowlist" | Only senders in groupAllowFrom can interact | | groupPolicy: "disabled" | Bot ignores all group messages |

json5
{
  channels: {
    telegram: {
      groupPolicy: "allowlist",
      groupAllowFrom: [123456789, "@allowed_user"]
    }
  }
}

Mention Requirement

By default, the bot requires an @mention in groups. You can change this per-group:

json5
{
  channels: {
    telegram: {
      groups: {
        "-1001234567890": {
          requireMention: false   // bot responds to all messages
        }
      }
    }
  }
}

Or use the session-only command /activation always in the group chat.

Per-Group Overrides

Each group entry supports these fields:

| Field | Description | |-------|-------------| | groupPolicy | Override the global group policy | | requireMention | Whether @mention is required | | skills | Skills available in this group | | allowFrom | Sender allowlist for this group | | systemPrompt | Custom system prompt for this group | | enabled | Enable/disable for this specific group |

Message Format & Chunking

HTML Parse Mode

OpenClaw sends messages using Telegram's HTML parse mode (not Markdown). Markdown from the LLM is automatically converted to HTML-safe tags. If Telegram rejects the HTML, the message is retried as plain text.

Text Chunking

Long messages are split into multiple Telegram messages:

json5
{
  channels: {
    telegram: {
      textChunkLimit: 4000,    // max chars per message (default: 4000)
      chunkMode: "newline"     // "length" (default) or "newline"
    }
  }
}
  • "length" — splits at the character limit
  • "newline" — splits at paragraph boundaries before applying the length limit

Media Handling

Media Size Limit

json5
{
  channels: {
    telegram: {
      mediaMaxMb: 5    // max file size in MB (default: 5)
    }
  }
}

Stickers

  • Static stickers (WEBP) are processed through vision and described to the LLM
  • Animated / video stickers are skipped
  • Sticker descriptions are cached in ~/.openclaw/telegram/sticker-cache.json to avoid redundant vision calls

To enable the bot to send stickers:

json5
{
  channels: {
    telegram: {
      actions: {
        sticker: true    // default: false
      }
    }
  }
}

History & Context

json5
{
  channels: {
    telegram: {
      historyLimit: 50,        // group context (default: 50)
      dmHistoryLimit: 100      // DM context
    }
  }
}

Per-user DM override:

json5
{
  channels: {
    telegram: {
      dms: {
        "123456789": {
          historyLimit: 200
        }
      }
    }
  }
}

Set to 0 to disable history.

Streaming

OpenClaw supports draft-based streaming in private chats (with forum topics enabled):

| Setting | Description | |---------|-------------| | streamMode: "off" | Streaming disabled (default) | | streamMode: "partial" | Continuous updates to a draft message | | streamMode: "block" | Chunked updates to a draft message |

Block mode settings:

json5
{
  channels: {
    telegram: {
      streamMode: "block",
      draftChunk: {
        minChars: 200,
        maxChars: 800,
        breakPreference: "paragraph"
      }
    }
  }
}

Webhook Mode (Production)

For production deployments, use webhooks instead of long-polling:

json5
{
  channels: {
    telegram: {
      webhookUrl: "https://your-domain.com/telegram-webhook",
      webhookSecret: "your-random-secret-string",
      webhookPath: "/telegram-webhook"    // local path, default: /telegram-webhook
    }
  }
}

The webhook listener binds to 0.0.0.0:8787 . When webhookUrl is set, OpenClaw automatically switches from polling to webhook mode.

Commands

Native Commands

OpenClaw registers these commands with Telegram's bot menu on startup:

| Command | Description | |---------|-------------| | /start | Welcome message | | /status | Show bot status | | /reset | Reset conversation | | /model | Show / switch model |

Custom Commands

Add menu entries via config (menu-only — they don't execute unless handled elsewhere):

json5
{
  channels: {
    telegram: {
      customCommands: [
        { command: "weather", description: "Get weather forecast" },
        { command: "translate", description: "Translate text" }
      ]
    }
  }
}

Command names must be lowercase a-z0-9_ , 1–32 characters. Leading / is stripped automatically. Cannot override native commands.

Inline Buttons

Control inline button availability:

| Setting | Scope | |---------|-------| | capabilities.inlineButtons: "off" | Disabled | | capabilities.inlineButtons: "dm" | DMs only | | capabilities.inlineButtons: "group" | Groups only | | capabilities.inlineButtons: "all" | Both DMs and groups | | capabilities.inlineButtons: "allowlist" | Both + sender filtering (default) |

Network & Proxy

json5
{
  channels: {
    telegram: {
      timeoutSeconds: 500,        // Bot API request timeout (default: 500)
      network: {
        autoSelectFamily: false   // disable Happy Eyeballs (default on Node 22)
      },
      proxy: "socks5://127.0.0.1:1080"   // SOCKS/HTTP proxy for Bot API
    }
  }
}

Troubleshooting

Bot Not Responding

  1. Verify token is correct:
bash
curl "https://api.telegram.org/bot/getMe"
  1. Check OpenClaw logs:
bash
openclaw logs --follow

Messages Not Reaching in Groups

  • Privacy mode must be disabled ( /setprivacy → Disable) or bot must be admin
  • Test with /activation always (session-only); persist via requireMention: false in config

IPv6 Routing Failures

The bot may silently stop responding if IPv6 routing fails. Check DNS for api.telegram.org :

bash
dig api.telegram.org AAAA

Fix by enabling IPv6 egress or forcing IPv4:

bash
# Add to /etc/hosts
149.154.167.220  api.telegram.org

Or use the network config:

json5
{
  channels: {
    telegram: {
      network: {
        autoSelectFamily: false
      }
    }
  }
}

Long-Polling Aborts (Node 22+)

Node 22 is stricter with AbortSignal instances. Upgrade OpenClaw to the latest version or downgrade to Node 20.

setMyCommands Failures

Outbound HTTPS/DNS to api.telegram.org may be blocked. Check your firewall rules.

Security Best Practices

  1. Never share your bot token — revoke immediately via BotFather if compromised
  2. Use pairing or allowlist for DM access control
  3. Set group policies to control who can interact in groups
  4. Find user IDs safely via openclaw logs --follow or the Bot API getUpdates endpoint — avoid third-party ID bots
  5. Use webhooks with a secret for production deployments

Next Steps