Cloudflare's API has thousands of endpoints. If you exposed each one as a separate MCP tool, the tool definitions alone would fill the model's context before the agent got to the user's request. Cloudflare's answer was to give agents the entire Cloudflare API through two tools, search() and execute(). The agent searches the API spec for the operations it needs, writes a short program, and runs it in a sandbox. Only the result comes back to the model.

Datadog shipped a similar mode for its MCP server, and Anthropic's engineering team described the general pattern months earlier. This post covers how search and execute works, how the Cloudflare and Datadog versions differ, a worked example of the same task done both ways, and the security decisions you need to make before giving an agent an execute tool.

For MCP basics, see AI Agents Part 4: MCP. For why large toolsets hurt agents, see why more MCP tools can make agents worse.

What Search and Execute Changes

A standard MCP server describes each operation as a separate tool, with a name, a description, and a JSON schema. The client loads those definitions into the model's context. Each time the model calls a tool, the full response also enters the context, and the model has to read it to decide what to do next.

That is fine for ten tools. It breaks down in two places as an API grows:

  1. Definition cost. Every tool schema uses context on every turn, including the many the agent will never call.
  2. Intermediate results. A task that lists 40 resources and checks each one sends all 40 responses through the model, even though the user wanted three lines of output.

Anthropic's post on code execution with MCP addresses both. It presents MCP servers to the model as code APIs and lets the model write a program that calls them. In Anthropic's example, a Google Drive transcript is copied into Salesforce. Token usage drops from about 150,000 to about 2,000 because the transcript passes between tools inside the execution environment and never enters the model's context. That figure comes from one workflow chosen to show the effect. Use it as an illustration, not as a benchmark for your workload.

Search and execute splits that idea into two steps:

Step What the agent does What enters the model's context
Discovery Queries the API description (spec or SDK docs) Only the matching operations
Execution Writes code that calls, loops, filters, and aggregates Only the value the code returns

The model still does the reasoning. It decides what to look for, which endpoints matter, and how to filter. The difference is that loops and filtering run as code instead of through repeated rounds of model calls.

Cloudflare vs. Datadog: Same Pattern, Different Surfaces

The two vendors use different names and point discovery at different things. That matters if you are writing agent instructions or evaluating which server fits your stack.

Cloudflare: search() and execute(). In Cloudflare's design, search() runs agent-written JavaScript against the Cloudflare OpenAPI specification. The spec stays on the server, and the agent queries it like a data structure (for example, "find paths containing dns_records"). execute() runs JavaScript that makes authenticated requests to the Cloudflare API inside a Workers isolate. The Cloudflare Agents guide on building a search and execute MCP server walks through building the same kind of server from your own OpenAPI spec. If your internal API already has a decent spec, that guide is the most direct starting point.

Datadog: search_datadog_sdk and execute_code. Datadog points discovery at its SDK instead of a raw OpenAPI document. Per the Datadog MCP Server code execution docs, the agent searches SDK methods and then runs code that uses them. An SDK surface gives the model typed methods and built-in pagination helpers, which can make generated code shorter and less fragile than hand-built HTTP requests. A raw spec covers every endpoint the API exposes, including ones the SDK may not wrap. Check Datadog's docs for current availability and supported clients before planning around it, because preview features change.

Datadog's earlier engineering post, Designing MCP tools for agents, is useful even if you never turn on code execution. It treats the context window as the main constraint. It argues for tighter output formats than verbose JSON, for pagination and truncation based on how much context a response uses rather than on record counts, and for error messages that tell the agent what to try next. Those lessons improve ordinary tools, and they apply to the result your execute code returns.

Cloudflare Datadog
Discovery tool search() search_datadog_sdk
Discovery target OpenAPI spec SDK methods
Execution tool execute() execute_code
Runtime Workers isolate Datadog-managed sandbox
Build your own? Yes, documented for any OpenAPI spec Vendor feature for Datadog's API

One gap is evaluation. An open issue in the Cloudflare MCP repository asks to add evals for search and execute tools. Token savings are easy to measure. Whether agents find the right endpoint and write correct code across a realistic task set is harder to measure, and there is little public evidence on it so far. Expect to build that evaluation yourself.

A Worked Example: Finding Stale DNS Records

Here is one task done both ways. The numbers are illustrative.

Task: "We decommissioned the server at 203.0.113.10. Which DNS records in any of our zones still point to it?"

Assume the account has 40 zones, with an average of 60 records each.

With ordinary MCP tools

The agent needs at least list_zones and list_dns_records. Those two tool definitions are cheap. In a server covering the whole API, though, they sit next to hundreds of others the agent also has to read past.

The run looks like this:

  1. Call list_zones. The response lists 40 zones with full metadata.
  2. Call list_dns_records 40 times, once per zone. That is roughly 2,400 records of JSON in total.
  3. Read everything and pick out the A records whose content matches the IP.

Even if the tool supports a content filter, the agent makes 41 calls and holds 41 responses in context. Each round trip is a model turn with its own latency and token cost. The work is simple filtering, but the model has to read every result to do it.

With search and execute

First, discovery. The agent writes a short query against the spec:

// search(): runs against the OpenAPI spec, not the live API
// Illustrative - check the docs for the exact sandbox globals
async () => {
  return Object.entries(spec.paths)
    .filter(([path]) => path.includes("dns_records"))
    .map(([path, ops]) => ({ path, methods: Object.keys(ops) }));
};

That returns a few paths. The agent sees that GET /zones/{zone_id}/dns_records accepts type and content filters. Then it writes the program:

