@enderfga/claw-orchestrator 5.1.0 → 6.0.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.
Files changed (147) hide show
  1. package/README.md +26 -26
  2. package/dist/bin/cli.js +107 -1
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/acp-server.d.ts +5 -5
  5. package/dist/src/acp-server.js +3 -3
  6. package/dist/src/acp-server.js.map +1 -1
  7. package/dist/src/autoloop/dispatcher.d.ts +22 -0
  8. package/dist/src/autoloop/dispatcher.js +71 -13
  9. package/dist/src/autoloop/dispatcher.js.map +1 -1
  10. package/dist/src/autoloop/messages.d.ts +10 -0
  11. package/dist/src/autoloop/messages.js.map +1 -1
  12. package/dist/src/autoloop/runner.js +6 -0
  13. package/dist/src/autoloop/runner.js.map +1 -1
  14. package/dist/src/constants.d.ts +0 -6
  15. package/dist/src/constants.js +0 -6
  16. package/dist/src/constants.js.map +1 -1
  17. package/dist/src/council.d.ts +15 -0
  18. package/dist/src/council.js +48 -35
  19. package/dist/src/council.js.map +1 -1
  20. package/dist/src/dashboard/index.html +191 -6
  21. package/dist/src/embedded-server.js +132 -9
  22. package/dist/src/embedded-server.js.map +1 -1
  23. package/dist/src/fanout.d.ts +30 -1
  24. package/dist/src/fanout.js +32 -3
  25. package/dist/src/fanout.js.map +1 -1
  26. package/dist/src/index.js +359 -4
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/kernel/agent-step.d.ts +59 -0
  29. package/dist/src/kernel/agent-step.js +100 -0
  30. package/dist/src/kernel/agent-step.js.map +1 -0
  31. package/dist/src/kernel/conditions.d.ts +11 -0
  32. package/dist/src/kernel/conditions.js +24 -0
  33. package/dist/src/kernel/conditions.js.map +1 -0
  34. package/dist/src/kernel/engine.d.ts +319 -0
  35. package/dist/src/kernel/engine.js +1047 -0
  36. package/dist/src/kernel/engine.js.map +1 -0
  37. package/dist/src/kernel/exec.d.ts +43 -0
  38. package/dist/src/kernel/exec.js +112 -0
  39. package/dist/src/kernel/exec.js.map +1 -0
  40. package/dist/src/kernel/file-lock.d.ts +50 -0
  41. package/dist/src/kernel/file-lock.js +135 -0
  42. package/dist/src/kernel/file-lock.js.map +1 -0
  43. package/dist/src/kernel/nodes/agent.d.ts +4 -0
  44. package/dist/src/kernel/nodes/agent.js +35 -0
  45. package/dist/src/kernel/nodes/agent.js.map +1 -0
  46. package/dist/src/kernel/nodes/autoloop.d.ts +78 -0
  47. package/dist/src/kernel/nodes/autoloop.js +75 -0
  48. package/dist/src/kernel/nodes/autoloop.js.map +1 -0
  49. package/dist/src/kernel/nodes/council.d.ts +12 -0
  50. package/dist/src/kernel/nodes/council.js +88 -0
  51. package/dist/src/kernel/nodes/council.js.map +1 -0
  52. package/dist/src/kernel/nodes/fanout.d.ts +11 -0
  53. package/dist/src/kernel/nodes/fanout.js +63 -0
  54. package/dist/src/kernel/nodes/fanout.js.map +1 -0
  55. package/dist/src/kernel/nodes/human-gate.d.ts +4 -0
  56. package/dist/src/kernel/nodes/human-gate.js +7 -0
  57. package/dist/src/kernel/nodes/human-gate.js.map +1 -0
  58. package/dist/src/kernel/nodes/index.d.ts +12 -0
  59. package/dist/src/kernel/nodes/index.js +21 -0
  60. package/dist/src/kernel/nodes/index.js.map +1 -0
  61. package/dist/src/kernel/nodes/router.d.ts +4 -0
  62. package/dist/src/kernel/nodes/router.js +12 -0
  63. package/dist/src/kernel/nodes/router.js.map +1 -0
  64. package/dist/src/kernel/nodes/subflow.d.ts +13 -0
  65. package/dist/src/kernel/nodes/subflow.js +38 -0
  66. package/dist/src/kernel/nodes/subflow.js.map +1 -0
  67. package/dist/src/kernel/nodes/ultraapp.d.ts +60 -0
  68. package/dist/src/kernel/nodes/ultraapp.js +62 -0
  69. package/dist/src/kernel/nodes/ultraapp.js.map +1 -0
  70. package/dist/src/kernel/nodes/verifier.d.ts +14 -0
  71. package/dist/src/kernel/nodes/verifier.js +84 -0
  72. package/dist/src/kernel/nodes/verifier.js.map +1 -0
  73. package/dist/src/kernel/projections.d.ts +42 -0
  74. package/dist/src/kernel/projections.js +133 -0
  75. package/dist/src/kernel/projections.js.map +1 -0
  76. package/dist/src/kernel/repo.d.ts +13 -0
  77. package/dist/src/kernel/repo.js +64 -0
  78. package/dist/src/kernel/repo.js.map +1 -0
  79. package/dist/src/kernel/secrets.d.ts +25 -0
  80. package/dist/src/kernel/secrets.js +48 -0
  81. package/dist/src/kernel/secrets.js.map +1 -0
  82. package/dist/src/kernel/store.d.ts +225 -0
  83. package/dist/src/kernel/store.js +838 -0
  84. package/dist/src/kernel/store.js.map +1 -0
  85. package/dist/src/kernel/templates/index.d.ts +140 -0
  86. package/dist/src/kernel/templates/index.js +266 -0
  87. package/dist/src/kernel/templates/index.js.map +1 -0
  88. package/dist/src/kernel/types.d.ts +326 -0
  89. package/dist/src/kernel/types.js +19 -0
  90. package/dist/src/kernel/types.js.map +1 -0
  91. package/dist/src/run-ledger.d.ts +57 -3
  92. package/dist/src/run-ledger.js +45 -2
  93. package/dist/src/run-ledger.js.map +1 -1
  94. package/dist/src/session-manager.d.ts +176 -129
  95. package/dist/src/session-manager.js +652 -603
  96. package/dist/src/session-manager.js.map +1 -1
  97. package/dist/src/types.d.ts +33 -3
  98. package/dist/src/ultraapp/build.d.ts +117 -3
  99. package/dist/src/ultraapp/build.js +319 -3
  100. package/dist/src/ultraapp/build.js.map +1 -1
  101. package/dist/src/ultraapp/contract.d.ts +52 -0
  102. package/dist/src/ultraapp/contract.js +83 -0
  103. package/dist/src/ultraapp/contract.js.map +1 -0
  104. package/dist/src/ultraapp/conventions.js +9 -2
  105. package/dist/src/ultraapp/conventions.js.map +1 -1
  106. package/dist/src/ultraapp/fix-on-failure.d.ts +21 -2
  107. package/dist/src/ultraapp/fix-on-failure.js +46 -62
  108. package/dist/src/ultraapp/fix-on-failure.js.map +1 -1
  109. package/dist/src/ultraapp/manager.d.ts +107 -2
  110. package/dist/src/ultraapp/manager.js +305 -86
  111. package/dist/src/ultraapp/manager.js.map +1 -1
  112. package/dist/src/verify/baseline.d.ts +73 -0
  113. package/dist/src/verify/baseline.js +186 -0
  114. package/dist/src/verify/baseline.js.map +1 -0
  115. package/dist/src/verify/contract.d.ts +116 -0
  116. package/dist/src/verify/contract.js +142 -0
  117. package/dist/src/verify/contract.js.map +1 -0
  118. package/dist/src/verify/evidence.d.ts +61 -0
  119. package/dist/src/verify/evidence.js +133 -0
  120. package/dist/src/verify/evidence.js.map +1 -0
  121. package/dist/src/verify/runner.d.ts +63 -0
  122. package/dist/src/verify/runner.js +317 -0
  123. package/dist/src/verify/runner.js.map +1 -0
  124. package/openclaw.plugin.json +8 -0
  125. package/package.json +2 -2
  126. package/skills/SKILL.md +120 -79
  127. package/skills/references/acp.md +17 -17
  128. package/skills/references/autoloop.md +139 -65
  129. package/skills/references/claude-cli-tracking.md +4 -4
  130. package/skills/references/cli.md +101 -59
  131. package/skills/references/council.md +109 -37
  132. package/skills/references/dashboard.md +34 -6
  133. package/skills/references/getting-started.md +13 -13
  134. package/skills/references/inbox.md +4 -4
  135. package/skills/references/mcp.md +39 -34
  136. package/skills/references/multi-engine.md +51 -47
  137. package/skills/references/observability.md +88 -28
  138. package/skills/references/openai-compat.md +39 -39
  139. package/skills/references/sessions.md +43 -25
  140. package/skills/references/tools.md +402 -309
  141. package/skills/references/ultra.md +45 -45
  142. package/skills/references/ultraapp.md +126 -50
  143. package/skills/references/verification.md +187 -0
  144. package/skills/references/workflow.md +362 -0
  145. package/dist/src/ultraapp/fix-on-failure-session.d.ts +0 -23
  146. package/dist/src/ultraapp/fix-on-failure-session.js +0 -51
  147. package/dist/src/ultraapp/fix-on-failure-session.js.map +0 -1
