How Code Mode works

Last updated Oct 12, 2026 Code Mode is a pattern where a model writes code to compose tools. The @cloudflare/codemode package implements that pattern with an isolated executor, service connectors, and a durable runtime.

These parts have separate responsibilities. The executor runs code but stores no state. Connectors provide capabilities but do not manage replay. The runtime records execution and controls approvals, replay, rollback, and reuse.

Caution

Code Mode is experimental and may have breaking changes.

What the model sees

In the standard setup, the model receives one outer tool named codemode. That tool accepts one field and returns a durable execution outcome:

type CodeModeInput = {
    code: string;
};

type PendingAction = {
    executionId: string;
    seq: number;
    connector: string;
    method: string;
    args: unknown;
};

type CodeModeOutput =
    | { status: "completed"; executionId: string; result: unknown; logs?: string[] }
    | { status: "paused"; executionId: string; pending: PendingAction[] }
    | { status: "error"; executionId: string; error: string; logs?: string[] };

Its description tells the model to write a JavaScript async arrow function. The description lists the configured connector namespace names, such as github or stripe, but it does not include every connector method and schema.

The model can use one Code Mode execution to discover relevant methods, then use the returned paths and types in its next execution. This keeps the complete tool catalog out of the initial model context.

Platform SDK

Inside the sandbox, the codemode global provides the platform-level SDK:

declare const codemode: {
    search(query: string): Promise<SearchOutput>;
    describe(target: string): Promise<DescribeOutput>;
    step<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
    run(name: string, input?: unknown): Promise<unknown>;
};

type SearchOutput = {
    results: Array<{
        path: string;
        connector: string;
        method: string;
        description?: string;
        kind: "method" | "snippet";
        score: number;
    }>;
    total: number;
    truncated: boolean;
};

type DescribeOutput = {
    path: string;
    description?: string;
    types: string;
    kind: "connector" | "method" | "snippet";
};

codemode.search() searches connector methods and saved snippets. It returns ranked paths, not complete schemas. The model can then pass one path to codemode.describe() to request focused TypeScript documentation.

codemode.step() records nondeterministic or side-effectful sandbox work for replay. codemode.run() invokes a saved snippet.

Connector SDKs

Each configured connector becomes another sandbox global. A connector named github is available as github, and its methods appear under paths such as github.list_pull_requests.

A connector-level description returns declarations similar to:

type ListPullRequestsInput = {
    owner: string;
    repo: string;
    state?: "open" | "closed";
};

type ListPullRequestsOutput = unknown;

declare const github: {
    list_pull_requests(
        input: ListPullRequestsInput,
    ): Promise<ListPullRequestsOutput>;
};

These declarations are generated from connector schemas. They are illustrative; the actual method names, input fields, and output types depend on the connector.

The sandbox also includes standard JavaScript globals. It does not expose Node.js APIs, host credentials, process, require, or unrestricted network access. All external operations go through connector globals unless the executor explicitly provides another capability.

Executor, connectors, and runtime

Executor

An executor runs one block of model-generated code once. It receives callable namespaces and returns a result, an error, and captured console output. It does not retain execution history.

DynamicWorkerExecutor uses a Dynamic Worker Loader to create an isolated Worker for each execution pass. A resumed execution runs the code again in another pass. Durable state therefore cannot live inside the sandbox.

External fetch() and connect() calls are blocked by default. DynamicWorkerExecutor configures globalOutbound: null unless you provide another value. You can provide a Fetcher to route outbound requests through a controlled service.

Connectors

Connectors bridge host-side services into the sandbox. A connector can wrap a Model Context Protocol (MCP) server, an OpenAPI document, an AI SDK toolset, or custom code.

Each connector becomes a global namespace. For example, a connector named github exposes calls such as github.list_pull_requests(). The generated code never receives the connector credentials or client objects.

Connector calls cross the sandbox boundary through Workers remote procedure calls (RPC). The runtime intercepts each call before the connector executes it. This interception applies approval, logging, replay, and rollback policy.

The codemode global provides discovery and runtime operations. codemode.search() finds connector methods and saved snippets. codemode.describe() returns focused TypeScript documentation without placing every connector schema in the model context.

Durable runtime

The runtime connects the executor and connectors. It stores execution records, connector-call logs, pending approvals, and snippets in isolated SQLite storage. This state survives request completion and Durable Object hibernation.

The executor and connector instances remain transient. Your application provides them again when it handles a later approval or request.

A typical Agent creates all three parts together:

src/server.jsjs

import {
    createCodemodeRuntime,
    DynamicWorkerExecutor,
} from "@cloudflare/codemode";

const runtime = createCodemodeRuntime({
    ctx: this.ctx,
    executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
    connectors: [github, repoApi],
});

const tools = { codemode: runtime.tool() };

src/server.tsts

import {
    createCodemodeRuntime,
    DynamicWorkerExecutor,
} from "@cloudflare/codemode";

const runtime = createCodemodeRuntime({
    ctx: this.ctx,
    executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
    connectors: [github, repoApi],
});

const tools = { codemode: runtime.tool() };

Code Mode stores this state in a Durable Object facet. A facet is a durable child of the Agent with its own SQLite storage. createCodemodeRuntime() and the Vite plugin manage this implementation detail. You do not create or address the facet directly.

Use multiple runtimes

Most Agents need only one Code Mode runtime. If you omit name, the runtime uses the name default.

Set name when one Agent needs separate Code Mode histories. For example, a runtime named research and another named operations keep separate execution records and snippet collections:

src/server.jsjs

const researchRuntime = createCodemodeRuntime({
    ctx: this.ctx,
    executor,
    connectors: researchConnectors,
    name: "research",
});

const operationsRuntime = createCodemodeRuntime({
    ctx: this.ctx,
    executor,
    connectors: operationsConnectors,
    name: "operations",
});

src/server.tsts

const researchRuntime = createCodemodeRuntime({
    ctx: this.ctx,
    executor,
    connectors: researchConnectors,
    name: "research",
});

const operationsRuntime = createCodemodeRuntime({
    ctx: this.ctx,
    executor,
    connectors: operationsConnectors,
    name: "operations",
});

A runtime name identifies its durable storage. It does not name the model, connector, tool, or individual execution.

Changing the connector set does not create another runtime. Each execution records every connector configured when it starts, and a saved snippet inherits that list. Approval replay and snippet execution require all recorded connectors to remain available, even if the original code did not call each one.

Durable execution log

The runtime assigns each execution a stable ID. Each connector call and codemode.step() entry receives a sequence number. The log records its arguments, state, replay policy, and result when applicable.

The runtime marks a call as executing before invoking its connector. It marks the call as applied after recording the result. If the host stops before completing the pass, the execution can remain in running. A later expirePaused() maintenance call marks that stale execution as an error and releases its resources. Approval does not resume a stale running execution.

This log is the replay spine. It also supports developer audit views and determines which actions can be rolled back. It is not general conversation memory and does not replace Agent state.

Approvals through abort and replay

A connector method can require user approval. When generated code reaches that method, the runtime records the action as pending and aborts the current pass. The action does not receive a provisional result.

The application can show the pending method and arguments to a user. Approval starts another pass with the same source code and execution ID. Calls already marked as applied return their recorded results instead of executing again. The approved action then executes, and the code continues until completion or another approval.

first pass:   read ── execute ──> result
              write ── pause

approval

second pass:  read ── replay ───> recorded result
              write ── execute ─> result
              next call ────────> continue

This design lets an approval wait beyond a request or hibernation. Generated code remains linear and does not implement pause or resume logic.