Host Smithers workflows over HTTP and WebSocket via a single-run server, a single-workflow serve app, and the multi-run Gateway control plane.
Three host surfaces ship from packages/server, each a tighter fit for a
different deployment.
startServer: a self-contained HTTP server with REST routes for run
lifecycle, SSE event streams, and approvals. One server, many workflows by
path. Reach for it when you want a plain HTTP API and no client SDK.
createServeApp: a Hono app bound to one already-loaded workflow and
run. This is what bunx smithers-orchestrator up --serve mounts. Compose it
into a larger Hono app or call app.fetch in tests.
Gateway: the headless control plane. Authenticate once, stream events
over WebSocket with resume-on-reconnect, decide approvals, inject signals,
run cron schedules, and serve many registered workflows. This is the surface
the Gateway client and custom UIs talk to.
import { startServer, createServeApp, Gateway } from "smithers-orchestrator";
createServeApp needs a SmithersDb adapter and a loaded SmithersWorkflow;
both come from your workflow module (new SmithersDb(workflow.db)). The
Gateway is constructed with new Gateway(opts), then you register()
workflows and listen().
A listening Node http.Server. headersTimeout and requestTimeout are
applied to it to bound slow header/body uploads. The full route table (run
start/resume/cancel, SSE events, frames, approvals, signals, /metrics) lives
in Server Mode.
const server = startServer({ port: 7331, authToken: process.env.SMITHERS_API_KEY, rootDir: process.cwd(),});
Build a Hono app for a single, already-loaded workflow and run. Returns a
standard Hono app: mount it with Bun.serve, route it into another Hono app, or
drive app.fetch directly in tests. This backs bunx smithers-orchestrator up --serve.
function createServeApp(opts: ServeOptions): import("hono").Hono;
The multi-run control plane. Construct it, register() one or more workflows,
then listen(). It serves RPC over POST /v1/rpc/<method> (and POST /rpc)
and over WebSocket on the same origin, with a /health, /metrics,
/workflows, and per-workflow webhook endpoints. The RPC methods (launchRun,
getRun, listRuns, submitApproval, submitSignal, cron, time-travel, and
more) are documented per method; see launchRun for the
request/response and scope shape they share.
register, extend, and the constructor are chainable. listen defaults to
port 7331; pass path for a Unix socket. close aborts active runs, drains
inflight work, and tears down connections and the scheduler.
Absolute path to the workspace root that holds .smithers/ and
smithers.db. Disk-backed registry reads (e.g. the listPrompts RPC)
resolve against it. Defaults to process.cwd().
Identity is read from request headers. Only safe behind a proxy you control
(Cloudflare Access, an internal API gateway) that strips and rewrites these
headers.
Register a workflow under key. Wires up its DB tables, optional cron schedule,
webhook config, and embedded UI bundle. Returns this, so calls chain. A
schedule writes a cron row keyed gateway:<key>; cron-fired runs get
ctx.auth.role = "system", triggeredBy = "cron:gateway", scopes = ["*"].