How Code Mode works·续

Only a paused execution can resume. A stale approval cannot revive a completed, rejected, or rolled-back execution. Rejecting an action ends the execution, but it does not undo earlier actions. Rollback is a separate operation.

Execution failures are returned as data to the agent loop. Sandbox errors and replay divergence therefore do not need to escape as uncaught RPC exceptions.

Deterministic replay

Replay requires connector calls and steps to occur in the same order. On every pass, a given sequence number must use the same connector, method, and arguments. A mismatch ends the execution with a replay-divergence error.

Recorded connector results make normal data-dependent branches stable. However, values from Date.now(), Math.random(), or other nondeterministic sources can change control flow or action arguments.

Use codemode.step() to capture such work once. The runtime records the closure result and returns that value during approval replay:

async () => {
    const createdAt = await codemode.step("created-at", () => Date.now());

return github.create_issue({
        owner: "cloudflare",
        repo: "agents",
        title: `Review created at ${createdAt}`,
    });
};

Connector calls already pass through the runtime and do not need a step wrapper. Use steps for nondeterministic or side-effectful work outside connector calls. If you explicitly allow direct network access, this includes direct network operations that must not repeat during approval replay.

Issue connector calls sequentially when an execution might pause. The host assigns sequence numbers when calls arrive. Calls in Promise.all() can arrive in different orders across passes and cause replay divergence.

Resource lifetimes

Some connectors need resources beyond one method call. Examples include browser sessions, database transactions, and temporary workspaces. Connector methods receive the stable execution ID, which can key durable resource metadata across passes.

Code Mode distinguishes two resource lifetimes:

  • Pass resources last for one sandbox pass. The runtime invokes onPassEnd() after completed, failed, and paused passes.
  • Execution resources last for the whole execution. The runtime invokes disposeExecution() after completion, failure, rejection, or rollback, but not after a pause.

A paused execution can resume in another Worker invocation. Connector lifecycle hooks must not depend on instance memory. Cleanup must also be idempotent because a completed execution can later be rolled back and disposed again.

The runtime calls lifecycle hooks for every configured connector. A connector that did not allocate a resource should safely do nothing. Cleanup errors are ignored so they do not turn a finished execution into a failed one.

Replay policy

By default, the runtime stores a connector result and replays it on later passes. This preserves the exact value that the original code observed.

A connector can mark a call with replay: "reexecute". The runtime still logs its sequence and arguments, but it does not store the result. A later pass runs the connector method again.

Use this policy only for idempotent reads with large, inexpensive results. The result can change between passes, so generated code must tolerate that change. Approval-required methods cannot use replay: "reexecute" because replay could apply an approved side effect more than once.

Rollback

Rollback walks applied connector calls in reverse order. It invokes the revert implementation for every applied method that provides one, regardless of whether that method required approval.

For each applied connector call, the runtime asks the currently configured connector to run its revert implementation. Methods without revert remain applied. Missing connectors are also skipped. A failed revert does not stop later compensation attempts, and the runtime reports failures after trying the remaining calls. The execution moves to rolled_back only if at least one call is reverted.

Rollback is compensation, not database transaction isolation. Connector authors define what reversal means for each action. An external system may also change between the original call and its compensation.

Retention and stale executions

The execution log is an audit trail and grows over time. When a new run begins, the runtime first inserts that run and then prunes older terminal executions. maxExecutions defaults to 50. Because a running execution is not terminal, completion can temporarily leave 51 terminal records until another run begins or you call pruneExecutions().

Running and paused executions are not pruned automatically. They may still need to finish or resume. Use expirePaused() from recurring maintenance to reclaim stale nonterminal runs. The runtime marks stale paused runs as rejected and stale running runs as errors, then disposes their execution resources.

You can also remove individual execution records or prune terminal history explicitly. Deleting a nonterminal execution disposes its execution-scoped resources.

Durable value and result limits

Each value stored for durable replay has a serialized character limit of 1,000,000. The implementation checks the JavaScript string length after serialization. This limit applies to connector arguments, recorded connector results, step results, and execution source code.

The runtime cannot truncate these values. Truncation would provide different data during replay. An oversized or unserializable replay value therefore fails the execution and suggests storing the data elsewhere, then passing a small reference such as a file path.

A final result has different behavior because replay does not consume it. The execution can complete and return the real result to the model. If the result cannot fit in the audit record, the runtime stores an omission message there instead.

transformResult can reshape the completed result before the model receives it. The transform runs after the runtime attempts to record the raw result. The audit trail retains the original value when it fits, while the model can receive a smaller representation.

Snippets

A snippet is saved source from an execution. Snippets turn model-written programs into reusable recipes. They remain available across requests and hibernation.

The model does not promote its own code. Your application reviews an execution and calls runtime.saveSnippet() with its execution ID. The API accepts any execution status, so verify that the execution completed successfully before saving it. The model can then find the snippet with codemode.search(), inspect it with codemode.describe(), and invoke it with codemode.run().

src/server.jsjs

const runs = await runtime.executions(20);

await runtime.saveSnippet("list-open-prs", {
    executionId: runs[0].id,
    description: "List open pull requests for a repository.",
});

src/server.tsts

const runs = await runtime.executions(20);

await runtime.saveSnippet("list-open-prs", {
    executionId: runs[0].id,
    description: "List open pull requests for a repository.",
});

A snippet can accept an input value. Its connector calls join the current execution log when the model runs it. The snippet also retains the connector list from its source execution. If a recorded connector is unavailable, codemode.run() resolves to an object with an error property. It does not throw automatically.

Was this helpful?

YesNo

On this page

How Code Mode works·续 - 图1Docs

{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/agents/tools/codemode/how-it-works/#page","headline":"How Code Mode works","description":"Learn how Code Mode isolates generated code and makes approvals, replay, rollback, and reuse durable.","url":"https://developers.cloudflare.com/agents/tools/codemode/how-it-works/","inLanguage":"en","image":"https://developers.cloudflare.com/agents/tools/codemode/how-it-works/og.png?v=150bca5f76cce557","dateModified":"2026-10-12","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["AI"]}


description: Expose tools from an existing MCP connection to models through a durable Code Mode runtime. title: Use MCP tools with Code Mode image: https://developers.cloudflare.com/agents/tools/codemode/mcp/og.png?v=e41ce0ad4f097800


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/agents/llms.txt
Use this file to discover all available pages before exploring further.