Single Agent Patterns: Code as Action
Intent
Use executable code rather than a fixed tool vocabulary as the agent's action space. Because code composes—loops, conditionals, variables—a single action can express what would otherwise take many discrete tool calls.
Introduction
Traditional agent architectures rely on a predefined JSON tool schema vocabulary (e.g., search_web(), fetch_url(), calc()). When a task requires iterating through 50 data records, filtering items, and aggregating numerical statistics, a standard ReAct loop must make 50 individual LLM reasoning turns—one for each tool invocation. This results in extreme latency, massive token consumption, and risk of context drift. The Code as Action pattern replaces rigid tool calls by empowering the agent to write and execute full code scripts (such as Python or JavaScript) directly in a runtime interpreter, turning code itself into the action space.
Collapsing Round-Trips via Expressive Composition
Code is inherently composable. It natively supports control flow primitives—for loops, if/else branches, local variables, and module imports. By generating code, an agent can perform multi-step data manipulation inside a single execution turn:
- Turn Compression: What would require 20 discrete tool-use round-trips collapses into 1 code generation step and 1 execution return.
- Exact Arithmetic & Transformation: Offloads math, string manipulation, data sorting, and parsing to the runtime environment, bypassing LLM floating-point arithmetic hallucinations.
- Dynamic Library Integration: The agent can import standard libraries (e.g.,
pandas,requests,json) to solve unforeseen algorithmic subproblems dynamically.
Mandatory Security Coupling with Sandboxing
Using code as an action space significantly increases the system's attack surface. Allowing an LLM to generate and execute unrestricted shell commands or Python scripts on a host system is an existential risk. Consequently, the Code as Action pattern is tightly coupled with Sandboxing and Permissioning. The code interpreter must execute inside isolated microVMs, with restricted disk mounts and network egress controls to prevent accidental or malicious system compromise.
Trade-offs
Adopting Code as Action yields immense performance and flexibility, but introduces specific execution risks:
Massive Turn Compression
Collapses complex loops, filtering, and multi-file processing from dozens of ReAct turns into a single code generation step.
Exact Calculation & Parsing
Offloads mathematical computations, data transformations, and regex parsing to a deterministic programming language runtime.
Enlarged Attack Surface
Requires strict microVM sandboxing, egress proxies, and resource timeout enforcement to prevent code execution vulnerability exploitation.
Silent Partial Failures
A script that partially succeeds (e.g. processes 10 of 20 files before crashing) can leave the environment in an inconsistent state.
Known Uses
Code as Action is widely used in state-of-the-art coding and reasoning agents:
- CodeAct: Framework demonstrating that using executable Python code as actions improves agent task completion over structured JSON tool calling [1].
- Voyager: Minecraft agent that generates, executes, and stores verified JavaScript skills to complete complex long-horizon tasks [2].
- OpenAI Code Interpreter / Advanced Data Analysis: Native sandboxed Python interpreter mode allowing LLMs to execute code for data analysis and visualization.
References
-
[1]
Wang, X., Chen, Y., Yuan, L., Zhang, Y., Li, Y., Peng, H., & Ji, H. (2024). Executable Code Actions Elicit Better LLM Agents (CodeAct). arXiv preprint arXiv:2402.01030.
https://arxiv.org/abs/2402.01030 -
[2]
Wang, G., Xie, Y., Jiang, Y., Mandlekar, A., Xiao, C., Zhu, Y., Fan, L., & Anandkumar, A. (2024). Voyager: An Open-Ended Embodied Agent with Large Language Models. Transactions on Machine Learning Research (TMLR).
https://arxiv.org/abs/2305.16291