Skip to main content

Serverless deployment

Deploying Smithers serverlessly means three independent choices. This page maps each onto the platforms Smithers supports today, states what runs where, and points at the exact exports. For the conceptual model (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 provider — needed only for CLI / full-OS agents, via <Sandbox>.

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 under Bun on any of the container platforms above 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 no longer hard-binds the Bun platform layer (RunOptions.effectPlatformLayer accepts NodeContext.layer, supplied by your entrypoint from @effect/platform-node). It 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, @effect/cluster’s single-runner uses the in-memory MessageStorage driver, matching the non-durable :memory: sqlite the Bun path already used). Still to land: 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’re 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’re 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’s 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 these container platforms today; Node-runtime and isolate paths are still in progress (see 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.