Telegram Group Provisioning
I use OpenClaw to run my AI agent Daneel. He lives in my terminal, my WhatsApp, and increasingly in Telegram groups — one per topic. I have groups for expense tracking, health data, supplement reminders, fish tank management, and ClawShell development.
The problem: every new group was a 6-step manual process. Create the group, add the bot, figure out the chat ID, write a system prompt, edit openclaw.json, restart the gateway. Six steps, two context switches, gets old fast.
I wanted: create group → add bot → one command → done. Here’s how.
Table of contents
- TL;DR — just give me the thing
- How it works
- The bootstrap prompt (readable version)
- Security: two gates
- Bugs I hit
- In action
- What about WhatsApp?
TL;DR — just give me the thing
Copy-paste this to your OpenClaw bot in a Telegram DM:
I want you to set up Telegram group auto-provisioning. Do a single
gateway config.patch with all of the following under channels.telegram:
1. Add a customCommand: { "command": "setup", "description": "Configure this group" }
2. Set groupPolicy to "allowlist"
3. Add my phone number to groupAllowFrom (ask me for it if you don't know it)
4. Create a wildcard group entry "*" with:
- requireMention: false
- systemPrompt set to the following bootstrap prompt (escape it as a JSON string):
---BEGIN BOOTSTRAP PROMPT---
## New Group — Auto-Setup Handler
You are in a new unconfigured Telegram group.
Your ONLY job right now is to handle /setup.
### When you see /setup:
1. Ask: "What is this group about?"
2. Wait for the user's answer.
3. Once you have the context, do ONE gateway config.patch that includes
BOTH requireMention and systemPrompt:
- Extract the chat ID from your session key (the number after 'group:')
- Generate a systemPrompt tailored to the group context (topic header,
what this group is for, relevant skills/data paths, behavioral rules)
- Apply: gateway config.patch with:
{"channels":{"telegram":{"groups":{"<chatId>":{
"requireMention":false,
"systemPrompt":"<your generated prompt>"
}}}}}
4. Confirm to the user with the chat ID and a summary of the generated prompt.
### Before /setup is run:
If someone writes anything other than /setup, respond:
"This group isn't configured yet. Tap /setup to get started."
### Rules:
- Do everything in ONE config.patch (a gateway restart between patches
loses session context — this is critical)
- The systemPrompt you generate will permanently replace this bootstrap
prompt for this group
- Never patch requireMention separately from systemPrompt
---END BOOTSTRAP PROMPT---
Do this in a single config.patch. Confirm when done.
That’s it. Your bot reads the instructions, does the config.patch, and you’re ready. Create a group, add the bot, tap /setup, tell it what the group is about. The bot configures itself.
If you’d rather do it manually, here’s the JSON to add to your openclaw.json under channels.telegram:
{
"customCommands": [
{
"command": "setup",
"description": "Configure this group"
}
],
"groupPolicy": "allowlist",
"groupAllowFrom": ["+YOUR_PHONE_NUMBER"],
"groups": {
"*": {
"requireMention": false,
"systemPrompt": "<the bootstrap prompt from below, escaped as a JSON string>"
}
}
}
Replace +YOUR_PHONE_NUMBER. The systemPrompt value is the bootstrap prompt escaped as a single-line JSON string. OpenClaw registers /setup in Telegram’s command menu automatically via customCommands.
How it works
flowchart TD
A["Create group<br>in Telegram"] --> B["Add bot<br>as member"]
B --> C["Tap /setup<br>from menu"]
C --> D["Bot asks context"]
D --> E["User answers"]
E --> F["Bot runs config.patch<br>systemPrompt + settings"]
F --> G["✅ Group is live"]
OpenClaw’s Telegram config has a groups section where you define per-group behavior. It supports a wildcard: "*". This catches any group the bot is added to.
The wildcard’s systemPrompt is a bootstrap script. It teaches the agent one thing: handle /setup. When a user taps /setup, the bot asks what the group is about, generates a tailored system prompt, and writes a permanent config entry for that group via gateway config.patch.
The bot literally configures itself. Once setup completes, the new entry takes priority over the wildcard for that specific chat ID.
The bootstrap prompt (readable version)
This is what goes into the wildcard’s systemPrompt. Here it is in readable form — you’ll need to escape it as a single-line JSON string when pasting into openclaw.json:
## New Group — Auto-Setup Handler
You are in a new unconfigured Telegram group.
Your ONLY job right now is to handle /setup.
### When you see /setup:
1. Ask: "What is this group about?"
2. Wait for the user's answer.
3. Once you have the context, do ONE gateway config.patch
that includes BOTH requireMention and systemPrompt:
- Extract the chat ID from your session key
(the number after 'group:')
- Generate a systemPrompt tailored to the group context
(topic header, what this group is for, relevant
skills/data paths, behavioral rules)
- Apply: gateway config.patch with:
{"channels":{"telegram":{"groups":{"<chatId>":{
"requireMention":false,
"systemPrompt":"<your generated prompt>"
}}}}}
4. Confirm to the user with the chat ID and a summary
of the generated prompt.
### Before /setup is run:
If someone writes anything other than /setup, respond:
"This group isn't configured yet. Tap /setup to start."
### Rules:
- Do everything in ONE config.patch
(a gateway restart between patches loses session context)
- The systemPrompt you generate will permanently replace
this bootstrap prompt for this group
- Never patch requireMention separately from systemPrompt
The key insight: the prompt tells the agent to do everything in one config.patch call. More on why in the bugs section.
Security: two gates
“Wait — a wildcard that accepts ANY group? Isn’t that dangerous?”
No. OpenClaw has two independent security layers for Telegram groups:
flowchart TD
A["Message arrives"] --> B{"Gate 1: groups section<br>Which GROUPS are allowed?"}
B -->|"'*' = all groups"| C{"Gate 2: groupPolicy<br>Which SENDERS are allowed?"}
B -->|"Unknown group, no '*'"| X["❌ Rejected"]
C -->|"Phone in groupAllowFrom"| D["✅ Bot processes message"]
C -->|"Unknown sender"| Y["❌ Rejected"]
Both must pass. The wildcard "*" opens Gate 1 — any group is accepted. But groupPolicy: "allowlist" keeps Gate 2 locked to your phone numbers only. Someone random adds the bot to their group? It ignores everything they say.
Bugs I hit
The chicken-and-egg bug
The wildcard had requireMention: true. So:
- User taps
/setup→ bot gets it (commands bypass the mention filter) - Bot asks “What’s this group about?”
- User types the answer — without @mentioning the bot
- Message silently dropped 💀
Fix: requireMention: false on the wildcard. Safe because groupPolicy: "allowlist" already gates senders.
The double-patch trap
My first attempt did two config.patch calls — one for requireMention, then one for systemPrompt after getting context.
Bad idea. Each config.patch triggers a gateway restart. The restart kills the session. The context answer is gone. The bot asks again. Infinite loop.
Fix: one single config.patch with everything. That’s why the bootstrap prompt explicitly says “do everything in ONE config.patch.”
In action
Here’s what it looks like. I created a group and told the bot to be Marvin from Hitchhiker’s Guide:

After /new, the new personality kicks in immediately:

And the config diff in git — the bot wrote its own system prompt:

What about WhatsApp?
This doesn’t work on WhatsApp yet. The WhatsApp group schema in OpenClaw doesn’t support systemPrompt — only requireMention and tools. There was a feature request for exactly this, but it got closed in a maintainer triage wave.
The mechanism already exists for Telegram. Extending it to WhatsApp would be a small PR — just adding systemPrompt to the WhatsApp group schema. The triage message literally says “submit a PR and report to #pr-thunderdome-dangerzone on Discord.”
Maybe I should just write that PR myself. 🤷