---
title: Cloudflare
description: Run Smithers on Cloudflare Workers with Durable Object SQLite or D1 storage and a Sandbox SDK provider.
---

`@smithers-orchestrator/cloudflare` runs Smithers inside Cloudflare Workers. It
provides a SQLite descriptor over Durable Object storage or D1, a factory that
builds the Smithers API against that descriptor, and a sandbox provider backed
by the Cloudflare Sandbox SDK.

Import `createSmithersCloudflare` from the main package subpath; the descriptor
and provider helpers are available from either the subpath or the scoped
package:

```ts
import {
  createSmithersCloudflare,
  createCloudflareDurableObjectSqliteDescriptor,
  createCloudflareD1SqliteDescriptor,
  createCloudflareSandboxProvider,
} from "smithers-orchestrator/cloudflare";
```

## Create the Smithers API

`createSmithersCloudflare(schemas, { db })` mirrors
[`createSmithers`](/reference/authoring) but takes a Cloudflare SQLite
descriptor as its storage:

```ts
type CreateSmithersCloudflareOptions = CreateSmithersOptions & {
  db: CloudflareSqliteDescriptor;  // required
  close?: () => Promise<void> | void;
};

const { smithers, outputs } = await createSmithersCloudflare(
  { input: inputSchema, result: resultSchema },
  { db: createCloudflareDurableObjectSqliteDescriptor(ctx.storage) },
);
```

It is `async` (it provisions the schema and per-output tables through the
descriptor) and returns the same API surface as `createSmithers` plus an
optional `close()`. Omitting `db` throws `INVALID_INPUT`.

## Storage: Durable Object SQLite (recommended)

`createCloudflareDurableObjectSqliteDescriptor(storage)` wraps a Durable
Object's SQLite store. Pass the Durable Object's `ctx.storage` (or its
`ctx.storage.sql` handle):

```ts
export class SmithersDurableObject {
  constructor(ctx, env) {
    this.descriptor = createCloudflareDurableObjectSqliteDescriptor(ctx.storage);
  }
}
```

This is the durable choice. When `storage` exposes a `transaction` method the
descriptor binds and forwards it, so Smithers gets real interactive
transactions (`BEGIN` / `COMMIT` / `ROLLBACK`). Frame commits, run-state
checkpoints, and task completion all rely on that atomicity.

## Storage: D1 (read-mostly only)

`createCloudflareD1SqliteDescriptor(database)` wraps a D1 binding:

```ts
const descriptor = createCloudflareD1SqliteDescriptor(env.DB);
```

<Warning>
  D1 has no interactive transactions. Its `prepare`/`bind`/`run` API cannot hold
  an open `BEGIN`/`COMMIT`/`ROLLBACK` across round-trips. The descriptor reports
  that limitation, and Smithers rejects transactional writes before their
  operation begins instead of risking a partial commit. Do not back durable run
  state with D1. Use `createCloudflareDurableObjectSqliteDescriptor` for
  durability and reserve D1 for read-mostly use.
</Warning>

## Sandbox provider

Runtime `"cloudflare"` is provider-backed: it has no built-in transport, so a
[`<Sandbox>`](/components/sandbox) that requests it needs a provider.
`createCloudflareSandboxProvider(options)` builds one over the Cloudflare
Sandbox SDK (`@cloudflare/sandbox`, an optional dependency imported lazily):

```ts
const provider = createCloudflareSandboxProvider({ binding: env.Sandbox });
```

Pass the provider where the runtime is resolved. Requesting runtime
`"cloudflare"` without a provider throws `INVALID_INPUT` ("Sandbox runtime
\"cloudflare\" requires a provider from smithers-orchestrator/cloudflare, e.g.
createCloudflareSandboxProvider()."). The provider's id is
`CLOUDFLARE_SANDBOX_PROVIDER_ID` (`"cloudflare-sandbox"`), which becomes the
selected runtime.

`options.binding` (or `(request) => binding`) must be the Durable Object binding
for the Sandbox SDK. Other options cover the sandbox id, workdir (default
`/workspace`), command, env, setup files, execution mode (`exec` or `process`),
and cleanup (`destroy` or `keep`).

## Serverless & cost

On Cloudflare, Smithers splits along the two execution modes described in
[Where agents run](/concepts/execution-model):

- **The control plane + in-process agents** run inside the Worker / Durable
  Object. `createSmithersCloudflare` builds the Smithers API against Durable
  Object SQLite (`createCloudflareDurableObjectSqliteDescriptor`), and SDK agents
  (`AnthropicAgent`, `OpenAIAgent`, …) are plain HTTPS calls with no subprocess --
  so a workflow built entirely from SDK agents runs Worker-native.
- **CLI / full-OS agents** cannot run in the Worker's JS runtime (they spawn a
  vendor binary via `node:child_process`). They are offloaded to a
  `@cloudflare/sandbox` container through `createCloudflareSandboxProvider`, which
  the Worker delegates to at each `<Sandbox>` boundary.

<Warning>
  **Not turnkey-serverless for CLI-agent workflows today.** The package ships
  storage descriptors and a sandbox provider, but **no Worker entry / Durable
  Object class and no Workers-native run driver**. The core engine that advances
  every run uses `node:fs` and `node:child_process` (git/jj worktrees on a real
  filesystem), so a Node/Bun host is still required to *drive* runs. The
  Cloudflare provider also creates **one container per `<Sandbox>` `run()`**
  (keyed `${runId}-${sandboxId}`) -- not per agent turn. Both `exec` and
  `process` execution modes wait for the work to finish and reconcile the result
  bundle; set `sleepAfter` to control idle hibernation. Treat Workers-native
  execution as the storage + in-process-agent path today, not turnkey serverless
  for CLI harnesses.
</Warning>

What's billed on Cloudflare:

| Component | Billing driver |
|---|---|
| In-process SDK agents | Model API tokens (billed by the model provider, not Cloudflare) |
| Worker / Durable Object control plane | Worker invocations + Durable Object requests and duration; DO-SQLite storage (rows read/written). Use **DO-SQLite** for durable run-of-record -- **D1 has no interactive transactions** and can leave partial state (see the D1 warning above) |
| `@cloudflare/sandbox` container (per `<Sandbox>`) | Container wall-clock from create → teardown. Idle hibernation follows `sleepAfter` (Sandbox SDK default ~10m if unset). `cleanup: "keep"` leaves the container billing until it hibernates; the default `cleanup: "destroy"` stops it at the end of the boundary -- in both `exec` and `process` modes, since `run()` awaits completion before cleanup |

<Note>
  Cloudflare's own pricing for Workers, Durable Objects, and the Sandbox SDK
  changes independently of Smithers -- check Cloudflare's current pricing pages for
  exact per-unit figures. Smithers only determines the **shape** of what's
  consumed: token calls, DO storage/requests, and container wall-clock per
  `<Sandbox>` boundary.
</Note>

## Notes

- The package exports no Durable Object class and no Worker entry helper. You write the Worker and Durable Object; the package supplies the storage descriptors and sandbox provider.
- `createMockCloudflareSandboxEnvironment(handler)` is exported for tests: it implements the subset of the Sandbox SDK the provider uses.
- The descriptor helpers are also exported from `@smithers-orchestrator/cloudflare`; only `createSmithersCloudflare` requires the `smithers-orchestrator/cloudflare` subpath.
