PuppyIP Resource Center
AI Development Tools 6 min Published 2026-11-10

Codex on Cloudflare Workers: Experimental Harness and Recovery

Cloudflare’s November 9, 2026 announcement describes an experimental example built on internal Agents SDK APIs: Codex’s Rust turn-processing code is compiled to WebAssembly and runs in a Durable Object. An operation ID records durable prompt acceptance, not completion. After a restart, completed steps can be reused, while interrupted steps, including model calls, may run again.

Cloudflare Workers Codex harness Durable Objects Agents SDK operation IDs task recovery

Service eligibility and regional restrictions

PuppyIP serves only compliant overseas businesses and their authorized personnel. Proxy services are not available in mainland China. The service may only be used for lawful business activities outside mainland China. Use of this service within mainland China is prohibited.

Hosting a proxy IP or server overseas does not change these restrictions. The service must not be provided to end users in mainland China through relaying, forwarding, sharing or resale. Before use, read the Terms of Service.

Key Takeaways

  • This is an experimental example built with internal Agents SDK APIs, not an exported SDK harness or the full Codex CLI with a Linux shell and repository tools.
  • The documented prerequisites are Git, Node.js 24 or later, pnpm, rustup, and a Cloudflare account. The example specifies Rust 1.95.0 for wasm32-unknown-unknown.
  • submit() returns after durably accepting a prompt, before the model finishes. Retrying the same prompt with the same operationId returns accepted: false for an existing operation; snapshot() reports its state.
  • After a Durable Object restart, completed task steps reuse stored results. Interrupted steps, including model calls, may run again, and event replay does not guarantee exactly-once external side effects.

Start with the example’s actual scope

Cloudflare’s November 9, 2026 changelog describes an experimental Agents SDK example. It adapts Codex’s Rust turn-processing and protocol code to WebAssembly and runs it inside a Cloudflare Durable Object. It uses internal SDK APIs; it is not an exported Agents SDK harness.

The example does not provide the full Codex CLI environment with a Linux shell and repository tools. Cloudflare’s guide directs those requirements to the Container harness or sandbox documentation. Choose the example for the environment you need: model-and-tool turn processing or a full repository execution environment.

Prepare the toolchain and Cloudflare account

The documented prerequisites are Git, Node.js 24 or later, pnpm, rustup, and a Cloudflare account. Run git clone https://github.com/cloudflare/agents.git and enter the agents repository root. Run pnpm install and pnpm nx run agents:build, then enter examples/next/harnesses/codex and install the specified toolchain: rustup toolchain install 1.95.0 --target wasm32-unknown-unknown.

From the example directory, sign in with the Cloudflare CLI using cf auth login, then run pnpm run start. The start script builds the WebAssembly module before starting Vite. If you have multiple Cloudflare accounts, the guide recommends setting CLOUDFLARE_ACCOUNT_ID before startup. The documented demo prompt writes a short README to /codex/result.txt and reads it back; after the turn finishes, reload the page to see whether the conversation and file remain available. This is the guide’s example flow, not a result from an execution in this article.

Local development still calls a remote model

Model calls use remote Workers AI through your Cloudflare account, including during local development. In src/server.ts, the example uses its AI binding and AI Gateway ID default to call model openai/gpt-6.1-sol. That default gateway needs Unified Billing or a stored OpenAI API key.

The announcement and guide do not establish actual charges for this example or verify eligibility for individual accounts and regions. This guide explains documented behavior; execution, billing, and performance have not been independently tested. Check access, gateway settings, and actual charges for the account you intend to use.

An operationId means accepted, not finished

Calling submit({ prompt, operationId }) on the example’s Coder Durable Object durably accepts the prompt and returns a receipt before the model has necessarily finished. The receipt contains operationId, streamId, and accepted. When retrying the same prompt, reuse the same operationId; if that ID already belongs to an operation, the receipt has accepted: false.

After receiving the receipt, call snapshot(operationId) to check for queued, running, completed, or failed. A completed snapshot contains output; a failed snapshot contains error. Clients should present acceptance and completion as separate states, and continue checking the original operation by its ID instead of treating a returned submission request as finished model work.

After a restart, completed steps are reused but interrupted steps may run again

The example divides its capabilities across several components: Tasks keeps a journal of model and tool steps; Sessions stores the transcript and compacts model context; Streams persists events for replay; and Workspace stores files in the Durable Object’s SQLite storage. The browser session hook receives a snapshot, subscribes to operation events, and resumes from the next unread sequence after reconnecting.

After a Durable Object restart, completed Tasks steps reuse their stored results. Interrupted steps can execute again, including model calls. Streams replay helps the client resume event reading in order, but it does not guarantee exactly-once external effects. If a tool can charge, create an external resource, send a message, or change another system, the application still needs its own deduplication strategy or must check the original outcome before retrying.

Add authentication before exposing sessions, and check tool limits

The example routes are unauthenticated. Add authentication and authorization appropriate to your application before exposing user sessions; do not publish the sample routes as a multi-user service entry point.

The adapter supports text, reasoning, and function tools. It does not support file responses, provider-executed tools, or tool approval requests. Check whether these limits fit your workflow before choosing this experimental example; do not assume that capabilities from another harness apply here.

Sources

Frequently Asked Questions

Does the default maxRounds of 128 mean a limit of 128 tool calls?

No. maxRounds limits the number of model rounds per turn and defaults to 128. The guide defines one round as a model call plus any tool calls it requests, so that number is not a total tool-call limit.

Why might there be no new model response events immediately after reconnecting?

The guide says model response events become available after the corresponding model round finishes. Reconnecting resumes persisted events from the next unread sequence. The absence of a new event alone does not establish failure; check snapshot() for the original operationId as well.

How can the example read and write files if file responses are unsupported?

Returning a file response and calling a file tool are separate capabilities. The example exposes reads and writes in its SQLite-backed Workspace as function tools named workspace_read and workspace_write. This does not mean the adapter supports file responses or a Linux shell.