0.15.0
0.15.0 is the biggest release since launch. The headline is the Gateway — a server that turns your workflows into a remotely controllable service, enabling bots, dashboards, and CI integrations. Under the hood, the engine has been rebuilt on top of the Effect ecosystem for durable execution, and tasks now retry infinitely by default.Gateway — Deploy Workflows as a Service
Until now, smithers workflows ran locally from the CLI. The Gateway changes that: it’s a server that exposes your workflows over WebSocket and HTTP so that external systems — bots, dashboards, CI pipelines, webhooks, cron jobs — can start runs, stream progress, approve human-in-the-loop gates, and deliver signals, all programmatically. If you’ve wanted to build a Slack bot that kicks off a code review workflow when a PR opens, or a dashboard where your team monitors and approves deployments, the Gateway is how you do it.Quick start
HTTP fallback
Every RPC method works viaPOST /rpc for stateless integrations:
Authentication
| Mode | Use case |
|---|---|
token | Static bearer tokens mapped to roles/scopes. Simplest option. |
jwt | Verify HS256 JWTs with configurable issuer, audience, and claim mapping. |
trusted-proxy | Behind a reverse proxy that handles auth. Identity from headers. |
Access control
Every method requires a minimum access level:| Level | Can do | Methods |
|---|---|---|
read | View runs, frames, attempts | runs.list, runs.get, frames.list |
execute | Start, cancel, signal runs | runs.create, runs.cancel, signals.send |
approve | Decide human-in-the-loop gates | approvals.decide |
admin | Manage cron schedules | cron.add, cron.remove |
Cron scheduling
cron.list, cron.add, cron.remove, cron.trigger.
Approval modes
Approval nodes surface as gateway events. Four modes: gate (yes/no), decision (approve/deny with notes), select (pick from options), rank (order by preference). Restrict who can approve withallowedScopes
and allowedUsers, or set autoApprove policies for fully autonomous workflows.
Durability
Infinite retry by default
Tasks now retry indefinitely with exponential backoff (1s → 2s → 4s → … capped at 5 minutes). Transient failures, rate limits, and model errors are absorbed automatically. Your workflows are durable by default.Side-effect safety
When a task retries after a previous attempt invoked non-idempotent tools, the agent prompt now includes an explicit warning that those side effects may have already occurred — preventing duplicate deployments, duplicate emails, etc.Resume contract hardening
Resume now acquires a durable DB claim before reactivating a run, which closes the split-brain window around stale-run recovery and detached supervisor handoff.- Live owner protection — A
runningrun will not be resumed if its recorded owner PID is still alive, even when--forceis used. - Stricter code drift detection — Resume compatibility now checks both the workflow entry file hash and the local import graph hash. Changing an imported workflow module invalidates resume the same way changing the entry file does.
- Child workflow provenance — Subflows now inherit workflow identity/root provenance so the same resume safety checks apply to child runs.
- Retry exhaustion stays terminal — Failed tasks with no retries remaining stay failed on resume unless the workflow definition now allows more retries.
Deterministic durable outputs
Approval-style components andSuperSmithers no longer write wall-clock
timestamps into durable task outputs. Human decision timing still exists in the
approval records and append-only event log, but replayed durable outputs stay
deterministic.
New Components & APIs
-
<Signal>— Typed wrapper over<WaitForEvent>. Validates the incoming payload against a Zod schema and passes typed data to children. -
defineTool()— First-class custom tool authoring with automatic event logging, idempotency keys, and side-effect tracking. -
usePatched()— Workflow versioning hook. Returnstruefor new runs,falsefor replaying runs. Enables safe rolling deployments. -
Task-level
allowTools— Restrict which CLI tools an agent can invoke per task. Combine withcliAgentToolsDefault: "explicit-only"for fine-grained agent sandboxing. -
Semantic MCP tools — Stable agent-facing tool surface:
list_workflows,run_workflow,get_run,resolve_approval,revert_attempt, and more. -
IDE integration —
smithers-ideMCP surface for editor tooling: open files, show diffs, run terminals, ask the user, render webviews.
CLI
smithers signal— Deliver structured data to a<Signal>or<WaitForEvent>node from the command line.smithers retry-task— Retry a specific task without time travel. Resets the node and dependents, re-executes only what changed.smithers timetravel— Revert to a previous task state. Optionally restore the VCS filesystem and resume immediately.smithers askdiagnostics —--dump-prompt,--tool-surface,--list-agents,--print-bootstrapfor debugging agent bootstrap.
Engine Redesign
The engine has been incrementally rebuilt on the Effect ecosystem. This is an internal change — your workflow code doesn’t change — but it gives smithers proper durable execution semantics: replay-safe activities, crash-recoverable deferred waits, workflow-level determinism, and a worker model that can scale beyond a single process. What changed:- Task execution is now wrapped in Effect Activities with structured retries, heartbeat propagation, and idempotency keys
- Approvals and signals are backed by DurableDeferred for replay-safe resolution
- The scheduler loop is wrapped in Workflow.make() with parent-child linkage
- Internal tables route through SqlMessageStorage (
@effect/sql-sqlite-bun) instead of raw drizzle — user output tables are unchanged - Task dispatch routes through a worker entity model (in-process by default, zero overhead), enabling future multi-process and remote execution
- Sandbox execution routes through entity-based runners with crash recovery
@effect/workflow, @effect/cluster, @effect/rpc,
@effect/sql-sqlite-bun are now used at runtime. They were already in
package.json but previously unused.
Observability
- Prometheus context-window usage buckets — Agent token reporting now emits
smithers_tokens_context_window_per_callplussmithers_tokens_context_window_bucket_total{bucket=...}so you can alert on prompt/context size ranges:<50k,50k-100k,100k-200k,200k-500k,500k-1m, and>=1m.
Breaking Changes
- Zod v3 support removed. The
zodV3Compat.tsshim has been deleted. All schema handling uses Zod v4 natively. If your workflows import from"zod", you’re already on v4 and nothing changes. If you were on Zod v3, upgrade before adopting 0.15.0.
Run Status Reclassification
- Stale runs surfaced as
continued— Runs whose heartbeat has gone stale now appear as"continued"instead of"running"ingetRun,listRuns, and the API. Filtering bystatus=runningalso includescontinuedfor backwards compatibility.
New Run Status
waiting-event— paused on a<WaitForEvent>or<Signal>node
New Workflows
<Sweep>— Cross-topic feature auditing workflow. Scans multiple areas of the codebase in a single pass to surface inconsistencies and missing coverage.
Fixes
- Failed resume no longer corrupts run state — If resume is rejected before the run is durably claimed and activated, smithers now leaves the existing run record untouched instead of marking it failed.
- Child process cleanup on cancel — Agents now spawn with
detached: trueand kill the entire process group on abort. Fixes zombie accumulation. - Input schema table generation — Input tables now get a
run_id-only primary key instead of the composite task key. - OpenAI schema sanitization —
sanitizeForOpenAI()fixes Zod v4 JSON Schema output for OpenAI’sresponse_formatconstraints. - Codex resume flag —
--output-schemaomitted when resuming Codex sessions. - Heartbeat timeouts — Raised from 60s/120s to 300s/300s. CLI agents need time to think.
picocolorsdependency — Now declared explicitly inpackage.json.- Stop retrying invalid heartbeat payloads — Heartbeats with malformed data no longer trigger infinite retry loops.
- Stop retrying deterministic invalid outputs — Tasks that fail with non-transient output validation errors are no longer retried.
- HTTP request metrics deterministic — Prometheus HTTP request metrics no longer drift due to timing races in tests.
- Kanban column retry configuration — Kanban columns can now configure per-task retry behavior.
- Preserve devtools hook instrumentation — DevTools hooks are no longer stripped during engine teardown.
- Settle aborted tasks before cancelling runs — Aborted tasks are now awaited before the run is marked cancelled, preventing orphaned state.
- Continue-on-fail tasks default to single-shot — Tasks with
continueOnFailnow default tonoRetryto avoid masking permanent failures.
Tooling
- oxlint — Added as a fast lint pass. Existing autofixable issues resolved.
Error Codes
- Added:
EXTERNAL_BUILD_FAILED,SCHEMA_DISCOVERY_FAILED