Skip to main content

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.
  1. A control-plane host — where the engine drives the run.
  2. A storage descriptor — where durable run state lives.
  3. A sandbox provideronly 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:
HostRuntimeRuns 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 EdgeV8 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:
DescriptorUse for
bun:sqlite (default)Local dev on Bun.
PGliteEmbedded Postgres, zero external DB.
PostgresProduction: RDS, Cloud SQL, Neon, Supabase, any Postgres. Use the pooled/serverless endpoint on functions.
createCloudflareDurableObjectSqliteDescriptorCloudflare Workers durable run-of-record (real interactive transactions).
createCloudflareD1SqliteDescriptorCloudflare 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).
PlatformPackageCreate fn · provider idExecution · transport
Cloudflare@smithers-orchestrator/cloudflarecreateCloudflareSandboxProvider · cloudflare-sandbox@cloudflare/sandbox container
AWS@smithers-orchestrator/awscreateAwsSandboxProvider · aws-sandboxFargate (ECS) or CodeBuild runner · S3 bundle transport
GCP@smithers-orchestrator/gcpcreateGcpSandboxProvider · gcp-sandboxCloud Run Jobs runner · GCS bundle transport
Vercel@smithers-orchestrator/vercelcreateVercelSandboxProvider · vercel-sandboxVercel Sandbox compute
Daytona@smithers-orchestrator/daytonacreateDaytonaSandboxProvider · daytona-sandboxDaytona sandboxes
Any host (Docker)@smithers-orchestrator/sandboxDocker http-runnerLocal/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.

Per-platform recipes

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).
PlatformControl plane (Bun container)StorageSandbox provider (CLI agents)Status
Local / any VMBunbun:sqlite / PGlite / PostgresDocker http-runner✅ Full
AWSBun on ECS / App RunnerPostgres (RDS)createAwsSandboxProvider (Fargate/CodeBuild)✅ Full
GCPBun on Cloud Run / GKEPostgres (Cloud SQL)createGcpSandboxProvider (Cloud Run Jobs)✅ Full
KubernetesBun deploymentPostgresDocker http-runner / custom✅ Full (no first-class provider yet)
VercelNode functionPostgres (Neon pooled)createVercelSandboxProvider⚠️ Node-runtime engine load in progress
CloudflareWorker + Durable ObjectDO-SQLitecreateCloudflareSandboxProvider⚠️ 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.