smithers up, see Serve Mode.
Import
Quick Start
ServerOptions
| Option | Type | Default | Description |
|---|---|---|---|
port | number | 7331 | TCP port |
db | BunSQLiteDatabase | undefined | SQLite database for mirroring run/event data; enables GET /v1/runs |
authToken | string | process.env.SMITHERS_API_KEY | Bearer token. Falls back to env var. Disabled if neither is set. |
maxBodyBytes | number | 1048576 (1MB) | Max request body size. Returns 413 if exceeded. |
rootDir | string | undefined | Root for workflow path resolution and tool sandboxing |
allowNetwork | boolean | false | Allow network access in bash tool |
http.Server instance, already listening.
Authentication
WhenauthToken is configured, every request must include:
Authorization: Bearer <token>, orx-smithers-key: <token>
401.
Observability
The server participates in the standard observability pipeline:smithers.http.requestscountersmithers.http.request_duration_mshistogram- Request handling, workflow loading, and body parsing wrapped in spans
- Prometheus scrape endpoint at
/metrics
API Routes
All routes use JSON request/response bodies exceptGET /v1/runs/:runId/events (SSE) and GET /metrics (Prometheus text).
JSON responses include Content-Type: application/json, Cache-Control: no-store, and X-Content-Type-Options: nosniff.
GET /metrics
Prometheus text exposition of runtime metrics.POST /v1/runs
Start a new workflow run or resume an existing one.{ "runId": "smi_abc123" }
The workflow is dynamically imported, tables are auto-created, and the run starts asynchronously.
| Status | Code | Condition |
|---|---|---|
| 400 | INVALID_REQUEST | Missing/invalid workflowPath, input, or config |
| 400 | RUN_ID_REQUIRED | resume: true without runId |
| 400 | WORKFLOW_PATH_OUTSIDE_ROOT | Path resolves outside rootDir |
| 404 | RUN_NOT_FOUND | resume: true but run does not exist |
| 409 | RUN_IN_PROGRESS | Run with this ID already active |
| 409 | RUN_ALREADY_EXISTS | Run with this ID exists (no resume) |
POST /v1/runs/:runId/resume
Resume a paused or failed run.{ "runId": "smi_abc123" }
If currently active, returns 200 with current status. Otherwise reloads the workflow and resumes from last checkpoint.
| Status | Code | Condition |
|---|---|---|
| 400 | INVALID_REQUEST | Missing/invalid workflowPath |
| 404 | RUN_NOT_FOUND | Run does not exist |
POST /v1/runs/:runId/cancel
Cancel a running workflow. Signals the run’sAbortController.
Response: { "runId": "smi_abc123" }
| Status | Code | Condition |
|---|---|---|
| 404 | NOT_FOUND | Run not in active runs |
GET /v1/runs/:runId
Run status and summary.| Field | Type | Description |
|---|---|---|
status | string | running, waiting-approval, finished, failed, cancelled |
startedAtMs | number | null | Start timestamp (ms) |
finishedAtMs | number | null | Finish timestamp (ms) |
summary | object | Node count by state |
GET /v1/runs/:runId/events
SSE stream of lifecycle events.| Parameter | Type | Default | Description |
|---|---|---|---|
afterSeq | number | -1 | Only events after this sequence number |
- Events named
smitherswith JSON payloads matchingSmithersEvent. - Polls database every 500ms.
- Keep-alive comment every 10s.
- Closes on terminal state (
finished,failed,cancelled). - Reconnect with
afterSeqto resume.
GET /v1/runs/:runId/frames
List render frames.| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Max frames |
afterFrameNo | number | undefined | Frames after this number |
POST /v1/runs/:runId/nodes/:nodeId/approve
Approve a node waiting for human approval.POST /v1/runs/:runId/nodes/:nodeId/deny
Deny a node waiting for human approval.GET /v1/runs
List all runs. Requires server-leveldb.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Max runs |
status | string | undefined | Filter by status |
DB_NOT_CONFIGURED if no database was provided.
Error Response Format
SERVER_ERROR.
Database Mirroring
When a server-leveldb is provided and the workflow uses a different database, run metadata and events are mirrored asynchronously to the server database. This enables cross-workflow listing via GET /v1/runs.