An unofficial, open-source implementation of the OpenAI Agents API (agents=v1) that runs Codex, Claude Code or OpenCode on your own Cloudflare account, against models you configure.
Keep the official OpenAI SDK on the client and point it at your Worker. The Worker owns the API, the session state, the sandboxes and the model credentials.
- Works with the official SDK. Sessions, turns, items, streaming, environments, files, skills, artifacts, subagents, MCP and vaults from
openai@7.15.0; the compatibility profile lists what differs. - Native runtimes in containers. Codex
0.154.0, the Claude Agent SDK0.3.268and OpenCode1.18.30run in Cloudflare Containers with an isolated/workspace. Each runtime keeps its own agent loop; this project supplies the sandboxes, tools, durability and the API around it. - Credentials stay in the Worker. The harness container has no Internet access. Model traffic leaves only through a private gateway that holds the provider keys; neither runtime nor sandbox ever sees them.
- Durable by design. Every transition is one SQLite transaction in a Durable Object; checkpoints and workspace backups live in R2. A dropped connection never loses a turn, and the next turn resumes from the last committed checkpoint.
- Hosted environments and tools. Shell and file tools in the sandbox, hosted web search, MCP servers with Vault credentials, programmatic tool calling in an isolated Dynamic Worker, and delegation between runtimes.
Note
Cloudflare's container platform changed at the end of September 2026, and the new version still has rough edges: a first deploy may need a second wrangler deploy, and some new sessions fail to start (create them again). Cloudflare Containers: known issues has what we have seen and what to do.
The setup CLI creates a Worker with the API and a small demo app: a prompt form, a job page that streams the turn as it runs, and a download of the files the agent wrote. You need Node 24, pnpm and a running Docker engine. The workers preset runs against Workers AI and needs no provider key.
mkdir my-agents && cd my-agents
pnpm dlx create-cf-open-agents-api@alpha init # choose the demo template and a provider
pnpm install
pnpm exec wrangler login
pnpm dev # or pnpm dev:rootless when init offered itOpen http://localhost:8787, type a prompt, pick a preset and press Build. The QuickStart explains what happens under the hood and answers the first questions that come up.
Deploying needs the secrets that the CLI's setup command asks for; .dev.vars stays local. The QuickStart's Deploy section lists them.
To add the API to a Worker you already have (a Vite app, a Hono Worker, anything Wrangler deploys), run init in its directory instead. It writes the bindings into wrangler.jsonc without losing your comments, generates the composition in src/agents.ts and snapshots the Docker build context into .cf-open-agents-api/. The CLI README covers init, setup and doctor.
Bind the Agent Worker as a service named AGENTS and give the official client tenantFetch as its fetch. The binding is the credential: the trusted Worker names the tenant, and no bearer token crosses it.
import { tenantFetch } from "cf-open-agents-api/cloudflare";
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "service-binding", // the SDK requires a value; the API never reads it on this path
baseURL: "https://agents.internal/v1",
fetch: tenantFetch(env.AGENTS, "default"),
});
const session = await client.beta.agents.sessions.create(
{ agent: { model: "codex" }, environment: { type: "openai_hosted" } },
{ headers: { "Idempotency-Key": "session-1" } },
);
for await (const event of client.beta.agents.sessions.stream(session.id, {
input: "Write a short report to /workspace/outputs/report.md and summarize it.",
idempotencyKey: "turn-1",
})) {
if (event.type === "agent.session.turn.output_text.delta") process.stdout.write(event.delta);
if (event.type === "agent.session.turn.failed" && !event.turn.subagent_id)
throw new Error(event.turn.error?.message ?? "turn failed");
}agents.internal is a routing label; the request never leaves the Service Binding. openai_hosted is the SDK's wire name and selects a Cloudflare sandbox here. codex is a preset the deployment defines; clients never see provider URLs or keys.
Calling over HTTPS from Node, Python or anywhere else? Set baseURL to your Worker's URL and pass the bearer token as apiKey; see the HTTP guide. A trusted Worker can also skip HTTP and call the typed RPC methods.
flowchart LR
Client["Your Worker or HTTP client<br/>(official OpenAI SDK)"]
subgraph Account["Your Cloudflare account"]
Worker["AgentWorker<br/>auth, validation, routing, RPC"]
Catalog["TenantCatalogDO<br/>agents, templates, skills, vaults, files"]
Session["SessionDO<br/>turns, items, event log (SQLite)"]
Harness["HarnessDO + Harness Container<br/>supervisor running Codex, Claude Code or OpenCode"]
Sandbox["SandboxDO + Sandbox Container<br/>/workspace, shell, files, exec-server"]
Gateway["Models entrypoint<br/>private model gateway with provider keys"]
Loader["Dynamic Worker (CODE_LOADER)<br/>programmatic tool code"]
R2[("R2<br/>native checkpoints, workspace backups,<br/>input files, skills, artifacts")]
end
Provider["Model provider<br/>OpenAI, Anthropic, Workers AI, OpenAI-compatible"]
Client -->|Service Binding or HTTPS| Worker
Worker --> Catalog
Worker --> Session
Session -->|start, poll, control, checkpoint| Harness
Harness -->|workspace tools| Sandbox
Harness -->|model.internal| Gateway
Gateway --> Provider
Harness --> Loader
Harness --> R2
Sandbox -->|backups| R2
One Worker exports every class. Each session has its own SessionDO, HarnessDO and SandboxDO. A turn is submitted in one transaction, driven by a Durable Object alarm, streamed from the durable event log, and sealed by a checkpoint to R2. Architecture walks through a turn end to end and states the durability rules.
defineAgentWorker composes everything from three things you own: the presets clients can name, the private model gateway, and how a request maps to a tenant.
import { createOpenAI } from "@ai-sdk/openai";
import {
type AgentBindings,
bearerTenant,
type ContainerBindings,
defineAgentWorker,
} from "cf-open-agents-api/cloudflare";
import { aiSDKModel, nativeModel } from "cf-open-agents-api/models";
interface Bindings extends AgentBindings, ContainerBindings {
API_TOKEN: string;
OPENAI_API_KEY: string;
}
// Wrangler binds the classes by these names, and the container objects find the egress
// and backup entrypoints by theirs; export them unrenamed.
export const {
Agents,
Models,
SessionDO,
TenantCatalogDO,
HarnessDO,
SandboxDO,
ContainerEgress,
SandboxEgress,
DirectoryBackupGateway,
} = defineAgentWorker<Bindings>({
// Presets: what clients name in agent.model. They never see the connection behind it.
agents: {
codex: { harness: "codex", model: "codex", webSearch: true, delegates: ["claude"] },
claude: { harness: "claude-code", model: "primary", tiers: { haiku: "fast" } },
},
// The private gateway: deployment-owned names mapped to provider connections.
models: (env) => ({
codex: () =>
nativeModel({
protocol: "responses",
baseURL: "https://api.openai.com/v1",
apiKey: env.OPENAI_API_KEY,
model: "gpt-6-astra",
}),
primary: () => aiSDKModel(createOpenAI({ apiKey: env.OPENAI_API_KEY })("gpt-6-astra")),
fast: () => aiSDKModel(createOpenAI({ apiKey: env.OPENAI_API_KEY })("gpt-5.6-luna")),
}),
// Who is calling: the HTTP path maps a bearer token to a tenant.
authenticate: (request, env) => bearerTenant(request, env.API_TOKEN, "default"),
});
export default Agents;nativeModel passes a provider's own protocol through unchanged, so reasoning state, images and hosted tools survive; aiSDKModel and openAICompatibleModel translate any AI SDK or Chat Completions model, including Workers AI. The library API documents every option, Extending covers custom drivers and adapters, and Web search shows hosted search next to a search of your own.
This is pre-release software published under the npm alpha dist-tag; expect breaking changes until 1.0. It implements the agents=v1 surface as the compatibility profile describes it, not every field of every endpoint, and it does not reproduce OpenAI's hosted infrastructure, billing or policies. The portable model adapters carry text, images, function calls, reasoning effort and structured output, but not encrypted reasoning or hosted tools; OpenCode has no hosted web search at all. Wrangler's local containers assume a rootful Docker bridge, so a rootless engine needs the workaround the CLI offers as dev:rootless (known issues).
It is also more than some jobs need. If a single model call with tools is enough, a Worker calling a provider directly is simpler. If you need OpenAI's hosted environments exactly as OpenAI runs them, use OpenAI. What this project buys you is the Agents API programming model with your own runtime, your own model provider, and session state, workspaces and provider keys that never leave your Cloudflare account.
| Requirement | Detail |
|---|---|
| Node and pnpm | Node 24 or newer; pnpm 11.1.2, the pinned packageManager |
| Docker | A running engine for local development. The two images need roughly 4 GB; the first build takes several minutes |
| Cloudflare account | Workers Paid plan (Containers require it), Durable Objects with SQLite, R2, and Workers AI for the workers preset |
| Model credentials | An OpenAI or Anthropic key for the codex, claude and opencode presets; nothing beyond your Cloudflare account for workers |
In production you pay for container run time (a harness and a sandbox container, both standard-1 unless you choose other sizes, each destroyed after 10 idle minutes), R2 storage for checkpoints and backups (nothing expires them unless you add a bucket lifecycle rule), Durable Object requests and storage, and whatever your model provider bills. A session keeps its sandbox between turns, so a chatty session pays for one container pair, not one per turn. Nothing here sets a spending limit for you; Deployment has the cost model and the scaling knobs.
git clone https://github.com/inaridiy/CF-Open-Agents-API.git && cd CF-Open-Agents-API
pnpm install --frozen-lockfile
pnpm check # docs, harness, types, lint, build, scripts, CLI, machine and Worker testspackages/agent-api is the library, packages/supervisor the Node process that drives the native runtimes inside the harness container, packages/create-cf-open-agents-api the setup CLI, packages/durable-machine the typed durable state machines the container lifecycle is built on, and examples/ holds the deployable Worker, the demo app and a consuming Worker. The scripted suites need no provider credentials. CONTRIBUTING has the first local run, every command, and which checks a change needs.
| Topic | Guide |
|---|---|
| The demo, step by step | QuickStart |
| Another Worker over a Service Binding | Service Binding |
| Typed RPC without HTTP | RPC |
| Node, Python or anything else over HTTPS | HTTP API |
| The setup CLI and the generated files | create-cf-open-agents-api |
| Embedding the library in your own Worker | Library API |
| Files, skills, MCP, subagents, forks | Environments and tools |
| Hosted web search, or a search of your own | Web search |
| Presets, model adapters, custom drivers | Extending |
| Durability rules and service boundaries | Architecture |
| Production setup, costs and scaling | Deployment |
| Cloudflare Containers behaviour to know | Cloudflare Containers: known issues |
| Moving an existing deployment to a release | Upgrading |
| What the official SDK can and cannot do here | Compatibility profile |
- Implements the
agents=v1surface ofopenai@7.15.0; runs Codex0.154.0, the Claude Agent SDK0.3.268and OpenCode1.18.30. - Not affiliated with, endorsed by or supported by OpenAI, Anthropic, the OpenCode project or Cloudflare. "OpenAI", "Codex", "Claude", "Claude Code", "OpenCode" and "Cloudflare" are trademarks of their owners and are used here only to describe compatibility.
- Does not use Cloudflare's
agentsnpm package. The name describes the API it implements, not a dependency.
Contributions are welcome. CONTRIBUTING explains the toolchain, the validation matrix and the scope of a good change; SECURITY is for vulnerability reports and CHANGELOG tracks releases.
Apache-2.0, see LICENSE. Vendored development skills keep their upstream licenses; see NOTICE.
