Direct function calling works well when an agent needs one or two known operations. Longer tasks can require loops, joins, filtering, and dependent calls. Sending every intermediate result back through the model adds turns and context.
Code mode is an alternative tool-use pattern: the model writes a small program that calls approved tools and processes their results inside an execution environment. The program is a plan, not an escape from the tool system.
Cloudflare's Code Mode documentation makes this distinction explicit. Configured tools appear as typed methods; generated code can compose them, filter intermediate data, and return a smaller result. Direct calls remain the simpler choice for small, fixed tool sets.
What the pattern changes
Suppose an agent must inspect open issues, find the files they mention, run a repository query for each file, and summarize the overlap. With direct tool calls, each result may require another model turn. With code as the interface, one bounded program can:
- fetch the approved issue records;
- extract and deduplicate paths;
- query the repository service for those paths;
- discard irrelevant fields; and
- return a compact evidence object.
This can reduce model round trips and keep bulky intermediate data outside the model context. It also makes ordinary control flow—loops, conditions, grouping, and error handling—available without defining a separate tool for every combination.
It does not remove external calls. The generated program still invokes configured tools, APIs, or libraries. Their schemas, permissions, rate limits, and failures still apply.
Typed, narrow surfaces
Expose the smallest useful interface. A typed method such as searchRepository({query, commit, limit}) is safer and easier to validate than a raw credential or unrestricted network client.
For every callable surface, define:
- input and output schemas;
- maximum result size;
- timeout and retry behavior;
- read or write classification;
- tenant and workspace scope;
- approval requirement; and
- audit fields.
Validate arguments at the boundary even when TypeScript or another static type system generated the client. Generated code is untrusted at runtime, and static types do not enforce authorization.
Isolation is a runtime property
Do not run model-generated code in the application process and call it a sandbox. Node.js documentation explicitly warns that node:vm is not a security mechanism for untrusted code.
A production sandbox should isolate the filesystem, processes, network, and resources according to the task. Cloudflare's Sandbox SDK, for example, documents per-sandbox VM isolation plus CPU, memory, and disk limits. OpenAI's Agents SDK sandbox model uses manifests and capabilities to define workspace inputs and available operations.
Isolation still needs policy:
- mount only required files;
- use short-lived, scoped credentials;
- deny network access by default or allowlist destinations;
- cap CPU, memory, disk, output, and runtime;
- run as an unprivileged identity; and
- discard or snapshot the workspace according to retention rules.
Processes inside one sandbox may share its resources. Do not place mutually untrusted tenants in the same boundary.
Separate computation from side effects
Code that transforms retrieved data is lower risk than code that deploys, pays, deletes, or messages. Keep external side effects behind explicit tools so the host can enforce approvals and idempotency.
A useful execution plan returns structured evidence and a proposed action. The host can then show the exact action to a human or apply deterministic policy before invoking the mutating tool.
Replay and audit
Record the program, tool versions, inputs or hashes, outputs, approvals, resource usage, and terminal status. Redact secrets and sensitive content. Replay is reliable only when dependencies and inputs are pinned; calling a live API again is a new execution, not a deterministic replay.
When not to use it
Prefer direct tool calls when the task has a few predictable steps, each result needs model judgment, or the sandbox overhead exceeds the saved turns. Use code mode for data-heavy composition, repeated calls, branching, or result shaping.
The design goal is not arbitrary code execution. It is bounded programmable composition over capabilities the host already understands and controls.