@@ -51,6 +51,7 @@ Agents cannot interfere with each other's files. All integration happens via `gi
51
51
  ### Consensus Voting
52
52
 
53
53
  Every agent must include `[CONSENSUS: YES]` or `[CONSENSUS: NO]` at the end of each round's response. The council continues until:
54
+
54
55
  - **All agents vote YES** — consensus reached
55
56
  - **Max rounds reached** — timeout
56
57
  - **Aborted** — user intervention
@@ -79,18 +80,19 @@ import { SessionManager } from '@enderfga/claw-orchestrator';
79
80
 
80
81
  const manager = new SessionManager();
81
82
 
82
- const session = manager.councilStart(
83
- 'Build a REST API with authentication',
84
- {
85
- agents: [
86
- { name: 'Planner', emoji: '🟠', persona: 'Technical planner focused on requirements decomposition and architecture' },
87
- { name: 'Generator', emoji: '🟢', persona: 'Implementation engineer focused on shipping correct code per plan' },
88
- { name: 'Evaluator', emoji: '🔵', persona: 'Independent quality gate focused on verification and acceptance' },
89
- ],
90
- maxRounds: 10,
91
- projectDir: '/tmp/my-api-project',
92
- }
93
- );
83
+ const session = manager.councilStart('Build a REST API with authentication', {
84
+ agents: [
85
+ {
86
+ name: 'Planner',
87
+ emoji: '🟠',
88
+ persona: 'Technical planner focused on requirements decomposition and architecture',
89
+ },
90
+ { name: 'Generator', emoji: '🟢', persona: 'Implementation engineer focused on shipping correct code per plan' },
91
+ { name: 'Evaluator', emoji: '🔵', persona: 'Independent quality gate focused on verification and acceptance' },
92
+ ],
93
+ maxRounds: 10,
94
+ projectDir: '/tmp/my-api-project',
95
+ });
94
96
 
