The pattern seemed obvious at first: give an AI agent a list of tools, let it pick the right one for each step, and watch it work through the task. That model has served us well for simple workflows — look up a record, write a file, send a message. But as agents get assigned more complex jobs, the cracks are starting to show.
The hidden cost of tool calls
Every time an agent invokes a tool, it pays a round-trip fee: the inference request goes out, the result comes back, and only then can the agent decide what to do next. At 300 to 500 milliseconds per hop, a ten-step operation becomes a multi-second wait. For a chatbot answering a question, that is acceptable. For an agent running inside a collaborative document — where the data structure it is editing might be modified by another user between steps — it starts to break things.
There is a subtler cost too. Tools are declarations: every tool the agent might need has to be described upfront, sitting in the context window (the working memory the model reads from) taking up space. Dozens of tools means a bloated context before the agent has done anything useful.
Writing code instead
Code mode flips the design. Rather than picking from a menu of predefined tools, the agent writes a block of code — in JavaScript, Python, or whatever the host environment supports — and executes it in one shot. The code can call multiple operations, filter results, chain transformations, and handle conditional logic, all without going back to the inference layer between steps.
The simplest version of this is already familiar: the bash tool that many AI coding assistants expose, where the agent writes shell commands and reads the output. Code mode extends that logic to richer, sandboxed runtimes.
Three things make it genuinely useful rather than just technically interesting:
– Speed. Multi-step operations run at code speed rather than inference speed. The round-trips disappear.
– Token efficiency. The agent does not need a definition for every possible tool pre-loaded into its context. It discovers what is available by writing code against an injected SDK — the same way a developer would explore an unfamiliar library.
– Composability. Filtering, mapping, reducing, chaining — these are native to code and awkward to express as sequential tool calls.
Where it makes sense (and where it does not)
The use cases that benefit most are predictable once you know the tradeoff: workflows with dozens of possible operations, where pre-loading all tool definitions is impractical; multi-step operations over data structures that can change mid-execution; and tasks that draw on libraries the model already knows well from training — standard SDKs, well-documented frameworks. If the agent already knows how to write against the library, designing a custom wrapper on top of it is unnecessary work.
A concrete example: an agent editing a CRDT (a data structure used for collaborative real-time editing, like the internals of Google Docs) faces exactly this problem. Traversing and modifying the document requires many sequential operations. With sequential tool calls, the document may have been edited by someone else before the agent finishes — and round-trip latency compounds the risk. Writing a single block of code that traverses and mutates the structure in one pass sidesteps both problems.
The runtime in that case was QuickJS — a lightweight JavaScript engine that runs sandboxed, isolated from the host system. Only explicitly injected functions are accessible to the agent-generated code; prototype access is blocked to prevent a class of JavaScript security vulnerabilities known as prototype pollution. If the code fails, the agent receives the error and captured log output and can retry.
That sandboxing concern is worth dwelling on. Code mode is not a universal upgrade. Letting an agent write and execute arbitrary code raises real security questions, especially in multi-tenant environments where untrusted code must be kept away from host-process state. The engineering work to do it safely — sandboxing, permission models, timeout enforcement — is non-trivial. Code mode trades simplicity for power, and the tradeoff is real.
Type safety on top
One direction the tooling is moving: catching errors before the code runs, not after. If the agent generates code with a type mismatch — passing a single value where a list is expected, or generating a class that does not satisfy a required interface — a compiler can catch that before any side effects happen. Compilation overhead at this scale is measured in tens of milliseconds, which is acceptable. The practical payoff is a tighter error-feedback loop and fewer cases where an agent silently does the wrong thing.
The longer arc here points toward agent-generated code as a first-class runtime artifact: sandboxed, type-checked, inspectable, and recoverable. That is a more robust foundation than a long list of tool definitions — and probably where the practice lands for the complex, stateful agent work that is increasingly what practitioners are actually building.
Text summarized and optimized using Anthropic’s models and reviewed by a human.