Why Code-Executing Agents Are More Efficient: From Tool Calls to Programmatic Orchestration

    Code-executing agents shift AI systems from step-by-step tool invocation to generating programs that orchestrate tools, data, and control flow. This approach can reduce context overhead, limit unnecessary model round trips, improve support for complex workflows, and make agent behavior more controllable. This article explains the architectural differences, practical benefits, tool design requirements, security considerations, and the types of tasks best suited to code execution.

    As agent systems connect to more external data sources and business systems, one issue becomes increasingly clear: connecting a model to more tools does not automatically make it more capable. When large numbers of tool definitions, parameter descriptions, and intermediate results enter the context at once, reasoning efficiency, response time, and operating cost can all suffer.

    A growing approach is to upgrade from direct tool calling to writing and executing programs. Instead of moving every piece of data through the model step by step, the model uses code to organize tools, process results, and control execution flow. This may appear to be only a change in invocation style, but it affects agent architecture, context management, data movement, and security isolation.

    Why Traditional Tool Calling Creates Context Overhead

    In a common agent design, the system provides the model with the names, purposes, parameter schemas, and return formats of all available tools. After receiving a user task, the model selects an appropriate tool and generates the required parameters.

    A typical workflow looks like this:

    1. Put a large set of tool descriptions into the model context.
    2. The model selects a tool and generates parameters.
    3. The tool executes and returns a result.
    4. The result is written back into the context.
    5. The model reads the result and decides what to do next.
    6. The process repeats until the task is complete.

    This pattern is intuitive for simple tasks, such as checking a status, retrieving a record, or performing a calculation. However, its limitations grow quickly when a task spans multiple systems, long documents, and complex control logic.

    1. Tool Definitions Consume Significant Context

    If an agent connects to several business systems, and each system exposes dozens or more tools, the parameter descriptions, field types, permission rules, and response schemas can become substantial.

    Even for a simple request, the model may need to process many definitions that are unrelated to the task. This increases input length and reduces the proportion of useful information. As the number of tools grows, models are more likely to:

    • Select a similar but unsuitable tool
    • Omit required parameters
    • Confuse fields with different meanings across systems
    • Gradually drift away from the task objective during multi-step execution

    2. Intermediate Data Is Repeatedly Moved Through the Model

    Consider a task that retrieves a lengthy meeting transcript from one data system and writes it into another business system. A traditional flow might be:

    • Call an API to retrieve the document
    • Return the complete text to the model
    • Have the model generate write parameters containing the full text
    • Call another API to submit the content to the destination system

    In this process, the model performs a large amount of copying and forwarding. It may not need to understand or transform all of the content, yet the long text still passes through the context multiple times. The larger the dataset, the more wasteful this becomes.

    3. Multi-Step Tasks Require Frequent Model Participation in Control Flow

    Loops, conditional branches, batch processing, and retry logic are often handled through repeated natural-language prompts in traditional tool-calling systems. For example, the model may first retrieve a set of records, then evaluate whether each record meets a condition, and finally decide whether to update it.

    This type of control flow is fundamentally program logic. If it is entirely delegated to the model, the system produces more back-and-forth interactions, and every step is affected by the uncertainty of model output.

    The Core Shift in Code-Executing Agents

    Code-executing agents do not eliminate tools. They change how tools are used.

    External systems still expose capabilities as tools or services, but the model writes a program that coordinates those capabilities. Tool results can move directly within the execution environment. Only content that genuinely requires model judgment, summarization, or generation needs to enter the model context.

    For example:

    1. import * as source from "./services/source-system";
    2. import * as target from "./services/target-system";
    3. async function runTask() {
    4. const record = await source.fetchDocument({
    5. id: "document-id"
    6. });
    7. const content = record.text;
    8. await target.createEntry({
    9. type: "meeting-note",
    10. fields: {
    11. content
    12. }
    13. });
    14. }
    15. await runTask();

    The key point is not the syntax. It is the change in data flow:

    • Tool capabilities are provided as callable modules.
    • The model generates the program and control flow.
    • Data moves from one function to another inside the execution environment.
    • The model does not need to read and reproduce all intermediate content.

    The model shifts from personally moving data at every step to designing a program that lets the runtime move the data.

    Key Benefits of This Architecture

    1. Lower Context Consumption

    Traditional systems continuously place tool definitions and tool results into context. Code execution can instead use on-demand loading. The model only needs to understand the modules and functions relevant to the current task, rather than reading every available tool description upfront.

    For long documents, large datasets, and cross-system workflows, intermediate data can remain in the execution environment. This significantly reduces irrelevant content in the context.

    Code execution does not eliminate context cost entirely. The model still needs to understand the task, select functions, and generate code. However, compared with repeatedly receiving and reproducing large blocks of data, the data path is much more efficient.

    2. Better Support for Complex Control Flow

    Programs naturally support:

    • Conditional logic
    • Loops
    • Parallel execution
    • Error handling
    • Timeouts
    • Batch submission
    • Result filtering
    • State tracking
    • Retries and rollback

    For example, batch retrieval and filtering can be handled in the execution environment:

    1. const items = await source.listItems({ limit: 1000 });
    2. const selected = items.filter(item => {
    3. return item.status === "pending" && item.score >= 80;
    4. });
    5. for (const item of selected) {
    6. await target.updateItem({
    7. id: item.id,
    8. status: "processed"
    9. });
    10. }

    With pure tool calling, the model might need to inspect records one by one, evaluate conditions, and issue individual update requests. With code, deterministic filtering and iteration are handled by the program, while the model focuses on generating the overall strategy.

    3. Fewer Model Round Trips

    In a multi-step workflow, every cycle of model reasoning, tool invocation, and returned result adds another interaction. More interactions increase response time and make state management more complex.

    Code execution can combine multiple steps into a single program:

    1. const data = await source.loadData();
    2. const normalized = normalize(data);
    3. const groups = groupByCategory(normalized);
    4. for (const [category, records] of Object.entries(groups)) {
    5. await target.saveBatch({
    6. category,
    7. records
    8. });
    9. }

    Each program step may still call an external service, but the model does not need to re-enter the loop between every step. This reduces unnecessary reasoning rounds and preserves model resources for tasks that require understanding and decisions.

    4. Greater Task Expressiveness

    Natural language is well suited to describing goals, but it is not always precise enough for complex execution procedures. Code can clearly express variables, dependencies, and execution order.

    For example, a request to retrieve all matching data, remove duplicates, group records by category, write each group to a target system, and retry failures can be ambiguous in natural language. A program can define exactly how every stage should work.

    This makes the agent more like a program generator:

    • The model translates a natural-language objective into an execution plan.
    • Code implements the deterministic workflow.
    • External services perform real operations.
    • Results return to the model for explanation or summarization when needed.

    Tool Design Must Evolve from Interfaces to Modules

    For code-executing agents to deliver real value, tools should provide more than isolated callable endpoints. They need clear module boundaries and stable data structures.

    1. Provide Semantically Clear Functions

    Function names and parameters should accurately communicate their purpose. Avoid making one function responsible for too many tasks. Reading, updating, and deleting data should be designed as separate operations to reduce the risk of misuse.

    2. Keep Return Structures Stable

    If the same function returns entirely different fields in different situations, model-generated code is more likely to fail. Return values should use consistent data structures and clearly define empty values, errors, pagination, and related cases.

    3. Support Batch Operations

    For data-intensive tasks, tools should prioritize batch reads, batch updates, or pagination. This prevents the model from generating large numbers of repetitive calls.

    4. Expose Necessary Capabilities, Not Everything

    More tools are not always better. Exposing too many internal interfaces increases selection difficulty for the model and expands security risk. A better approach is to provide the minimum required capability set for a task and load modules on demand.

    Code Execution Does Not Remove Security Risks

    Although code execution improves efficiency, it also introduces new security challenges. Model-generated code is dynamic, and without appropriate constraints, it may perform actions beyond what was intended.

    A production system should consider at least the following measures.

    1. Isolate the Execution Environment

    Code should run in a restricted sandbox or isolated container. File access, network access, process creation, and system-call permissions should be limited. The runtime should not directly expose sensitive host resources.

    2. Apply Fine-Grained Access Control

    Every tool and data category should have clear permission boundaries. Read and write permissions should be separated, while high-risk actions should support human confirmation.

    3. Validate Parameters and Audit Operations

    Even when code is generated by a model, the tool layer must validate parameters. The system should log the caller, invocation time, input parameter summaries, execution results, and exception details for troubleshooting and traceability.

    4. Enforce Resource Limits

    Limit execution time, memory, invocation counts, and output size for each task. This helps prevent resource exhaustion caused by infinite loops, repeated retries, or large-scale data retrieval.

    5. Add Confirmation Steps for High-Risk Actions

    Operations involving deletion, bulk modification, funds, permissions, or sensitive data should not depend solely on model judgment. A two-stage process can be used: generate a plan, request user confirmation, and then execute it.

    Tasks That Benefit Most from This Approach

    Code-executing agents are especially suitable for:

    • Data synchronization across multiple business systems
    • Filtering and transforming long documents or large datasets
    • Automation workflows involving loops, conditions, and retries
    • File parsing, format conversion, and batch processing
    • Tasks requiring programmatic calculations on intermediate results
    • Complex environments with many tools that must be discovered on demand

    For simple question answering, one-time lookups, or low-risk single-step actions, direct tool calling is often simpler. Architecture should not become more complex by default. The right choice depends on task uncertainty, data volume, and control-flow complexity.

    Implications for Agent Design

    The real value of code-executing agents is not simply saving a few context-window tokens. It is a clearer division of responsibilities between the model and the program.

    Models are good at:

    • Understanding natural-language goals
    • Identifying task intent
    • Creating execution plans
    • Selecting appropriate capabilities
    • Explaining final results

    Programs are good at:

    • Moving and transforming data
    • Executing loops and conditions
    • Handling deterministic logic
    • Managing errors and retries
    • Making workflows reproducible

    A strong agent system should not force the model to do everything. The model should handle the parts that require intelligence, while repetitive, deterministic, and scalable work is delegated to code.

    From this perspective, the future of agents is not simply about adding more tools. It is about building a more rational execution system: tools can be discovered as needed, data can move through controlled environments, complex workflows can run reliably as programs, and models can focus on understanding, planning, and decision-making.

    This is why code-executing agents have long-term value. They combine the flexibility of language models with the determinism of traditional programs, reducing context pressure while improving the controllability, maintainability, and production readiness of complex tasks.