Documentation Index
Fetch the complete documentation index at: https://smithers.sh/llms.txt
Use this file to discover all available pages before exploring further.
Serve mode starts a Hono-based HTTP server alongside a running workflow. Every route operates on the single active run — no workflow path or run ID in requests.
CLI
bunx smithers-orchestrator up workflow.tsx --serve --port 3000 --host 0.0.0.0
| Flag | Default | Description |
|---|
--serve | false | Enable HTTP server mode |
--port | 7331 | TCP port |
--host | 127.0.0.1 | Bind address |
--auth-token | SMITHERS_API_KEY env | Bearer token for auth |
--metrics | true | Expose /metrics Prometheus endpoint |
The process stays alive after the workflow completes so final state remains queryable. Ctrl+C stops both the server and the workflow.
Detached mode:
bunx smithers-orchestrator up workflow.tsx --serve --port 8080 -d
Programmatic
import { createServeApp } from "smithers-orchestrator/serve";
const app = createServeApp({
workflow,
adapter,
runId,
abort: new AbortController(),
authToken: "sk-secret",
});
Bun.serve({ port: 3000, fetch: app.fetch });
createServeApp returns a standard Hono app. Mount it with Bun.serve, pass it to another Hono app via app.route(), or use app.fetch in tests.
ServeOptions
type ServeOptions = {
workflow: SmithersWorkflow<any>; // loaded workflow instance
adapter: SmithersDb; // database adapter for the workflow
runId: string; // active run ID
abort: AbortController; // shared cancellation controller
authToken?: string; // bearer token; falls back to SMITHERS_API_KEY; disabled if unset
metrics?: boolean; // expose /metrics; default true
};
Authentication
When authToken is configured, every route except /health requires:
Authorization: Bearer <token>, or
x-smithers-key: <token>
Missing or invalid tokens receive 401.
Routes
GET /health
Returns 200 regardless of auth.
GET /
Run status and node summary.
{
"runId": "run-1234",
"workflowName": "bugfix",
"status": "running",
"startedAtMs": 1707500000000,
"finishedAtMs": null,
"summary": { "finished": 3, "in-progress": 1, "pending": 2 }
}
GET /events
SSE stream of lifecycle events. Same format as the multi-workflow server.
| Parameter | Type | Default | Description |
|---|
afterSeq | number | -1 | Only events after this sequence |
event: smithers
data: {"type":"NodeStarted","runId":"run-1234","nodeId":"analyze","iteration":0,"attempt":0}
id: 1
event: smithers
data: {"type":"NodeFinished","runId":"run-1234","nodeId":"analyze","iteration":0,"attempt":0}
id: 2
- Polls every 500ms.
- Auto-closes when the run reaches a terminal state.
- Reconnect with
?afterSeq=N to resume from a known position.
GET /frames
Rendered workflow frames.
| Parameter | Type | Default | Description |
|---|
limit | number | 50 | Max frames |
afterFrameNo | number | — | Frames after this number |
POST /approve/:nodeId
Approve a pending approval gate. All fields optional. Returns { "runId": "run-1234" }.
{
"iteration": 0,
"note": "Looks good",
"decidedBy": "alice"
}
POST /deny/:nodeId
Deny a pending approval gate. Same body as /approve/:nodeId.
POST /cancel
Cancel the running workflow.
| Status | Code | Condition |
|---|
| 200 | — | Cancelled successfully |
| 409 | RUN_NOT_ACTIVE | Run already finished/failed/cancelled |
GET /metrics
Prometheus text exposition. Same metrics as the multi-workflow server.
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description"
}
}
Unknown routes return 404 with code NOT_FOUND.
Serve Mode vs Multi-Workflow Server
| Serve mode | Multi-workflow server |
|---|
| Scope | Single workflow, single run | Any workflow, multiple concurrent runs |
| Start | smithers up --serve or createServeApp() | startServer() |
| Routes | /, /events, /approve/:nodeId, … | /v1/runs, /v1/runs/:runId, … |
| Framework | Hono | Node.js http |
| Use case | Development, single-purpose services | Production API gateway |
Example
# Start a workflow with serve mode
bunx smithers-orchestrator up workflow.tsx --serve --port 8080 --auth-token sk-secret
# Status
curl http://localhost:8080/ -H "Authorization: Bearer sk-secret"
# Stream events
curl -N http://localhost:8080/events -H "Authorization: Bearer sk-secret"
# Approve
curl -X POST http://localhost:8080/approve/deploy \
-H "Authorization: Bearer sk-secret" \
-H "Content-Type: application/json" \
-d '{"note": "Ship it", "decidedBy": "alice"}'
# Health (no auth)
curl http://localhost:8080/health