Channels
Planning
OpenClaw Planning Plugin โ structured task plans with real-time Feishu/Telegram progress cards
Configuration Example
{
"plugins": {
"installs": {
"planning": {
"source": "path",
"sourcePath": "~/.openclaw/extensions/planning"
}
}
}
}
README
[English](README.md) | [ไธญๆ](README.zh-CN.md)
# OpenClaw Planning Plugin
Structured task planning for OpenClaw agents. Keeps agents on track across tool calls and context compaction, and gives users real-time visibility into what their agent is doing.
## Features
- **`plan_write` tool** โ agents create and update task plans during multi-step work
- **Multiple concurrent plans** โ agents can track unrelated tasks in separate plans within the same session
- **System prompt injection** โ all active plan states are injected every turn (sparse/full/stale reminders, adaptive to recency)
- **Conversation-aware card routing** โ notifications are sent to the correct chat (group or DM) via `message_received` hook
- **Feishu interactive cards** โ visual progress cards with live PATCH updates
- **Telegram messages** โ plain-text progress with live edits
- **Subagent plan delegation** โ sub-agents automatically update the parent's plan and Feishu/Telegram card via `subagent_spawned` hook
- **Spawn gating** โ `sessions_spawn` is blocked until the agent creates a plan, ensuring user visibility and clean cancellation
- **Confirmation interception** โ suppresses unnecessary "shall I proceed?" messages when any active plan exists
- **Subagent failure awareness** โ pokes parent session when a sub-agent fails
## How It Works
### Plan Lifecycle
```
Agent receives task
โ plan_write (create plan with pending items)
โ work on items, updating status as it goes
โ plan_write (close plan with all items completed)
โ deliver final result
```
Multiple plans can be active simultaneously. Each plan is identified by its title โ the agent uses the same title to update an existing plan, or a different title to create a new concurrent plan. Each plan gets its own progress card/message.
### Subagent Delegation
When an agent spawns a sub-agent, the plugin automatically delegates plan ownership:
```
Agent creates plan โ spawns sub-agent
โ subagent_spawned hook links child to parent's planDir
โ sub-agent sees parent's plan via before_prompt_build
โ sub-agent's plan_write updates parent's plan file
โ Feishu/Telegram card is PATCHed (same card, not a new one)
โ parent resumes and can continue updating the same plan
```
Spawning is gated: `sessions_spawn` is blocked if the agent has no active plan, forcing the agent to create one first. This ensures the user always has visibility and can cancel cleanly.
### System Prompt Injection
Every turn, `before_prompt_build` injects context based on plan state:
| State | Injection | Purpose |
|-------|-----------|---------|
| No plan | `<plan_available>` | Nudge agent to create a plan for multi-step work |
| Just updated (idle < 3) | Sparse reminder | Save tokens โ agent already has full context |
| Normal (idle 3โ7) | Full reminder | Show current plan status with all items |
| Stale (idle โฅ 8) | Full + warning | Prompt agent to update the plan |
### Channel Notifications
When the agent calls `plan_write`, progress is pushed to the conversation where the request originated:
- **Feishu** โ interactive Card 2.0 with stacked bar chart progress, live-updated via PATCH
- **Telegram** โ plain-text message with Unicode progress bar, live-updated via editMessage
- **Other channels** โ plan still works for agent self-tracking; no push notification
The `message_received` hook captures `conversationId` so cards are sent to the correct chat (group or DM), not always to the requester's DM.
### Confirmation Interception
The `message_sending` hook detects short confirmation-request messages (e.g., "shall I proceed?", "ๆฏๅฆ็ปง็ปญ?") and suppresses them when an active plan exists. Conservative matching โ would rather miss than false-positive.
## Plan Statuses
| Status | Text Symbol | Card Symbol | Card Color |
|--------|-------------|-------------|------------|
| pending | โ | โ | default |
| in_progress | โ | โ **bold** | orange |
| completed | โ | โ ~~strikethrough~~ | grey |
| cancelled | โ | โ ~~strikethrough~~ | dark yellow |
| failed | โ | โ **bold** | red |
## Installation
Add to your `openclaw.json`:
```json
{
"plugins": {
"installs": {
"planning": {
"source": "path",
"sourcePath": "~/.openclaw/extensions/planning"
}
}
}
}
```
Restart the gateway to load the plugin.
### Feishu Setup (optional)
To enable Feishu card notifications, configure credentials in `openclaw.json`:
```json
{
"channels": {
"feishu": {
"appId": "cli_xxx",
"appSecret": "xxx",
"domain": "feishu"
}
}
}
```
Per-agent accounts are supported via `channels.feishu.accounts.{agentAccountId}`.
### Telegram Setup (optional)
To enable Telegram message notifications:
```json
{
"channels": {
"telegram": {
"botToken": "123456:ABC-DEF..."
}
}
}
```
Per-agent accounts are supported via `channels.telegram.accounts.{agentAccountId}.botToken`.
## File Structure
```
src/
โโโ index.ts # Plugin entry โ registers tool + 8 hooks
โโโ types.ts # Core types: PlanFile, PlanItem, PlanStatus
โโโ plan-tool.ts # plan_write tool schema and description
โโโ plan-state.ts # Disk I/O: atomic read/write of .plan.json files
โโโ plan-injection.ts # System prompt text + Feishu card + plain-text rendering
โโโ runtime-state.ts # In-memory session state: idle counters, active-plan flags
โโโ feishu-client.ts # Feishu REST client (send/update cards, token cache)
โโโ telegram-client.ts # Telegram Bot API client (send/edit messages)
```
Plan files are stored per-agent, per-session, per-plan:
```
~/.openclaw/agents/{agentId}/plans/{sessionHash}/{titleHash}.plan.json
```
## Known Limitations
- **Telegram plain text only** โ messages do not use `parse_mode`, so Markdown formatting is not rendered
- **Subagent poke uses private API** โ `enqueueSystemEvent` is not part of the formal Plugin SDK; may break on OpenClaw upgrades
- **Delegation requires same agentDir** โ subagent plan delegation only works when parent and child share the same `agentDir` (true for same-agent subagents)
- **ConversationId availability** โ card routing to group chats depends on `conversationId` being present in the `message_received` hook context; if unavailable, falls back to requester DM
## Requirements
- OpenClaw >= 2026.2.0
- Node.js >= 18 (for native `fetch`)
## License
MIT
channels
Comments
Sign in to leave a comment