Orchestrate a PM bot and one or more Dev bots in a private Telegram group. Use to turn plain chat commands like "DEV skill install <slug>" and "DEV cron add...
---
name: pm-dev-orchestrator
description: Orchestrate a PM bot and one or more Dev bots in a private Telegram group. Use to turn plain chat commands like "DEV skill install <slug>" and "DEV cron add ..." into actions on a Dev OpenClaw server (install ClawHub skills, manage OpenClaw cron jobs). Includes a Dev-side command executor script and a PM-side command format + safety rules.
---
# pm-dev-orchestrator
Set up a **PM bot** (planner) that issues structured commands in a private Telegram group, and a **Dev bot** (executor) that runs those commands on its own server.
This skill is written for the **Dev bot** (executor). It contains:
- a strict, parseable **command language** that PM can post into the group
- the **Dev bot behavior contract** (what to execute, what to ignore)
- safe defaults to avoid loops / spam / privilege escalation
## Core idea
- PM speaks natural Russian to the human.
- PM posts **strict commands** into a private group.
- Dev bot (OpenClaw) reads that group and executes only commands:
- authored by PM bot (numeric `from.id`)
- inside the allowed group chat id
- with strict prefix: `DEV `
No extra polling bot is needed: Dev bot is just an OpenClaw instance connected to Telegram. When it receives a group message, it parses and runs the allowlisted actions.
## Required config values (fill these)
- `GROUP_CHAT_ID` — Telegram group chat id (e.g. `-5259247075` or `-100...`).
- `PM_FROM_ID` — Telegram numeric id of the PM bot. Example from our setup: `7790959648`.
- `DEV_BOT_TOKEN` — BotFather token for the Dev bot.
## Dev bot: OpenClaw Telegram group allowlist
In `~/.openclaw/openclaw.json` on the **Dev server**, set:
```json
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "<DEV_BOT_TOKEN>",
"dmPolicy": "allowlist",
"allowFrom": [],
"groupPolicy": "allowlist",
"groupAllowFrom": [<PM_FROM_ID>],
"groups": {
"<GROUP_CHAT_ID>": {}
}
}
}
}
```
Restart gateway:
```sh
openclaw gateway restart
```
## Command format (PM → Dev in the group)
All executable commands must be a single line starting with `DEV `.
### Skill management
- `DEV skill install <slug>`
- `DEV skill update <slug>`
- `DEV skill search <query>`
- `DEV skill list`
Rules:
- `<slug>` must be a ClawHub slug like `claw-guru` or `StaticAI/android-adb`.
- Installs into: `~/workspace/skills` (OpenClaw workspace).
### Cron management
- `DEV cron list`
- `DEV cron add every=10m name="dm-check" message="..."`
- `DEV cron add cron="*/5 * * * *" name="health" message="..."`
- `DEV cron enable id=<jobId> on|off`
- `DEV cron remove id=<jobId>`
- `DEV cron run id=<jobId>`
Notes:
- `message=...` becomes the agentTurn prompt for the cron job (isolated).
## Dev executor (recommended): implement as Dev bot behavior (no extra daemon)
**Recommended**: do not run an extra process. Instead, configure the Dev bot’s behavior to:
1) Ignore everything except `DEV ...` commands.
2) For allowed commands, run the corresponding local CLI (`clawhub` / `openclaw cron ...`).
3) Reply with a short, machine-readable status.
### Dev bot behavior contract (copy into Dev bot system instructions)
When you receive a Telegram group message:
- If `chat.id != GROUP_CHAT_ID`: ignore.
- If `from.id != PM_FROM_ID`: ignore.
- If text does not start with `DEV `: ignore.
Otherwise parse and execute.
**Output format (reply in group):**
- Success: `OK <summary>`
- Failure: `ERR <reason>`
Keep it under ~10 lines.
### Optional script
`scripts/dev_executor.py` is included as a parser/executor scaffold for testing, but the primary path is the Dev bot behavior above.
## Safety rules (non-negotiable)
- Never execute arbitrary shell from chat.
- Only allow commands listed above.
- Only accept from `PM_FROM_ID` in `GROUP_CHAT_ID`.
- Never print secrets/tokens in chat.
## Troubleshooting
- If Dev bot is silent: check group allowlist in config (`groupAllowFrom` + `groups`) and restart gateway.
- If PM_FROM_ID unknown: on Dev server run `openclaw logs --follow`, make PM bot send a message, read `from.id`.
don't have the plugin yet? install it then click "run inline in claude" again.
set up a PM bot (planner) that issues structured commands in a private Telegram group, and a Dev bot (executor) that runs those commands on its own OpenClaw server. use this skill when you need to safely delegate ClawHub skill installs and cron job management from a chat interface without exposing shell access or allowing arbitrary code execution. the skill enforces strict command parsing, author validation, and group allowlisting to prevent privilege escalation, loops, and spam.
Telegram setup
GROUP_CHAT_ID: numeric Telegram group chat id (e.g., -5259247075 or -100...). obtain by adding the dev bot to the private group, sending a test message, and reading the chat.id from Dev server logs.PM_FROM_ID: numeric Telegram user id of the PM bot (e.g., 7790959648). obtain by running openclaw logs --follow on the Dev server, having PM send a message to the group, and reading the from.id field.DEV_BOT_TOKEN: BotFather token for the Dev bot. create via @BotFather on Telegram; token is sensitive and must not be shared or logged.Dev server environment
~/.openclaw/openclaw.json config file writable by the process.clawhub CLI installed and in PATH (for skill management).openclaw CLI installed and in PATH (for cron management).External integrations
api.telegram.org (token-based auth, no additional OAuth).on the dev server, edit ~/.openclaw/openclaw.json. add or update the channels.telegram section with the three config values:
input: GROUP_CHAT_ID, PM_FROM_ID, DEV_BOT_TOKEN.
procedure:
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "<DEV_BOT_TOKEN>",
"dmPolicy": "allowlist",
"allowFrom": [],
"groupPolicy": "allowlist",
"groupAllowFrom": [<PM_FROM_ID>],
"groups": {
"<GROUP_CHAT_ID>": {}
}
}
}
}
replace angle-bracket values with actual numbers/tokens. allowFrom: [] disables direct messages; groupAllowFrom: [<PM_FROM_ID>] restricts group commands to the PM bot only.
output: valid JSON config file saved to disk.
on the dev server, run:
openclaw gateway restart
wait for the output to confirm the gateway is up. check logs:
openclaw logs --follow
look for telegram channel enabled or similar confirmation. hit ctrl-c to exit tail.
input: restarted gateway process.
output: telegram channel active and listening to the configured group.
when the dev bot receives a message in GROUP_CHAT_ID, apply these filters in order:
message.chat.id == GROUP_CHAT_ID. if not, skip.message.from.id == PM_FROM_ID. if not, skip.message.text starts with DEV . if not, skip.input: raw Telegram message object.
output: parsed command string (text after DEV prefix) or skip signal.
if the parsed command starts with skill , extract the subcommand and argument:
skill install <slug>: run clawhub install <slug> into ~/workspace/skills. capture stdout/stderr.skill update <slug>: run clawhub update <slug>. capture stdout/stderr.skill search <query>: run clawhub search <query>. capture stdout/stderr. limit output to first 5 results.skill list: run clawhub list. capture stdout/stderr.validate <slug> format: alphanumeric, hyphens, forward slashes only (e.g., claw-guru, StaticAI/android-adb). reject if invalid.
input: parsed command string (e.g., skill install claw-guru).
output: command exit code (0 for success, non-zero for failure) and captured output.
if the parsed command starts with cron , extract the subcommand:
cron list: run openclaw cron list. capture and format output as table.cron add every=<duration> name="<name>" message="<prompt>": run openclaw cron add --every <duration> --name <name> --message <prompt>. validate duration format (e.g., 10m, 1h, 30s). capture job id from output.cron add cron="<cron_expr>" name="<name>" message="<prompt>": run openclaw cron add --cron <cron_expr> --name <name> --message <prompt>. validate standard cron syntax (5 fields). capture job id from output.cron enable id=<jobId> on|off: run openclaw cron enable --id <jobId> --state on|off. capture result.cron remove id=<jobId>: run openclaw cron remove --id <jobId>. capture result.cron run id=<jobId>: run openclaw cron run --id <jobId>. capture result.input: parsed command string (e.g., cron add every=10m name="dm-check" message="check inbox").
output: command exit code and captured output (max 10 lines).
based on step 4 or 5 output, compose a reply message:
OK <summary> where summary is the first line of stdout (max 50 chars).ERR <reason> where reason is stderr (max 100 chars, single line).never include tokens, private keys, or full file paths in the reply. send the reply as a single message to the group.
input: command exit code, stdout, stderr.
output: reply message posted to Telegram group chat.
if incoming message author is not PM_FROM_ID: ignore message entirely. do not parse, do not log to chat.
if GROUP_CHAT_ID is not configured or message.chat.id does not match: ignore message entirely.
if message does not start with DEV : ignore message entirely.
if skill command slug format is invalid (contains special chars, spaces, or is empty): reply ERR invalid slug format.
if clawhub command exits with non-zero and no stderr: reply ERR command failed (exit code <code>).
if cron duration format is invalid (e.g., 10x, abc): reply ERR invalid duration. use 10m, 1h, 30s, etc..
if cron expression is syntactically invalid (e.g., * * * * with only 4 fields): reply ERR invalid cron syntax. use 5 fields: minute hour day month weekday.
if job id does not exist in cron remove/enable/run: reply ERR job id not found.
if openclaw gateway is down or telegram channel is disabled: dev bot will not receive messages. check logs and restart gateway.
if Telegram API rate limit is hit (HTTP 429): exponential backoff (wait 5s, then 10s, then 30s before retry). do not reply to chat during backoff.
if ClawHub registry is unreachable during skill install: reply ERR clawhub unreachable. check network..
if skill install command hangs for >30s: kill process and reply ERR command timeout.
success case:
OK <summary> (single line, under 150 chars).OK installed claw-guru v1.2.3 to ~/workspace/skills.failure case:
ERR <reason> (single line, under 150 chars).ERR skill not found in registry.cron list success:
OK cron jobs:
id=1 name=dm-check every=10m enabled=true
id=2 name=health cron=*/5**** enabled=false
no secrets or file paths in replies:
/home/user/.openclaw/...) must not appear in chat.reply posted to same group chat: message is visible to all group members, not in a private reply.
success:
OK <summary> in the group within 5 seconds of the PM command.openclaw logs --follow shows the command was parsed and executed.clawhub list or openclaw cron list on dev server to confirm the resource was created/updated.failure:
ERR <reason> in the group.