What even is code mode? Code mode, an agent design pattern in which a model writes a single script that calls tools as functions instead of making one tool call per inference step, cuts cost and latency by keeping tool results in program variables rather than the model's context, according to Boris Tane, who said the agent at his company Polylane uses the approach for most of its tool calls. Tane argued the pattern has been wrongly framed as an MCP optimization, writing that "code mode has nothing to do with MCP, it's a decision about where tool results go." In his CI-failure example, a coding agent that lists 15 GitHub workflow runs and then fetches jobs for each failed run one at a time pays for every payload in context, while a single script filters the runs, fetches failed jobs in parallel and returns only the run ID, commit and failing job names. Boris Tane https://x.com/boristane What even is code mode? Explore with AI Code mode is a simple idea: instead of asking a model to call tools one at a time, you give it a single tool that runs code, and you expose all the other tools as functions it can call from that code. The model writes a small program, the program calls the tools, and only what the program returns goes back to the model. graph TB M "Model" -- |"writes a script"| C "Code tool" C -- T1 "GitHub" C -- T2 "AWS" C -- T3 "Sentry" T1 ~~~ R T2 ~~~ R T3 ~~~ R C -- |"only the return value"| R "Model" style C fill: d1fae5,stroke: 6ee7b7,color: 065f46 Over the last year, code mode has mostly been discussed as a better way to use MCP servers. This framing undersells it. Code mode has nothing to do with MCP, it’s a decision about where tool results go: either into the model’s context, or into the variables of a program the model wrote. Any agent can make that decision, and at Polylane https://polylane.com/ , our agent makes it for most of its tool calls. Tool calling In most agents, tool calling works the same way: - the model asks for a tool - the harness runs it - the full result is appended to the conversation The model reads the whole array of messages again, decides what to call next, and the loop goes round again. Let’s say you’re using a coding agent and ask it why CI is failing on main. It calls the GitHub API, lists the last 15 workflow runs and gets back 15 full run objects. It then picks the failed ones from within its context, and makes multiple sequential tool calls, asking for the jobs of each failed run, one at a time. Every tool call is a full inference step, and every payload stays in the context for the rest of the conversation. The model only needed the run ID, the commit and the name of the failing job, but it paid for everything else too. In this setup the model is the glue between the tools, and it’s a very expensive glue. Code mode With code mode, the glue is code the model writes. The same question becomes a single script: js // Simplified, modelled on scripts our agent writes. async = { const { data } = await tools.githubApi { method: "GET", path: "/repos/{owner}/{repo}/actions/runs", params: { owner: "acme", repo: "web", branch: "main", per page: 15 }, } ; const failed = data.workflow runs.filter r = r.conclusion === "failure" ; return Promise.all failed.map async run = { try { const jobs = await tools.githubApi { method: "GET", path: "/repos/{owner}/{repo}/actions/runs/{run id}/jobs", params: { owner: "acme", repo: "web", run id: run.id }, } ; return { id: run.id, sha: run.head sha.slice 0, 7 , failedJobs: jobs.data.jobs.filter j = j.conclusion === "failure" .map j = j.name , }; } catch e { return { id: run.id, error: String e }; } } , ; }; The tool results land in variables instead of the context. The script filters the runs, fetches the jobs of the failed ones in parallel, and returns a handful of fields per run. That return value is the only thing the model sees. This is not only cheaper, it’s also faster. With tool calling, the model takes a full inference step for every call, and at each step it reads, and reasons about, a growing dump of JSON it mostly doesn’t need. With code mode, it writes one script, the calls inside it run in parallel, and the model gets its answer back from a single tool call. Fewer steps, less to read at each step, and less reasoning about irrelevant fields. Code mode is also not limited to JavaScript. Any language that can be interpreted in an isolated environment works, and many agent frameworks use Python instead: the model writes a Python function that calls the tools, and the environment runs it. Where does the code run? The beauty of code mode is that the model can write and execute arbitrary code. The scary part of code mode is that the model can write and execute arbitrary code. That code has to run somewhere it can’t do any damage. Polylane’s agent has a tool called executeCode for this. Its only input is a string of JavaScript: an async function, like the script above. When the model wants to use code mode, it calls executeCode like any other tool: js { "name": "executeCode", "input": { "code": "async = { const { data } = await tools.githubApi { ... } ; return data.workflow runs.length; }" } } Inside that code, the model has access to a single global object called tools . It has one async function per tool the agent can use, and each function takes the same input as the tool and returns its result: // What the model can call from inside a script. await tools.githubApi { method: "GET", path: "/repos/{owner}/{repo}/pulls", params: { owner: "acme", repo: "web" } } ; await tools.vercelListDeployments { projectId: "prj 123", limit: 10 } ; await tools.awsCloudWatchLogs { action: "query", logGroupNames: "/aws/lambda/checkout-api" , queryString: "..." } ; await tools.sentryIssues { action: "get", issueId: "4512" } ; Each script runs in a fresh V8 isolate from Dynamic Cloudflare Workers https://developers.cloudflare.com/dynamic-workers/ , with no network access at all. This is how executeCode starts one, trimmed: js const executor = new DynamicWorkerExecutor { loader: env.LOADER, timeout: EXECUTION TIMEOUT MS, globalOutbound: null, // fetch and connect throw inside the isolate } ; const { result, logs, error } = await executor.execute code, provider ; The isolate has no network, so how does tools.githubApi reach GitHub? That’s what the provider is for. It’s built outside the isolate, in a regular Cloudflare Worker, and maps every tool name to a function that runs the real tool: // Simplified: one function per tool, running in a regular Worker, not in the isolate. const provider = { name: "tools", fns: Object.fromEntries Object.entries agentTools .map name, tool = name, input = tool.execute input , }; Inside the isolate, tools only holds stubs with the same names. When the script calls tools.githubApi input , the stub sends the name and the input over RPC to that regular Worker, which runs the real githubApi tool with the workspace’s credentials, and the result is sent back into the isolate. The only way the script can reach GitHub is through that tool, and it never sees a token. graph TB M "Script from the model" -- I "Isolate, no network" I -- |"tools.githubApi "| A "Worker, with credentials" A -- G "GitHub API" style I fill: d1fae5,stroke: 6ee7b7,color: 065f46 An isolate starts in a few milliseconds, so there’s no pool of isolates to keep warm. Every script gets a new one, and it’s thrown away as soon as the script returns. You don’t need Cloudflare for this We run code mode on Cloudflare because the rest of Polylane runs there, and isolates are a very good fit for it. But all you need is an isolated environment that can run code without network access, and a way to pass your tools into it. There are plenty of options, including: - Claude’s programmatic tool calling. The Claude API has programmatic tool calling https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling : Claude writes code that runs in Anthropic’s sandbox, and each call to one of your tools pauses the script and comes back to your application as a normal tool call. - pctx. pctx https://github.com/portofcontext/pctx is an open source code mode server: it sits in front of your MCP servers and runs the generated code in a Deno sandbox that can only reach the hosts you allow. - Pyodide in Deno. Pydantic’s mcp-run-python https://github.com/pydantic/mcp-run-python runs Python with Pyodide inside Deno, isolated from the host. - QuickJS in WebAssembly. quickjs-emscripten https://github.com/justjake/quickjs-emscripten gives you a small JavaScript engine in WebAssembly that you can embed in any Node.js process, with no network and no file system unless you pass them in. Code mode is not about MCP Early implementations of code mode focused on converting MCP servers into TypeScript APIs, which is why most people think of code mode as a better way to use MCP. But if you look at what the isolate actually needs, it’s a list of functions with their types, and a way to call them. MCP is one source of those functions. The agent’s own tools are another, and for most agents they are by far the bigger one. That’s how we use it. Polylane connects to everything you run in production: your clouds, your observability tools, your code, your error tracking, etc. It investigates production issues and opens pull requests to fix them https://polylane.com/use-cases/ticket-resolution/ , and every provider it connects to comes with its own tools. That adds up to a few hundred tools, and describing all of them in full in the prompt would take close to 300,000 tokens before the conversation even starts. None of these tools go through MCP on their way into executeCode . They’re the agent’s own tools, passed into the isolate as functions. How Polylane uses code mode The prompt is an index, not a manual Putting every tool signature in the prompt would cost more context than code mode saves. So we don’t. When we build executeCode ’s description, we generate a TypeScript declaration of the tools object with just the name of each tool and a one-line summary taken from its description: js // Part of the tool index in executeCode's description. declare const tools: { awsCloudWatchLogs: ToolFn; datadogSearchLogs: ToolFn; sentryIssues: ToolFn; vercelListDeployments: ToolFn; // more tools, each with a one-line summary omitted here / Look up instructions and TypeScript input/output types for tools by name. / describe: names: string = Promise