// execute(): runs in the sandbox with server-held credentials
// Illustrative - pagination omitted for brevity
async () => {
  const zones = await cloudflare.request({ method: "GET", path: "/zones?per_page=50" });
  const hits = [];
  for (const z of zones.result) {
    const recs = await cloudflare.request({
      method: "GET",
      path: `/zones/${z.id}/dns_records?type=A&content=203.0.113.10`,
    });
    for (const r of recs.result) hits.push({ zone: z.name, record: r.name, id: r.id });
  }
  return hits;
};

The model sees two tool calls, two short code blocks, and a result like three objects with zone, record name, and ID. The 40 API calls still happen, but inside the sandbox.

The comment about pagination matters. If the code fetches only the first page of zones and the account has 60, the agent will confidently report a partial answer. A list of tool calls makes that kind of gap easy to spot. A loop hides it. You trade fewer tokens for more careful review of the code, and that is the main reason evals for these tools matter.

When Ordinary MCP Tools Are Enough

Search and execute does not replace normal tool design. Use the simpler option when it fits:

  • The toolset is small. If your server has a handful of tools with clear names, the definitions cost little and the model picks well. A discovery step only adds a round trip.
  • Most tasks take one call. "Get ticket 4812" or "create a draft invoice" does not benefit from a program. Code execution helps with loops, joins, and filters across many results.
  • Every action needs its own approval. With typed tools, a human approves delete_record(id=...). With execute, the human has to read a program. That is harder, and many reviewers will approve it without reading.
  • Your client has no sandbox story. If you cannot run untrusted code in isolation with controlled egress, do not ship an execute tool.
  • Audit requirements are per operation. Compliance teams often want one log line per business action. You can log every API call made inside the sandbox, but you have to build that.

A practical split many teams can use is typed tools for the common, high-stakes operations and search and execute for the long tail of read-heavy questions. If the long tail is mostly reads, most of the risk stays in the typed path where review is easy.

If you keep ordinary tools, apply Datadog's lessons and budget tool output before it fills the context. Filtering on the server side, compact output formats, and pagination sized to the context window recover much of the benefit without running generated code.

Sandbox, Permissions, Credentials, and Writes

An execute tool runs code that a language model wrote, sometimes after reading untrusted content. Treat it the way you would treat any remote code execution endpoint, because that is what it is. Settle four things before production.

1. Sandbox limits

The runtime should have no filesystem access to anything that matters, a CPU and wall-clock limit, a memory cap, and network egress limited to the target API. Cloudflare uses Workers isolates for this. Whatever runtime you choose, the egress rule is the one that prevents a prompt-injected agent from sending data to a server an attacker controls. Simon Willison's lethal trifecta explains why: private data, untrusted input, and an exfiltration path together create the problem. A sandbox that can only reach your own API closes the third part. For how to choose a runtime, see where agent code actually runs.

2. Permissions

execute can reach every endpoint the backing token can reach. A single tool with a broad token has far more reach than 40 narrow tools did. Scope the token to what this agent is supposed to do. If one agent needs reads and another needs writes, run two servers or two tokens. Do not rely on the system prompt to keep the agent away from endpoints it should not touch.

3. Credential handling

The generated code should never see a raw API key. In Cloudflare's design, requests go through a server-provided client that adds authentication outside the agent's code. Copy that pattern. If a key appears as a string in the sandbox, the model can print it, log it, or return it. Our post on agent identity management covers the broader rule.

4. Approval of writes

This decision has the biggest effect on whether the pattern is safe to use. Options, from strictest to loosest:

Approach How it works Tradeoff
Read-only execute The sandbox client rejects non-GET requests. Writes go through typed tools. Simplest to defend. Bulk writes need a separate path.
Plan then apply Execute returns a list of proposed writes. A human approves them. A second call applies only that list. Reviewers see data, not code. Needs a little extra plumbing.
Code review A human approves the program before it runs. Reviewing code is slow and error-prone at volume.
Unrestricted The agent writes freely. Only acceptable in disposable environments.

Plan then apply is usually the right default for production writes. It keeps the token savings of code execution while giving the reviewer a concrete diff ("delete these 3 records") instead of a loop to trace by hand. It also fits the patterns in approval gates and exception routing.

Choosing a Design for Your API

For a team deciding what to build, the choice mostly comes down to three questions:

  1. How many operations does the agent need to reach? If it is a handful, use typed tools. If it is hundreds, or if you cannot predict which ones, search and execute earns its complexity.
  2. What share of tasks loop or filter over many results? If that is the common case, code execution saves both tokens and turns. If it is rare, typed tools with server-side filters cover it.
  3. Can you run untrusted code with controlled egress and server-held credentials? If not, stop here and improve your typed tools.

Measure both designs on your own tasks before deciding. Vendor token numbers describe vendor demos. Your agents need to find the right endpoint, handle pagination, and return correct answers on your data. Build 20 to 30 real questions with known answers, run each design against them, and compare accuracy, tokens, and wall-clock time.

Putting Code Mode Behind a Real Workflow

The hard part is usually what surrounds the two tools: scoping tokens, building the plan-then-apply path for writes, logging each sandboxed API call so audits still work, and building the evals that catch the pagination bug before a customer does. OpenNash does this work during the design and build phases. We map which operations stay as typed tools and which go through execute, then hand over the server, the evals, and the runbook so your team owns the result.

If you have an internal API that agents keep struggling with, book a call and bring three questions your team asks it every week. We will sketch which of them belong in typed tools and which belong behind search and execute, and what the approval path for writes should look like.