95
97
  console.log(`Council started: ${session.id}`);
96
98
  // Poll for status
@@ -113,15 +115,15 @@ Agents can use different engines and models:
113
115
 
114
116
  ## Council Tools
115
117
 
116
- | Tool | Description |
117
- |------|-------------|
118
- | `council_start` | Start a council. Runs in background, returns session ID immediately. |
119
- | `council_status` | Get current status (running/consensus/max_rounds/error), responses, votes. |
120
- | `council_abort` | Stop all agent sessions and terminate the council. |
121
- | `council_inject` | Inject a user message into all agents' prompts in the next round. |
118
+ | Tool | Description |
119
+ | ---------------- | --------------------------------------------------------------------------------------- |
120
+ | `council_start` | Start a council. Runs in background, returns session ID immediately. |
121
+ | `council_status` | Get current status (running/consensus/max_rounds/error), responses, votes. |
122
+ | `council_abort` | Stop all agent sessions and terminate the council. |
123
+ | `council_inject` | Inject a user message into all agents' prompts in the next round. |
122
124
  | `council_review` | Review completed council output: changed files, branches, plan status, agent summaries. |
123
- | `council_accept` | Accept work and clean up: remove worktrees, branches, plan.md, reviews/. |
124
- | `council_reject` | Reject work: rewrite plan.md with feedback for the council to retry. |
125
+ | `council_accept` | Accept work and clean up: remove worktrees, branches, plan.md, reviews/. |
126
+ | `council_reject` | Reject work: rewrite plan.md with feedback for the council to retry. |
125
127
 
