To course

The agent loop

One step of an agent loopPractice: one step of the loopThe loop in codePractice: the loop in codeStopping and retryingPractice: stopping and retryingWhat only code can decidePractice: what code decides

Reliability in production

Timeout and idempotency keyPractice: timeout and idempotency keySays done, but nothing happenedPractice: false successDurable agent: checkpoints and resumePractice: durable agent

Agent designs

Workflow or agentPractice: workflow or agentReAct and plan-and-executePractice: ReAct and plan-and-executePlan-and-SolvePractice: Plan-and-SolveReflexionPractice: ReflexionOne agent or a swarmPractice: one agent or a swarm

Context and cost

Why the agent bill growsPractice: tokens and cacheContext engineeringPractice: managing the windowAgent memoryPractice: what the agent keeps

Tools and protocols

MCPPractice: MCPTool descriptions and injectionPractice: tool descriptions and injectionCode instead of a toolsetPractice: code instead of a toolsetAgent skills and A2APractice: agent skills and A2A

Frameworks

LangGraph or the raw loopPractice: LangGraph or the raw loopAgent SDKs: what you are buyingPractice: agent SDKs

Coding agents

Driving a coding agent from a specPractice: driving a coding agent from a spec
←→RUSign in
Agents › Tools and protocolsDeep dive

Code instead of a toolset

Builds onMCP

This block compares two ways an agent can use tools: one call at a time, or a script the model writes. It shows where each costs tokens, where code loses, and which checks have to move when you let the model write code. Vendors call this code mode or programmatic tool calling.

Northwind needs every order delayed more than five days last month, out of 10,000 rows, with a follow-up task in the CRM for each one with carrier NorthPost.

Read me the whole ledger, or follow my list

On the phone, your colleague says "read me the ledger" and you read 10,000 rows aloud. They listen to all of it, pick out 312, and ask for 312 follow-ups, one per call, each time with the whole conversation repeated from the top.

Or your colleague dictates a short list: "go through the ledger, keep these rows, open a task for each, tell me how many." You carry it out in a locked back room and phone back with two numbers.

With tool calls, the data crosses the model. With code, it stays in the sandbox and only the printed output comes back.
With tool calls, the data crosses the model. With code, it stays in the sandbox and only the printed output comes back.

What happens, step by step

On Anthropic's API, this is programmatic tool calling. You mark which tools the script may call:

{
  "name": "list_orders",
  "description": "Lists orders for a month with status and carrier.",
  "input_schema": {
    "type": "object",
    "properties": {
      "month": {
        "type": "string"
      }
    },
    "required": [
      "month"
    ]
  },
  "allowed_callers": [
    "code_execution_20260120"
  ]
}
  1. The model writes Python in which list_orders is an async function. It takes a single dict and returns a string.
  2. The script runs in a sandboxed container.
  3. When the script calls a tool, it pauses, and the API returns a tool_use block to your code. Its caller field names the code execution run.
  4. Your code runs the tool and sends back a tool_result. The script resumes, and the result does not enter the model's context.
  5. When the script ends, the model gets its output and continues.

The script itself might look like this:

rows = json.loads(await list_orders({"month": "2026-10"}))
late = [r for r in rows
        if r["carrier"] == "NorthPost" and r["days_late"] > 5]
for r in late:
    await create_task({"order_id": r["order_id"], "kind": "follow_up"})
print(len(rows), len(late))

The model reads two numbers. Cloudflare's Code Mode follows the same idea with generated JavaScript in a V8 isolate. Details differ per product: on Anthropic's API, for instance, tools from an MCP connector cannot be called this way, and strict: true tools are not supported.

What it saves, and when it does not

A result sent back to the model is read again on every later turn, so sequential calls add up fast. The chart uses a 12,000-token prefix, no caching, and our own arithmetic.

Input tokens summed over a run. Code wins by a wide margin on many independent lookups, and loses slightly on two small dependent calls. Each group has its own scale.
Input tokens summed over a run. Code wins by a wide margin on many independent lookups, and loses slightly on two small dependent calls. Each group has its own scale.

Parallel calls close much of the gap, and they need no sandbox. With two small dependent calls, the model must see the first result before it can write the second call, so the script saves no turn.

Published numbers vary with the task, so read who chose it:

Source

Task

Result

Anthropic post

A hypothetical Drive to Salesforce flow

150,000 to 2,000 tokens

Cloudflare

Whole Cloudflare API in two tools

1.17M to about 1,000 tokens of tool definitions

Anthropic docs

75-tool benchmark

About 38% fewer billed input tokens, same accuracy

Anthropic docs

τ²-bench, one or two sequential calls per turn

Same scores, about 8% more cost

The vendor examples are favorable cases. Quality depends on the model and the chain. In one August 2026 preprint, on a 309-task subset of BFCL v4, code matched or beat JSON calls in 11 of 14 models, while three older GPT models fell behind. In its 52-task chaining test, the advantage reached 18.8 points at chains of 12 or more steps and did not appear on short chains.

Who is watching now

With tool calls the model sees each result and picks the next step. With a script it writes the plan once, and a loop can issue 500 refunds in one turn while the model reads none of the results. How much your code sees depends on the product. On Anthropic's API each call still pauses and comes to your code. Cloudflare's codeMcpServer calls upstream handlers from inside one outer code tool, and its docs say to enforce authorization and approval in each handler.

The script can call whatever it can reach. Limits and credentials live on the other side of the boundary.
The script can call whatever it can reach. Limits and credentials live on the other side of the boundary.

So the rules from the refund block stay in the tool, and two get added.

Treat the code as untrusted. An injection the model read earlier can shape the script, and Anthropic says running generated code needs sandboxing, resource limits and monitoring. Hugging Face says no local Python sandbox can be completely secure, so an interpreter inside your own process does not count as a boundary. allowed_callers is not one either: Anthropic's docs say not to rely on it as a security boundary.

How to choose

Tool calls

Code

Good fit

Few tools, single steps

Many tools, big results, long chains, loops

Infrastructure

None extra

Sandbox, limits, network control

Oversight

The model reads each result

The check is in the tool

The choice can be per tool. Northwind's list_orders goes through code. issue_refund stays a direct tool with its own checks, because someone should see each refund.

Conclusion

Go deeper

Code execution with MCP (Anthropic)The main argument, and the closing note on the cost of a sandbox.Programmatic tool callingField names, the pause and resume flow, limits and measured savings.Code Mode (Cloudflare)Why models may write code better than tool calls.Build a Code Mode MCP serverWhere the authorization check has to live in that design.Secure code execution (Hugging Face)Where the risks of running generated code come from.
‹ Previous
Suggest an improvementFound a mistake