Tools
Code Mode maintainer notes
Implementation layout
- config contract:
tools.codeMode - catalog builder: effective tools to compact entries and id map
- model-surface adapter: replace visible tools with control/direct tools
- QuickJS-WASI runtime adapter: load, eval, snapshot, restore, dispose
- worker supervisor: timeout, abort, crash isolation
- bridge adapter: JSON-safe host callbacks and result delivery
- TypeScript transform adapter
- snapshot store: TTL, size caps, run/session scoping
- trajectory projection for nested tool calls
- telemetry counters and diagnostics
The implementation reuses catalog and executor concepts from Tool Search, but
does not use a node:vm child as the sandbox.
Validation checklist
Code mode coverage should prove:
- disabled config without an enabling override leaves existing tool exposure unchanged
- omitted
enabled, including object config that sets other fields, stays disabled unless an agent or model override enables it - per-model
true,false, and unset values preserve activation precedence, fallback-model selection, and limits from the enclosing options - enabled config exposes
exec,wait, and only required direct-only tools to the model when tools are active for the run - raw no-tool runs,
disableTools, and empty allowlists do not trigger code-mode payload enforcement - every catalog-eligible effective non-MCP name has one callable winner
- direct-only tools stay model-visible and do not appear in
catalog - denied tools have no global or catalog handle
- bare globals, callable
catalog.searchresults,catalog.all, and handledescribe()work for OpenClaw and client tools without exposing exact ids API.list("mcp")andAPI.read("mcp/<server>.d.ts")expose TypeScript-style MCP declarations without a bridge/tool call- MCP namespace
$api()remains available as an inline fallback for schemas - MCP namespace calls work for visible MCP tools with one object input, while
direct MCP entries are absent from generic
catalogdiscovery - Tool Search control tools are hidden from both the model surface and the hidden catalog
- nested calls preserve approval and hook behavior
- caught and uncaught nested failures remain recoverable without replaying previously executed side effects
- network-controlled failures retain untrusted-content wrapping and sanitization
- shell
execis hidden from the model but callable as a guest global when allowed - recursive code-mode
execandwaitare not callable from guest code - TypeScript input is transformed and evaluated without loading TypeScript on disabled or JavaScript-only paths
import,require, filesystem, network, and environment access fail- infinite loops time out and cannot block the Gateway
- memory cap failures terminate the guest VM
- output and snapshot caps are enforced for completed and suspended calls
waitresumes a suspended snapshot and returns the final value- expired, aborted, wrong-session, and unknown
runIdvalues fail - transcript replay and persistence preserve code-mode control calls
- transcript and telemetry show nested tool calls clearly
E2E test plan
Run these as integration or end-to-end tests when changing the runtime:
- Start a Gateway with
tools.codeMode.enabled: false. - Send an agent turn with a small direct tool set.
- Assert the model-visible tools are unchanged.
- Restart with
tools.codeMode.enabled: true. - Send an agent turn with OpenClaw, plugin, MCP, and client test tools.
- Assert the model-visible tool list is
exec,wait, plus only configured direct-only tools. - In
exec, call safe bare globals and assert normalized, reserved, and colliding names match the quick index. - Search
catalog, inspect handle metadata/describe(), and call OpenClaw/plugin/client handles without observing exact ids. - In
exec, callAPI.list("mcp")andAPI.read("mcp/<server>.d.ts")and assert the declaration files describe visible MCP tools. - In
exec, call MCP tools throughMCP.<server>.<tool>({ ...input })and assert direct MCP entries are absent fromcatalog.search()andcatalog.all(). - Assert denied tools are absent and cannot be called by guessed id.
- Start a nested tool call that resolves after
execreturnswaiting. - Call
waitand assert the restored VM receives the tool result. - Assert the final answer contains output produced after restore.
- Assert timeout, abort, and snapshot expiry clean up runtime state.
- Export trajectory and assert nested calls are visible under the parent code-mode call.
Docs-only changes to this page should still run pnpm check:docs.
Was this useful?