The Effect API is the lower-level authoring surface for teams that already model application logic withDocumentation Index
Fetch the complete documentation index at: https://smithers.sh/llms.txt
Use this file to discover all available pages before exploring further.
Effect, Layer, and Schema. It uses the same Smithers runtime as JSX: steps are persisted in SQLite, completed work is not re-run on resume, outputs are schema-validated, and dependencies drive scheduling. The difference is authoring style: you compose a graph with functions instead of rendering JSX.
Use JSX for most workflows. Use the Effect API when your workflow is part of an Effect service, you want step bodies to return Effect values directly, or you need a React-free API for generated workflow definitions.
Minimal workflow
execute() returns an Effect. The success value is the decoded output of the final graph node: a step output for a single step, the last child for a sequence, or an array for a parallel block. If the run stops on an approval or timer, the success value is the normal RunResult with a waiting status.
Steps and dependencies
Create steps with$.step(id, options). IDs are durable: changing an ID creates a new task and leaves the old persisted output behind. A step can return a plain value, a Promise, or an Effect; Smithers decodes the result with the step’s output schema before writing it.
Use needs to read completed step outputs inside another step:
input, dependency values, executionId, stepId, attempt, iteration, signal, heartbeat(data), and lastHeartbeat.
Control flow
Use$.sequence(...) for ordered work and $.parallel(...nodes, { maxConcurrency }) for concurrent work. Use $.match(source, { when, then, else }) when a completed step decides which branch mounts, and $.loop({ id, children, until, maxIterations }) for repeated work. Nested loops are not supported.
Smithers.createComponent({ name }).build(($, params) => ...), then mount it with $.component("instance-id", component, params). Component step IDs are prefixed with the instance ID so multiple instances do not collide.
Operational notes
- Provide exactly one persistence layer with
Effect.provide(Smithers.sqlite({ filename })). - Keep step IDs stable across releases; use new IDs for materially different work.
- Use
heartbeat()in long-running steps and honorsignalin external calls. - Use
retry,retryPolicy,timeout,skipIf, andcachethe same way you would on JSX tasks. - Prefer idempotent step bodies. For external side effects, use
executionId,stepId, andattemptwhen constructing idempotency keys.