Serverless deployment
Deploying Smithers serverlessly is three independent choices. This page maps
each choice onto the platforms Smithers supports today, states honestly what
runs where, and points at the exact exports. For the conceptual model behind it
(in-process vs full-OS agents, what’s billed), read
Where agents run, sandboxes & cost first.
- A control-plane host — where the engine drives the run.
- A storage descriptor — where durable run state lives.
- A sandbox provider — only if your workflow uses CLI / full-OS agents
via
<Sandbox>; in-process SDK agents need none.
1. Control-plane host
The engine renders the workflow, schedules tasks, and persists frames. Where it
can run depends on the runtime’s system access:
| Host | Runtime | Runs the engine today? |
|---|
| A container running Bun (ECS, App Runner, Cloud Run service, GKE, a VM) | Bun | ✅ Yes |
| The Node runtime (Vercel Node function, AWS Lambda Node, a Node server) | Node (has fs + child_process) | ⚠️ In progress |
| Cloudflare Worker / Vercel Edge | V8 isolate (no fs/child_process) | ⚠️ In progress |
The engine currently requires the Bun runtime. Run it on any container
platform (ECS, App Runner, Cloud Run, GKE, a VM) under Bun and the full engine
works today. Two portability efforts are in flight:
- Node runtime (Vercel Node functions, Lambda Node): closest, since Node
has
fs + child_process. The engine module now imports cleanly under
plain Node (all bun:sqlite-reaching value imports are lazy-loaded, guarded
by a node-subprocess regression test), and it no longer hard-binds the Bun
platform layer (RunOptions.effectPlatformLayer accepts NodeContext.layer,
supplied by your entrypoint from @effect/platform-node). The engine now
drives a run to completion under plain Node, proven end-to-end by a
node-subprocess regression test that runs a compute-task workflow against
PGlite and asserts the run reaches finished; the worker-task dispatch path
no longer requires bun-sqlite (under Node the @effect/cluster single-runner
uses the in-memory MessageStorage driver, matching the non-durable :memory:
sqlite the Bun path already used). Still to land before calling Node fully
supported: validating agent (CLI/SDK) tasks and the gateway under Node.
- Isolates (Workers, Edge): further out — the engine and gateway also use
node:fs / node:child_process (git/jj worktrees on a real filesystem),
which an @effect/platform FileSystem/Command seam must abstract. Today
an isolate can host storage + in-process SDK agents (via
createSmithersCloudflare), but not the run driver.
2. Storage descriptor
Durable run state is dialect-abstracted (sqlite | postgres), so the same
control plane runs on any of these:
| Descriptor | Use for |
|---|
bun:sqlite (default) | Local dev on Bun. |
| PGlite | Embedded Postgres, zero external DB. |
| Postgres | Production: RDS, Cloud SQL, Neon, Supabase, any Postgres. Use the pooled/serverless endpoint on functions. |
createCloudflareDurableObjectSqliteDescriptor | Cloudflare Workers durable run-of-record (real interactive transactions). |
createCloudflareD1SqliteDescriptor | Cloudflare D1 — read-mostly only (no interactive transactions; unsafe for durable run state). |
On Node hosts, point Smithers at Postgres and you are done. On Cloudflare, build
the API with createSmithersCloudflare over the Durable Object SQLite
descriptor (see Cloudflare).
3. Sandbox provider (only for full-OS / CLI agents)
In-process SDK agents (AnthropicAgent, OpenAIAgent, HermesAgent,
ElizaAgent) need no provider — they are HTTPS calls in your process. CLI
agents (ClaudeCodeAgent, CodexAgent, OpenCodeAgent, …) spawn a vendor
binary and must run inside a container, which a SandboxProvider supplies at
each <Sandbox> boundary. Each provider ships a create…SandboxProvider and a
createMock…SandboxEnvironment test double; AWS/GCP/Vercel/Daytona also ship a
register…SandboxProvider helper (on Cloudflare the provider is wired through
createSmithersCloudflare).
| Platform | Package | Create fn · provider id | Execution · transport |
|---|
| Cloudflare | @smithers-orchestrator/cloudflare | createCloudflareSandboxProvider · cloudflare-sandbox | @cloudflare/sandbox container |
| AWS | @smithers-orchestrator/aws | createAwsSandboxProvider · aws-sandbox | Fargate (ECS) or CodeBuild runner · S3 bundle transport |
| GCP | @smithers-orchestrator/gcp | createGcpSandboxProvider · gcp-sandbox | Cloud Run Jobs runner · GCS bundle transport |
| Vercel | @smithers-orchestrator/vercel | createVercelSandboxProvider · vercel-sandbox | Vercel Sandbox compute |
| Daytona | @smithers-orchestrator/daytona | createDaytonaSandboxProvider · daytona-sandbox | Daytona sandboxes |
| Any host (Docker) | @smithers-orchestrator/sandbox | Docker http-runner | Local/remote Docker |
There is no dedicated Kubernetes provider yet. On a cluster, run the
control plane as a normal Node deployment and use the Docker http-runner
(or register a custom SandboxProvider that submits a K8s Job) for the
full-OS agent path.
The control plane runs under Bun on any of these container platforms today;
the Node-runtime and isolate paths are in progress (see the host section above).
| Platform | Control plane (Bun container) | Storage | Sandbox provider (CLI agents) | Status |
|---|
| Local / any VM | Bun | bun:sqlite / PGlite / Postgres | Docker http-runner | ✅ Full |
| AWS | Bun on ECS / App Runner | Postgres (RDS) | createAwsSandboxProvider (Fargate/CodeBuild) | ✅ Full |
| GCP | Bun on Cloud Run / GKE | Postgres (Cloud SQL) | createGcpSandboxProvider (Cloud Run Jobs) | ✅ Full |
| Kubernetes | Bun deployment | Postgres | Docker http-runner / custom | ✅ Full (no first-class provider yet) |
| Vercel | Node function | Postgres (Neon pooled) | createVercelSandboxProvider | ⚠️ Node-runtime engine load in progress |
| Cloudflare | Worker + Durable Object | DO-SQLite | createCloudflareSandboxProvider | ⚠️ Storage + SDK agents; run driver in progress |
What it costs
Three independent axes (detailed in
the execution model):
- Model tokens / subscription — billed by the model provider.
- Control-plane host compute — your Node function/server wall-clock (or
Worker/DO requests + duration on Cloudflare).
- Sandbox provider compute — only when a
<Sandbox> runs: the container/VM
wall-clock from create → run → teardown, plus the bundle-transport storage
(S3/GCS/DO). A workflow of only in-process SDK agents pays this axis nothing.
Read next