@enderfga/claw-orchestrator 3.5.6 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -119,7 +119,60 @@ never see the JSON — only the Planner's narrative.
119
119
  5-minute dedup on (level, summary) prevents duplicate pushes from the same
120
120
  event. Channel chain: `auto` walks wechat → whatsapp → email; `wechat` /
121
121
  `webchat` / `email` route directly; `both` does webchat (if session known)
122
- + wechat fallback chain.
122
+ + wechat fallback chain. **`on_phase_error` and `on_decision_needed` cannot
123
+ be set to `silent: true`** by Planner — `update_push_policy` strips the flag
124
+ and records the attempt in `decisions.jsonl` (these channels are the
125
+ operator's lifeline; they stay loud).
126
+
127
+ ## Auto-compact
128
+
129
+ Each agent's context is monitored after every turn. When `getStats().contextPercent`
130
+ crosses the per-agent threshold the dispatcher invokes `/compact` with a
131
+ role-tuned hint (`compactSummaryFor`). Defaults: Planner 80 %, Coder 70 %,
132
+ Reviewer 70 %. Override per run via `compactThresholds`. A 30 s debounce
133
+ prevents re-fire while post-compact stats settle. Events: `compact` is
134
+ emitted on the dispatcher EventEmitter AND appended to `decisions.jsonl`.
135
+
136
+ ## Phase-error circuit
137
+
138
+ Subprocess deaths (Claude session lost), failed `git commit` in an iter, and
139
+ other phase-bound failures surface as `phase_error` messages instead of
140
+ silently masquerading as a "clarification request". The runner counts
141
+ consecutive `phase_error`s and:
142
+
143
+ 1. Fires `on_phase_error` on each one (defaults to error / both channels).
144
+ 2. After `phaseErrorCircuit` consecutive errors (default **3**) emits a
145
+ `decision`-level push and an automatic `terminate { reason:
146
+ 'phase_error_circuit' }`.
147
+
148
+ A successful (non-error) `iter_done` resets the counter. Override the
149
+ threshold via `AutoloopConfig.phaseErrorCircuit`.
150
+
151
+ ## Reviewer frozen memory
152
+
153
+ `reviewer_memory.md` is read at Reviewer-session start and **injected as a
154
+ frozen `<frozen_memory_snapshot>` block** into the system prompt. It stays
155
+ constant for the lifetime of that session so Claude's prefix cache hits.
156
+ Reviewer can append fresh observations to the file on disk; those edits
157
+ become visible only on the next Reviewer reset (`autoloop_reset_agent`
158
+ with `agent: 'reviewer', eager_restart: true`).
159
+
160
+ ## Decisions audit
161
+
162
+ `<ledger>/decisions.jsonl` is the auditable trail of runner / dispatcher
163
+ decisions:
164
+
165
+ | Kind | When |
166
+ |---|---|
167
+ | `spawn_subagents` | Planner emits `spawn_subagents` |
168
+ | `reset_agent` | Any agent reset (manual or auto-recovery) |
169
+ | `compact` | Auto-compact fires |
170
+ | `update_push_policy` | Planner mutates the policy |
171
+ | `policy_silence_blocked` | Planner tried to silence a critical channel |
172
+ | `phase_error` | Surfaced from dispatcher to runner |
173
+ | `terminate` | Run ends (planner reason or `phase_error_circuit`) |
174
+
175
+ JSONL, one entry per line, ts-prefixed.
123
176
 
124
177
  ## Ledger layout
125
178
 
@@ -128,22 +181,30 @@ event. Channel chain: `auto` walks wechat → whatsapp → email; `wechat` /
128
181
  ├── plan.md # Planner-authored, git-committed
129
182
  ├── goal.json # Planner-authored, git-committed
130
183
  ├── push_log.jsonl # every notify_user attempt + channel used
184
+ ├── decisions.jsonl # runner / dispatcher audit trail (see above)
131
185
  ├── reviewer_sandbox/ # Reviewer cwd; restaged per iter
132
186
  │ ├── plan.md # copy
133
187
  │ ├── goal.json # copy
134
188
  │ ├── iter-N/ # this iter's directive + diff + eval
135
189
  │ ├── prior_verdict.json
136
- │ └── reviewer_memory.md # persistent across iters
190
+ │ ├── reviewer_memory.md # persistent (frozen-injected at session start)
191
+ │ └── reviewer_log.jsonl # persistent (Reviewer's append-only audit log)
137
192
  └── iter/<n>/
138
- ├── directive.json # Planner → Coder
139
- ├── eval_output.json # what Coder reported
193
+ ├── directive.json # Planner → Coder (schema_version: 1)
194
+ ├── eval_output.json # what Coder reported (schema_version: 1)
140
195
  ├── diff.patch # git diff of the iter
141
- ├── verdict.json # Reviewer decision + audit notes
196
+ ├── verdict.json # Reviewer decision + audit notes (schema_version: 1)
142
197
  └── coder_summary.txt
143
198
  ```
144
199
 
145
200
  The orchestrator git-commits each iter automatically. Coder must NOT call
146
- `git commit` itself — that confuses the diff log.
201
+ `git commit` itself — that confuses the diff log. **If `git commit` fails
202
+ inside an iter** (pre-commit hook reject, signing key missing, …) the
203
+ dispatcher emits a `phase_error` instead of writing `iter_artifacts`, so
204
+ the failure is visible to the runner and counts toward the circuit.
205
+
206
+ Every JSON artifact in the ledger carries a `schema_version` field (currently
207
+ `1`) to make future migrations explicit.
147
208
 
148
209
  ## Backend HTTP / SSE
149
210
 
@@ -210,9 +271,10 @@ iter 0 ledger artifacts (`directive` + `eval_output` + `diff.patch` +
210
271
 
211
272
  ## Known limitations
212
273
 
213
- - **No auto-compact on token budget.** Manual `autoloop_reset_agent` covers
214
- the same recovery path. Auto-compact is queued for a follow-up once
215
- `ISession.getStats` exposes token-usage hooks.
274
+ - **`webchat` channel is a no-op** — `notifyUserFallbackChain` does not yet
275
+ carry a webchat session id at the run level, so `channel: 'webchat'`
276
+ always returns `channel_used: 'none'`. Use `auto` / `wechat` / `email`
277
+ until the inbound route lands.
216
278
  - **One-way push.** WeChat → Planner inbound replies are not yet wired (would
217
279
  need an openclaw-gateway tmux-passthrough route). Reply via webchat /
218
280
  `autoloop_chat`.
@@ -221,3 +283,10 @@ iter 0 ledger artifacts (`directive` + `eval_output` + `diff.patch` +
221
283
  - **No fork / population mode.** Single linear iter trajectory per run.
222
284
  - **Cross-run knowledge isolated.** Each run's `reviewer_memory.md` and
223
285
  `coder_notes.md` live in that run's ledger; no shared meta-store yet.
286
+ - **No cost / wall-clock budget cap.** Only `phaseErrorCircuit` + Reviewer
287
+ hold/reject streaks bound the run; a steady-but-pointless ratchet could
288
+ run for days. Set `max_iters` in `goal.json` to bound iter count.
289
+ - **Run state in memory.** SessionManager restart drops the live `autoloops`
290
+ map; the on-disk ledger survives but cannot resume a running state.
291
+ - **Multi-run / same workspace** races on `git index.lock`. Run separate
292
+ workspaces (or git worktrees) for concurrent runs.
@@ -0,0 +1,294 @@
1
+ # MCP integration
2
+
3
+ Claw Orchestrator ships a Model Context Protocol (MCP) server (`clawo-mcp`) so any MCP-compatible host can drive its 41 tools.
4
+
5
+ This document covers:
6
+
7
+ - [How it works](#how-it-works)
8
+ - [Host configuration](#host-configuration)
9
+ - [Hermes Agent](#hermes-agent)
10
+ - [Claude Desktop / Claude Code](#claude-desktop--claude-code)
11
+ - [Cursor](#cursor)
12
+ - [Cline (VS Code)](#cline-vs-code)
13
+ - [Continue](#continue)
14
+ - [Zed](#zed)
15
+ - [Windsurf](#windsurf)
16
+ - [Goose](#goose)
17
+ - [Any other MCP host](#any-other-mcp-host)
18
+ - [Environment variables](#environment-variables)
19
+ - [Tool filtering](#tool-filtering)
20
+ - [Tool annotations](#tool-annotations)
21
+ - [Troubleshooting](#troubleshooting)
22
+ - [MCP vs OpenClaw plugin: when to use which](#mcp-vs-openclaw-plugin-when-to-use-which)
23
+
24
+ ---
25
+
26
+ ## How it works
27
+
28
+ `clawo-mcp` is a thin stdio MCP server. It reuses the same tool definitions registered by the OpenClaw plugin entry point (`src/index.ts`), so there is exactly one source of truth and zero schema drift between the OpenClaw plugin form and the MCP server form.
29
+
30
+ Tools fall into a few groups:
31
+
32
+ | Group | Examples |
33
+ |---|---|
34
+ | Session lifecycle | `session_start`, `session_send`, `session_stop`, `session_list`, `session_grep`, `session_compact`, `session_update_tools`, `session_switch_model` |
35
+ | Cross-session messaging | `session_send_to`, `session_inbox`, `session_deliver_inbox` |
36
+ | Status / introspection | `sessions_overview`, `coding_session_status`, `coding_agents_list` |
37
+ | Multi-agent council | `council_start`, `council_status`, `council_abort`, `council_inject`, `council_review`, `council_accept`, `council_reject` |
38
+ | Ultraplan / ultrareview | `ultraplan_start`, `ultraplan_status`, `ultrareview_start`, `ultrareview_status` |
39
+ | Autoloop | `autoloop_start`, `autoloop_chat`, `autoloop_status`, `autoloop_list`, `autoloop_reset_agent`, `autoloop_stop` |
40
+ | Codex specifics | `codex_resume`, `codex_review`, `codex_goal_set`, `codex_goal_get`, `codex_goal_pause`, `codex_goal_resume`, `codex_goal_clear` |
41
+ | Agent teams | `team_list`, `team_send` |
42
+ | Maintenance | `project_purge` |
43
+
44
+ Full per-tool parameter documentation lives in [`tools.md`](./tools.md).
45
+
46
+ Install once:
47
+
48
+ ```bash
49
+ npm install -g @enderfga/claw-orchestrator
50
+ # `clawo-mcp` is on PATH; the OpenClaw `clawo` CLI is also installed
51
+ ```
52
+
53
+ When invoked, `clawo-mcp`:
54
+
55
+ 1. Sets `CLAWO_NO_EMBEDDED_SERVER=1` so the orchestrator does not bind its HTTP control plane (port 18796) — MCP-only deployments do not need it.
56
+ 2. Captures the plugin's registered tools via an in-memory shim.
57
+ 3. Speaks MCP over stdio. All log lines go to stderr; stdout is reserved for the protocol.
58
+
59
+ ---
60
+
61
+ ## Host configuration
62
+
63
+ ### Hermes Agent
64
+
65
+ Add to `~/.hermes/config.yaml`:
66
+
67
+ ```yaml
68
+ mcp_servers:
69
+ clawo:
70
+ command: clawo-mcp
71
+ env:
72
+ ANTHROPIC_API_KEY: "..."
73
+ OPENAI_API_KEY: "..."
74
+ GEMINI_API_KEY: "..."
75
+ tools:
76
+ include:
77
+ - mcp_clawo_session_start
78
+ - mcp_clawo_session_send
79
+ - mcp_clawo_session_stop
80
+ - mcp_clawo_council_start
81
+ - mcp_clawo_council_status
82
+ - mcp_clawo_council_review
83
+ ```
84
+
85
+ Reload without restarting:
86
+
87
+ ```text
88
+ /reload-mcp
89
+ ```
90
+
91
+ Hermes prefixes tool names with `mcp_<server>_`. The model sees the prefixed names; you do not call them manually.
92
+
93
+ ### Claude Desktop / Claude Code
94
+
95
+ `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "clawo": {
101
+ "command": "clawo-mcp",
102
+ "env": {
103
+ "ANTHROPIC_API_KEY": "...",
104
+ "OPENAI_API_KEY": "...",
105
+ "CLAWO_MCP_TOOLS": "session_start,session_send,council_start,council_status"
106
+ }
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ For Claude Code (`~/.claude.json` or per-project `.mcp.json`), use the same shape under `mcpServers`.
113
+
114
+ ### Cursor
115
+
116
+ In Cursor settings → MCP, add a server. The config file is `~/.cursor/mcp.json`:
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "clawo": {
122
+ "command": "clawo-mcp",
123
+ "env": { "ANTHROPIC_API_KEY": "...", "OPENAI_API_KEY": "..." }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ### Cline (VS Code)
130
+
131
+ VS Code command palette → `Cline: Open MCP Settings`. Add:
132
+
133
+ ```json
134
+ {
135
+ "mcpServers": {
136
+ "clawo": {
137
+ "command": "clawo-mcp",
138
+ "env": { "ANTHROPIC_API_KEY": "...", "OPENAI_API_KEY": "..." }
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### Continue
145
+
146
+ `~/.continue/config.yaml`:
147
+
148
+ ```yaml
149
+ mcpServers:
150
+ - name: clawo
151
+ command: clawo-mcp
152
+ env:
153
+ ANTHROPIC_API_KEY: "..."
154
+ OPENAI_API_KEY: "..."
155
+ ```
156
+
157
+ ### Zed
158
+
159
+ `~/.config/zed/settings.json` under `context_servers`:
160
+
161
+ ```json
162
+ {
163
+ "context_servers": {
164
+ "clawo": {
165
+ "command": { "path": "clawo-mcp", "env": { "ANTHROPIC_API_KEY": "..." } }
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ ### Windsurf
172
+
173
+ `~/.codeium/windsurf/mcp_config.json`:
174
+
175
+ ```json
176
+ {
177
+ "mcpServers": {
178
+ "clawo": {
179
+ "command": "clawo-mcp",
180
+ "env": { "ANTHROPIC_API_KEY": "..." }
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### Goose
187
+
188
+ `~/.config/goose/config.yaml`:
189
+
190
+ ```yaml
191
+ extensions:
192
+ clawo:
193
+ type: stdio
194
+ cmd: clawo-mcp
195
+ envs:
196
+ ANTHROPIC_API_KEY: "..."
197
+ ```
198
+
199
+ ### Any other MCP host
200
+
201
+ Anything that speaks stdio MCP will work. The minimum shape is:
202
+
203
+ ```text
204
+ command: clawo-mcp
205
+ env:
206
+ ANTHROPIC_API_KEY: "..."
207
+ ```
208
+
209
+ Check your host's MCP docs for the exact key names (`command`/`cmd`, `env`/`envs`, `args`/`arguments`).
210
+
211
+ ---
212
+
213
+ ## Environment variables
214
+
215
+ Hosts deliberately do not forward your full shell environment to MCP subprocesses. Pass every variable your engines need explicitly under the host's `env` block.
216
+
217
+ | Variable | Used by |
218
+ |---|---|
219
+ | `ANTHROPIC_API_KEY` | Claude Code engine |
220
+ | `OPENAI_API_KEY` | Codex engine |
221
+ | `GEMINI_API_KEY` (or `GOOGLE_API_KEY`) | Gemini engine |
222
+ | `GATEWAY_URL`, `GATEWAY_KEY` | Routing through an OpenClaw / Anthropic-style gateway |
223
+ | `CLAWO_MCP_TOOLS` | Comma-separated allowlist of tool names; unlisted tools are not advertised |
224
+ | `CLAWO_NO_EMBEDDED_SERVER` | Suppresses port 18796 binding. `clawo-mcp` sets this automatically |
225
+
226
+ The engines themselves (`claude`, `codex`, `gemini`, `agent`, `opencode`) must also be installed and authenticated on the host machine — `clawo-mcp` spawns them as subprocesses, it does not bundle them.
227
+
228
+ ---
229
+
230
+ ## Tool filtering
231
+
232
+ 41 tools is a lot for a small context window. Reduce noise either at the host level (most hosts have an `include` / `exclude` filter — see Hermes example above) or at the server level via `CLAWO_MCP_TOOLS`:
233
+
234
+ ```bash
235
+ CLAWO_MCP_TOOLS="session_start,session_send,session_stop,council_start,council_status" clawo-mcp
236
+ ```
237
+
238
+ Both are valid; host-level filtering keeps the config in one place, server-level filtering hides tools before the host even sees them.
239
+
240
+ A reasonable minimum set for "let the model drive a single Claude Code session":
241
+
242
+ - `session_start`, `session_send`, `session_stop`, `session_list`, `coding_session_status`
243
+
244
+ For "let the model run councils and review work":
245
+
246
+ - `council_start`, `council_status`, `council_review`, `council_accept`, `council_reject`
247
+
248
+ For "let the model commission an ultrareview before merging":
249
+
250
+ - `ultrareview_start`, `ultrareview_status`
251
+
252
+ ---
253
+
254
+ ## Tool annotations
255
+
256
+ `clawo-mcp` advertises [tool annotations](https://modelcontextprotocol.io/specification/server/tools#annotations) so hosts can prefer safer tools when reasoning:
257
+
258
+ | Annotation | Tools |
259
+ |---|---|
260
+ | `readOnlyHint` + `idempotentHint` | `session_list`, `sessions_overview`, `coding_session_status`, `session_grep`, `session_inbox`, `coding_agents_list`, `team_list`, `council_status`, `council_review`, `ultraplan_status`, `ultrareview_status`, `autoloop_status`, `autoloop_list`, `codex_goal_get` |
261
+ | `destructiveHint` | `session_stop`, `council_abort`, `council_accept`, `council_reject`, `autoloop_stop`, `project_purge` |
262
+ | `openWorldHint` | All tools that make outbound model API calls (most session / council / ultraplan / autoloop tools) |
263
+
264
+ ---
265
+
266
+ ## Troubleshooting
267
+
268
+ **The host shows no tools after restart**
269
+ - Confirm `clawo-mcp` resolves on PATH: `which clawo-mcp`. If you used a non-global install, use the absolute path in `command`.
270
+ - Confirm the host logs (Hermes: `~/.hermes/logs/`, Claude Desktop: View → Open Logs Folder). Look for the `[clawo-mcp]` lines.
271
+
272
+ **Engine starts but fails with `command not found`**
273
+ - The underlying coding CLI (`claude`, `codex`, `gemini`, etc.) is not on PATH in the host's subprocess environment. Either install globally or set `claudeBin` / `codexBin` etc. via `customEngine.bin` per session, or pass an explicit `PATH` in the host's `env` block.
274
+
275
+ **`401` / `auth` errors from a session**
276
+ - The corresponding API key is missing from the `env` block. Hosts do not inherit your shell environment.
277
+
278
+ **Tool list comes back empty**
279
+ - `CLAWO_MCP_TOOLS` filter is set to names that don't exist. Drop it and check `tools/list` again, then add back the correct names. Stderr will print a warning.
280
+
281
+ **Port 18796 in use error**
282
+ - `clawo-mcp` does not bind it; this is only reachable via the OpenClaw plugin path or `clawo serve`. If you see this, something else (a stale `clawo` or an OpenClaw gateway) is running. `lsof -i :18796`.
283
+
284
+ ---
285
+
286
+ ## MCP vs OpenClaw plugin: when to use which
287
+
288
+ | Use case | Recommended form |
289
+ |---|---|
290
+ | You already run OpenClaw and want the tools available to every OpenClaw agent | OpenClaw plugin |
291
+ | You want to drive coding agents from Hermes Agent, Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf, Goose, or another MCP host | MCP server |
292
+ | You want to call the orchestrator from a non-MCP custom runtime (Python, Go, …) | Standalone `clawo serve` HTTP API |
293
+
294
+ The same package supports all three — they share the SessionManager and tool definitions. Pick whichever entry point matches your host.