126
128
  ## Post-Processing Lifecycle
127
129
 
@@ -134,6 +136,7 @@ After a council reaches consensus or hits max rounds, use the review/accept/reje
134
136
  ```
135
137
 
136
138
  Returns a structured report:
139
+
137
140
  - **changedFiles**: all files modified by the council with insertion/deletion counts
138
141
  - **branches**: remaining `council/*` branches
139
142
  - **worktrees**: remaining council worktrees
@@ -148,6 +151,7 @@ Returns a structured report:
148
151
  ```
149
152
 
150
153
  Cleans up all council scaffolding:
154
+
151
155
  - Removes all `council/*` worktrees and `.worktrees/` directory
152
156
  - Deletes all `council/*` branches
153
157
  - Removes `plan.md` and `reviews/` directory
@@ -163,12 +167,12 @@ Rewrites `plan.md` with rejection feedback and commits it. All worktrees and bra
163
167
 
164
168
  ## Configuration
165
169
 
166
- | Parameter | Default | Description |
167
- |-----------|---------|-------------|
168
- | `maxRounds` | 15 | Maximum collaboration rounds |
169
- | `agentTimeoutMs` | 1,800,000 (30 min) | Per-agent timeout per round |
170
- | `maxTurnsPerAgent` | 30 | Max tool turns per agent per round |
171
- | `maxBudgetUsd` | — | API spend limit per agent |
170
+ | Parameter | Default | Description |
171
+ | ------------------ | ------------------ | ---------------------------------- |
172
+ | `maxRounds` | 15 | Maximum collaboration rounds |
173
+ | `agentTimeoutMs` | 1,800,000 (30 min) | Per-agent timeout per round |
174
+ | `maxTurnsPerAgent` | 30 | Max tool turns per agent per round |
175
+ | `maxBudgetUsd` | — | API spend limit per agent |
172
176
 
173
177
  ### defaultPermissionMode
174
178
 
@@ -191,20 +195,88 @@ Permission priority: agent-level `permissionMode` > `defaultPermissionMode` > `'
191
195
 
192
196
  The council system prompt is loaded from `configs/council-system-prompt.md` and supports hot-editing. It includes 9 charter sections tuned through extensive multi-agent collaboration testing:
193
197
 
194
- | Section | Purpose |
195
- |---------|---------|
196
- | §0 No Hallucination | Agents must use tools, never fabricate results |
197
- | §1 Plan First | Two-phase protocol with plan.md |
198
- | §2 Parallel Coordination | Claim/done protocol for concurrent work |
199
- | §3 Truth in Git | Git state over conversation memory |
200
- | §4 Merge to Main | Local only, never push |
201
- | §5 Cross-Review | Structured APPROVE/REQUEST_CHANGES |
202
- | §6 Auto-Conflict Resolution | Never stop on merge conflicts |
203
- | §7 Action Over Words | Never ask permission, just work |
204
- | §8 Efficient Tool Use | Minimum necessary principle |
198
+ | Section | Purpose |
199
+ | --------------------------- | ---------------------------------------------- |
200
+ | §0 No Hallucination | Agents must use tools, never fabricate results |
201
+ | §1 Plan First | Two-phase protocol with plan.md |
202
+ | §2 Parallel Coordination | Claim/done protocol for concurrent work |
203
+ | §3 Truth in Git | Git state over conversation memory |
204
+ | §4 Merge to Main | Local only, never push |
205
+ | §5 Cross-Review | Structured APPROVE/REQUEST_CHANGES |
206
+ | §6 Auto-Conflict Resolution | Never stop on merge conflicts |
207
+ | §7 Action Over Words | Never ask permission, just work |
208
+ | §8 Efficient Tool Use | Minimum necessary principle |
205
209
 
206
210
  Placeholders: `{{emoji}}`, `{{name}}`, `{{persona}}`, `{{workDir}}`, `{{otherBranches}}`
207
211
 
208
212
  ## Transcript Logging
209
213
 
210
214
  All council sessions save transcripts to `~/.openclaw/council-logs/council-<timestamp>.md`. Completed councils remain queryable via `council_status` for 30 minutes after completion.
215
+
216
+ ## Consensus is advisory (6.0.0)
217
+
218
+ Through 5.1.0 a council ended when `parseConsensus` found `[CONSENSUS: YES]` in
219
+ every agent's reply — that is, the termination condition was a regex over agent
220
+ prose. Two things made that weaker than it looked: the fallback patterns match a
221
+ bare `consensus: yes` anywhere in the text, and when a reply came back short and
222
+ unmarked the orchestrator re-prompted twice _asking for the token_, which is
223
+ demanding a vote rather than checking anything.
224
+
225
+ Votes are still collected and still recorded — they are what the agents were
226
+ asked for, and they are useful. They are recorded on the run as
227
+ `consensusVotes`, each with the parse `source` (`strict` / `variant` / `none`) so
228
+ a loosely-detected vote is visible as such.
229
+
230
+ What changed is that they no longer decide whether the work is acceptable. Give
231
+ the run an acceptance contract and the runtime checks the result itself:
232
+
233
+ ```jsonc
234
+ workflow_start({
235
+ template: "council",
236
+ task: "Fix the failing integration tests",
237
+ agents: [{ name: "alice", engine: "claude" }, { name: "bob", engine: "codex" }],
238
+ contract: { checks: [{ type: "command", cmd: "npm", args: ["test"] }] }
239
+ })
240
+ ```
241
+
242
+ Without a contract the council behaves exactly as before and the run completes
243
+ `unverified` — nothing checked it.
244
+
245
+ `council_start` and the rest of the `council_*` tools keep their signatures, with
246
+ one change forced by the cutover: **`councilStart` is now async** (it creates a
247
+ durable run before returning). The same applies to `fanoutStart`,
248
+ `ultraplanStart` and `ultrareviewStart`. Tool callers are unaffected; direct
249
+ TypeScript callers need an `await`.
250
+
251
+ ## Lifecycle moved to the kernel
252
+
253
+ A council is a kernel run. `councils`, its 30-minute eviction timer, and
254
+ `listCouncilsFromDisk` — which read `~/.openclaw/council-logs/*.md` with a regex
255
+ and fabricated a stub session with no responses and an empty config — are gone.
256
+ `council_list` returns real records, from disk, across processes.
257
+
258
+ `council_review` / `accept` / `reject` work after a restart now. They act on the
259
+ git state a finished council left behind, not on live agents, so they run against
260
+ a `Council` rebuilt from the record. Only `council_inject` still needs the live
261
+ engine, and it says so plainly when there isn't one.
262
+
263
+ Transcripts are still written to `~/.openclaw/council-logs/` for humans. Nothing
264
+ parses them.
265
+
266
+ ## Changed-file reporting
267
+
268
+ `council_review` used to diff `HEAD~20..HEAD` with a `HEAD~10` fallback: a magic
269
+ window unrelated to when the council started, which returned nothing at all on a
270
+ shallow or young history. It now diffs against the **merge-base** of `HEAD` and
271
+ the first `council/*` branch — the actual fork point — and includes files the
272
+ agents created, which a tracked-file diff cannot see.
273
+
274
+ `CouncilChangedFile.status` was previously hardcoded to `'clean'` for every
275
+ entry, which read as "reviewed and found fine" when nothing had looked at it. It
276
+ is now optional and left undefined until a reviewer assesses the file; the new
277
+ `change` field carries git's own account (`added` / `modified` / `deleted`).
278
+
279
+ ## Related
280
+
281
+ - [`verification.md`](./verification.md) — acceptance contracts
282
+ - [`workflow.md`](./workflow.md) — the council node inside a durable run
@@ -11,11 +11,11 @@ reverse proxy, e.g. `https://<your-host>/dash`).
11
11
 
12
12
  ## Tabs
13
13
 
14
- | Tab | Backed by | Launch endpoint |
15
- |---|---|---|
14
+ | Tab | Backed by | Launch endpoint |
15
+ | -------- | -------------------------------- | -------------------- |
16
16
  | Autoloop | `SessionManager.autoloopStart()` | `POST /autoloop/new` |
17
- | Council | `SessionManager.councilStart()` | `POST /council/new` |
18
- | Forge | `UltraappManager.createRun()` | `POST /ultraapp/new` |
17
+ | Council | `SessionManager.councilStart()` | `POST /council/new` |
18
+ | Forge | `UltraappManager.createRun()` | `POST /ultraapp/new` |
19
19
 
20
20
  Each tab has a `+ New` button in the sidebar. Council and Autoloop open a
21
21
  modal form (because they need workspace/task input); Forge POSTs an empty
@@ -89,11 +89,11 @@ authenticates only against your edge auth; the dashboard's own token stays
89
89
  inside the box.
90
90
 
91
91
  Example sasha-doctor pattern (matches the user-side setup):
92
+
92
93
  ```js
93
94
  // after the edge auth check passes:
94
95
  if (!req.headers.authorization) {
95
- req.headers.authorization =
96
- "Bearer " + fs.readFileSync("~/.openclaw/server-token", "utf-8").trim();
96
+ req.headers.authorization = 'Bearer ' + fs.readFileSync('~/.openclaw/server-token', 'utf-8').trim();
97
97
  }
98
98
  proxyHTTP(req, res, 18796);
99
99
  ```
@@ -121,6 +121,14 @@ the orchestrator re-attaches the Planner (reusing the persisted Claude
121
121
  session ID when available, so Claude's context picks up where it left
122
122
  off) and the dashboard reconnects to `/events` for live updates.
123
123
 
124
+ If the run used a **custom engine** for any role, the button first asks
125
+ `/autoloop/<id>/resume-requirements` and prompts for one reference name per
126
+ role — the name of a `CLAWO_CUSTOM_ENGINE_<NAME>` variable on the orchestrator
127
+ host. The config itself is never stored and never sent; only the name is. Until
128
+ this existed the button sent an empty body unconditionally, so a custom-engine
129
+ run was resumable from the library and the HTTP API but not from the UI that
130
+ offers the button.
131
+
124
132
  Runs that pre-date this feature have no `chat.jsonl` and no persisted
125
133
  session — they still resume cleanly, but with a blank Planner pane and a
126
134
  fresh Claude context. New runs going forward retain both.
@@ -170,3 +178,23 @@ launchctl kickstart -k "gui/$(id -u)/com.clawo.serve"
170
178
  # Then visit /login?token=$(cat ~/.openclaw/server-token)&redirect=/dash once
171
179
  # to refresh the cookie.
172
180
  ```
181
+
182
+ ## Runs tab (6.0.0)
183
+
184
+ A fourth tab listing durable workflow runs. Because runs are checkpointed to
185
+ disk, this sees runs started by other processes and by earlier sessions, not just
186
+ what the current server started.
187
+
188
+ Each row shows the run state and its verdict as one of three things:
189
+
190
+ - **verified** — an acceptance contract ran and passed.
191
+ - **refuted** — a contract ran and a required check failed.
192
+ - **unchecked** — no contract was declared. Rendered in neutral grey, not red:
193
+ an unchecked run is not a failed one, and colouring it like one would misreport
194
+ every run that simply never asked to be checked.
195
+
196
+ Opening a run shows per-node state (kind, attempts, visit count for loops, and
197
+ any error), the consensus votes when a council node ran — labelled advisory,
198
+ because they are recorded rather than used to decide completion — and the
199
+ evidence bundle: per-check pass/fail with the failing detail, the fix rounds
200
+ consumed, and how many files changed since the base commit.
@@ -68,8 +68,8 @@ The plugin does not manage authentication — it expects each CLI to be ready to
68
68
 
69
69
  The embedded HTTP server (used by CLI and standalone mode) optionally supports bearer token authentication:
70
70
 
71
- | Variable | Purpose |
72
- |----------|---------|
71
+ | Variable | Purpose |
72
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------- |
73
73
  | `OPENCLAW_SERVER_TOKEN` | Set to enable bearer token auth. All requests (except `/health`) must include `Authorization: Bearer <token>` |
74
74
 
75
75
  When set, the token is also written to `~/.openclaw/server-token` for the CLI to read automatically. Default: no auth (localhost binding is the primary security boundary).
@@ -83,11 +83,11 @@ The server exposes an OpenAI-compatible API at `/v1/chat/completions`. It serves
83
83
 
84
84
  Quick config for any client:
85
85
 
86
- | Setting | Value |
87
- |---------|-------|
88
- | API Base URL | `http://127.0.0.1:18796/v1` |
89
- | API Key | The value of `OPENCLAW_SERVER_TOKEN`, or any string if auth is disabled |
90
- | Model | `claude-fable-5`, `claude-opus-5`, `claude-sonnet-5`, `gpt-5.5`, `agy-pro`, etc. |
86
+ | Setting | Value |
87
+ | ------------ | -------------------------------------------------------------------------------- |
88
+ | API Base URL | `http://127.0.0.1:18796/v1` |
89
+ | API Key | The value of `OPENCLAW_SERVER_TOKEN`, or any string if auth is disabled |
90
+ | Model | `claude-fable-5`, `claude-opus-5`, `claude-sonnet-5`, `gpt-5.5`, `agy-pro`, etc. |
91
91
 
92
92
  See [openai-compat.md](./openai-compat.md) for the full session-keying rules, `X-Session-Reset` semantics, the legacy-heuristic env var, and the `/v1/sessions` inspection endpoint.
93
93
 
@@ -111,12 +111,12 @@ In `~/.openclaw/openclaw.json`:
111
111
  "proxy": {
112
112
  "enabled": false,
113
113
  "bigModel": "gemini-3.1-pro-preview",
114
- "smallModel": "gemini-3-flash-preview"
115
- }
116
- }
117
- }
118
- }
119
- }
114
+ "smallModel": "gemini-3-flash-preview",
115
+ },
116
+ },
117
+ },
118
+ },
119
+ },
120
120
  }
121
121
  ```
122
122
 
@@ -56,10 +56,10 @@ console.log(`Delivered ${count} queued messages`);
56
56
 
57
57
  ## Tools
58
58
 
59
- | Tool | Description |
60
- |------|-------------|
61
- | `session_send_to` | Send message between sessions |
62
- | `session_inbox` | Read inbox messages |
59
+ | Tool | Description |
60
+ | ----------------------- | --------------------------------------- |
61
+ | `session_send_to` | Send message between sessions |
62
+ | `session_inbox` | Read inbox messages |
63
63
  | `session_deliver_inbox` | Deliver queued messages to idle session |
64
64
 
65
65
  ## Message Format
@@ -29,17 +29,17 @@ This document covers:
29
29
 
30
30
  Tools fall into a few groups:
31
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` |
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
43
 
44
44
  Full per-tool parameter documentation lives in [`tools.md`](./tools.md).
45
45
 
@@ -69,9 +69,9 @@ mcp_servers:
69
69
  clawo:
70
70
  command: clawo-mcp
71
71
  env:
72
- ANTHROPIC_API_KEY: "..."
73
- OPENAI_API_KEY: "..."
74
- GEMINI_API_KEY: "..."
72
+ ANTHROPIC_API_KEY: '...'
73
+ OPENAI_API_KEY: '...'
74
+ GEMINI_API_KEY: '...'
75
75
  tools:
76
76
  include:
77
77
  - mcp_clawo_session_start
@@ -150,8 +150,8 @@ mcpServers:
150
150
  - name: clawo
151
151
  command: clawo-mcp
152
152
  env:
153
- ANTHROPIC_API_KEY: "..."
154
- OPENAI_API_KEY: "..."
153
+ ANTHROPIC_API_KEY: '...'
154
+ OPENAI_API_KEY: '...'
155
155
  ```
156
156
 
157
157
  ### Zed
@@ -193,7 +193,7 @@ extensions:
193
193
  type: stdio
194
194
  cmd: clawo-mcp
195
195
  envs:
196
- ANTHROPIC_API_KEY: "..."
196
+ ANTHROPIC_API_KEY: '...'
197
197
  ```
198
198
 
199
199
  ### Any other MCP host
@@ -214,14 +214,14 @@ Check your host's MCP docs for the exact key names (`command`/`cmd`, `env`/`envs
214
214
 
215
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
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 |
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
225
 
226
226
  The engines themselves (`claude`, `codex`, `gemini`, `agy`, `agent`, `opencode`) must also be installed and authenticated on the host machine — `clawo-mcp` spawns them as subprocesses, it does not bundle them.
227
227
 
@@ -255,40 +255,45 @@ For "let the model commission an ultrareview before merging":
255
255
 
256
256
  `clawo-mcp` advertises [tool annotations](https://modelcontextprotocol.io/specification/server/tools#annotations) so hosts can prefer safer tools when reasoning:
257
257
 
258
- | Annotation | Tools |
259
- |---|---|
258
+ | Annotation | Tools |
259
+ | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
260
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) |
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
263
 
264
264
  ---
265
265
 
266
266
  ## Troubleshooting
267
267
 
268
268
  **The host shows no tools after restart**
269
+
269
270
  - Confirm `clawo-mcp` resolves on PATH: `which clawo-mcp`. If you used a non-global install, use the absolute path in `command`.
270
271
  - Confirm the host logs (Hermes: `~/.hermes/logs/`, Claude Desktop: View → Open Logs Folder). Look for the `[clawo-mcp]` lines.
271
272
 
272
273
  **Engine starts but fails with `command not found`**
274
+
273
275
  - 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
276
 
275
277
  **`401` / `auth` errors from a session**
278
+
276
279
  - The corresponding API key is missing from the `env` block. Hosts do not inherit your shell environment.
277
280
 
278
281
  **Tool list comes back empty**
282
+
279
283
  - `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
284
 
281
285
  **Port 18796 in use error**
286
+
282
287
  - `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
288
 
284
289
  ---
285
290
 
286
291
  ## MCP vs OpenClaw plugin: when to use which
287
292
 
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
+ | Use case | Recommended form |
294
+ | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
295
+ | You already run OpenClaw and want the tools available to every OpenClaw agent | OpenClaw plugin |
296
+ | You want to drive coding agents from Hermes Agent, Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf, Goose, or another MCP host | MCP server |
297
+ | You want to call the orchestrator from a non-MCP custom runtime (Python, Go, …) | Standalone `clawo serve` HTTP API |
293
298
 
294
299
  The same package supports all three — they share the SessionManager and tool definitions. Pick whichever entry point matches your host.