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:
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: 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; Microsandbox/AWS/GCP/Vercel/Daytona also ship a register…SandboxProvider helper (on Cloudflare the provider is wired through createSmithersCloudflare).
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).

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.