Implementation layout

The shared catalog and tool bridge retain policy ownership. Executors own JavaScript execution and continuation state. Node's node:vm is trusted execution, not a sandbox security boundary.

Rebuilding before_tool_call hooks must retain the surrounding execution wrappers in their original order. Caller authority, cancellation, activity, and run-lifetime checks enclose preparation and result finalization as well as the tool body. Execution wrappers register their rebuild function when copying tool metadata; schema-only copies preserve that registration.

Tool Search treats each published catalog entries array as an immutable descriptor snapshot. Registration, restriction, and executor rebinding replace that array; publish schema or description changes through the catalog owner. Search text is rendered lazily once per snapshot, and warm searches reuse the content-addressed lexical index. Visibility is checked on every search, including mutable permission sets, and BM25 statistics use only that effective inventory. Cached lexical data contains no tool executors.

Validation checklist

Code mode coverage should prove:

E2E test plan

Run these against both executors when changing the runtime:

  1. Start a Gateway with tools.codeMode.enabled: false.
  2. Send an agent turn with a small direct tool set.
  3. Assert the model-visible tools are unchanged.
  4. Restart with tools.codeMode.enabled: true.
  5. Send an agent turn with Apus, plugin, MCP, and client test tools.
  6. Assert the model-visible tool list is exec, wait, plus only configured direct-only tools.
  7. In exec, call safe bare globals and assert normalized, reserved, and colliding names match the quick index.
  8. Search catalog, inspect handle metadata/describe(), and call Apus/plugin/client handles without observing exact ids.
  9. In exec, call API.list("mcp") and API.read("mcp/<server>.d.ts") and assert the declaration files describe visible MCP tools.
  10. In exec, search by task intent across native and MCP tools, inspect the MCP handle's declaration, and call it. Verify normalized name collisions, exact namespaced lookup, bounded remote metadata, and the untrusted output wrapper. Direct MCP.<server>.<tool>({ ...input }) calls must agree, and catalog.all() must remain native after search.
  11. Assert denied tools are absent and cannot be called by guessed id.
  12. Start a nested tool call that resolves after exec returns waiting.
  13. Call wait and assert the continued context receives the tool result.
  14. Assert the final answer contains output produced after resume without replay.
  15. Assert timeout, abort, and continuation expiry clean up runtime state.
  16. 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.