Skip to content

Commit d833ff7

Browse files
georgiclaude
andcommitted
Merge branch 'claude/websocket-codeact-workflow-editing-7nqsxb'
feat(chat): run chat turns in CodeAct mode with a JS graph object model Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2 parents 37f10b4 + 7868fc2 commit d833ff7

10 files changed

Lines changed: 1218 additions & 29 deletions

File tree

docs/codeact-design.md

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,46 @@ The action executes with the same privileges tool mode already grants:
178178
- CLI: `nodetool agent run <yaml> --codeact`; the agent YAML also takes
179179
`execution_mode: codeact`. Flag > YAML > setting.
180180

181+
## Chat turns (websocket runner)
182+
183+
The chat websocket runner honors the same setting: when `resolveExecutionMode()`
184+
says `codeact`, a plain chat turn presents `execute_code` (plus `view_image`,
185+
the one channel that puts pixels into context and so cannot ride the JSON
186+
observation envelope) instead of the toolbelt, and the ToolSearch deferral
187+
machinery is replaced by the in-sandbox `searchTools()`. The adapter is
188+
`createChatCodeActSession` (`packages/agents/src/codeact/chat-codeact.ts`): a
189+
chat toolbelt mixes server tools with client (`ui_*`) tools that exist
190+
server-side only as schemas, so instead of `buildToolBridge` the session
191+
bridges `tools.<name>()` to the chat runner's own `executeTool` router —
192+
permission gating, client round-trips over the ToolBridge, and asset
193+
materialization all stay where they are. `state` persists across the turn's
194+
actions; there is no `finish()` — a plain assistant message ends the turn, and
195+
the prompt says so (`variant: "chat"` of `buildCodeActSystemPrompt`).
196+
197+
## Workflow graph editing: the JS object model
198+
199+
When the belt carries the `ui_*` workflow document tools, code actions get an
200+
object model instead of one bridged call per mutation
201+
(`packages/agents/src/codeact/graph-model.ts`):
202+
203+
```js
204+
const wf = await openWorkflow(workflowId);
205+
const input = wf.addNode("in1", "nodetool.input.StringInput", { name: "prompt" });
206+
wf.addNode("llm1", "nodetool.agents.Agent", {}, { x: 400, y: 120 });
207+
wf.connect("in1", "output", "llm1", "prompt");
208+
wf.node("llm1").setTitle("Draft").set({ system: "be brief" });
209+
await wf.commit();
210+
```
211+
212+
Mutators are synchronous: they update a local mirror (`wf.nodes`, `wf.edges`,
213+
`wf.node(id)`) and queue the equivalent `ui_*` operation. `commit()` replays
214+
the queue through the bridged tools — the same contract the renderer and the
215+
headless document tools implement, so routing, validation, and live-editor
216+
sync are untouched. A failed commit names the failing operation and keeps it
217+
(and everything after it) queued for a retry; removing a never-committed node
218+
cancels its queued ops instead of issuing a delete. Tests:
219+
`packages/agents/tests/chat-codeact.test.ts`.
220+
181221
## Evaluation
182222

183223
`eval codeact` (registered next to `subtask`): objectives with instrumented
@@ -203,5 +243,3 @@ finalization — no network, no model.
203243
action space, not about Python specifically.
204244
- Replacing planners. GraphPlanner/ScriptPlanner/CodePlanner already use
205245
code-shaped *artifacts*; this changes the step execution loop only.
206-
- The chat/websocket toolbelt. Chat turns keep tool mode; wiring codeact into
207-
the websocket runner is a follow-up once step-level evals justify it.

packages/agents/CLAUDE.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,19 @@ Design and the research it follows (CodeAct, ICML 2024): docs/codeact-design.md.
489489
`NODETOOL_AGENT_EXECUTION_MODE` environment variable pins the mode and wins
490490
over both. CLI:
491491
`nodetool agent run <yaml> --codeact` (YAML: `execution_mode: codeact`).
492+
- Chat turns honor the same setting: the websocket runner swaps the toolbelt
493+
for `execute_code` (+ `view_image`) via `createChatCodeActSession`
494+
(`src/codeact/chat-codeact.ts`), which bridges `tools.<name>()` to the chat
495+
runner's own tool router instead of `buildToolBridge` — permission gating
496+
and client (`ui_*`) round-trips stay where they are. When the belt carries
497+
the `ui_*` workflow document tools, actions also get the graph object model
498+
(`src/codeact/graph-model.ts`): `openWorkflow()` returns a model whose
499+
synchronous mutators queue ops against a local mirror and `commit()` replays
500+
them through the same `ui_*` contract.
492501
- Eval suite `codeact` runs the same offline instrumented cases through either
493502
executor for a mode comparison: `nodetool eval codeact -p <p> -m <m>`.
494-
- Tests: `tests/codeact-executor.test.ts`, `tests/codeact-eval.test.ts`
495-
(scripted provider, real sandbox, no network).
503+
- Tests: `tests/codeact-executor.test.ts`, `tests/codeact-eval.test.ts`,
504+
`tests/chat-codeact.test.ts` (scripted provider, real sandbox, no network).
496505

497506
## Script Mode (code-shaped orchestration)
498507

0 commit comments

Comments
 (0)