Skip to main content
Each recipe is a working snippet plus one line of context. They compose freely.
API reference: Reference overview maps every package to its exhaustive API page, each with links to source and tests.
If you want a ready-to-run outcome before writing workflow code, start with Starters or run bunx smithers-orchestrator starters.

Default model routing

Smithers-generated workflows are Codex-first when usable Codex authentication is available. GPT-5.6 Luna is now the broad default: start with it for research, implementation, ordinary tool use, UI work, and routine-to- substantial execution, then escalate only when the task earns the extra cost or judgment. Pin the tier to the role: Luna remains the first implementation, research, and ordinary tool-use model even for large or substantial changes; size alone does not promote it to Sol. Escalate to Terra only for explicitly tool-heavy validation or higher-judgment checking, and to Sol for ambiguous architecture, final review, high-stakes decisions, or repeated Luna failure. Non-Codex adapters are later sequential fallbacks when earlier Codex agents are unavailable or fail; they are not parallel peers or a second opinion on every run. claude-fable-5 is the configured smart-role fallback or an intentional Claude-native specialist. Explicit provider-specific workflows continue to run as written. See the SOTA model registry for the decision rules and primary release links.

Implement → review loop

Iterate until a reviewer signs off, with a hard cap.
Stop conditions must be measurable (boolean, count, array length). Avoid “looks good” prompts; agents are literal. In a <Loop> until, read the most recent iteration with ctx.latest. ctx.outputMaybe(.., { nodeId }) without an explicit iteration resolves the current render iteration (which equals the loop iteration only for a single, non-nested loop, and is 0 when several loops coexist), so an outputMaybe-based until can silently never advance.

Parallel Codex review

Two Codex tiers provide independent signals without routing to another provider. Cost = the slower model’s latency.
continueOnFail keeps one tier’s timeout from blocking the other.

Approval gate with branching

Decision data drives the next branch.
onDeny: "fail" aborts, "continue" proceeds without the gated branch, "skip" skips the gated tasks.

Retry policy & timeouts

Defaults to fit the work: simple tasks 30–60s + 1–2 retries, tool-heavy 2–5m + 1–2, large generations 5–10m + 0–1. Exponential backoff for rate-limited APIs.

Optional, non-blocking step

Use for nice-to-have telemetry, lint, optional analysis.

Conditional branch on output

ctx.outputMaybe for control flow.

Dynamic ticket discovery

Discover work, run each ticket, re-render to catch the next batch. Scales to large projects.
Use stable IDs (t.id, not array index) so resume matches.

Coherent task with tools

One context boundary per logical operation, not per step. Splitting too finely loses cross-step reasoning.

Per-agent least-privilege tools

Match the tool surface to the role.

Side-effect tools with idempotency

External mutations must mark themselves and use the runtime idempotency key.
Retries reuse the same idempotency key, so a successful side effect from attempt 1 isn’t doubled by attempt 2.

Caching for iterative authoring

Tweak the downstream Task without re-running the expensive upstream one. Don’t cache side effects.

Schemas in their own file

All data shapes in one place; new contributors read schemas.ts first.

MDX prompt with auto-injected schema

props.schema is the JSON-schema description of the Task’s outputSchema, auto-injected. Keeps the prompt and the validator in sync. In .mdx prompt files, prose that looks like JSX or HTML is parsed as JSX. Wrap examples such as <Parallel maxConcurrency={N}> in inline backticks or a fenced code block so the prompt module still compiles and exports its default prompt component.

Custom hooks over ctx

Workflow logic factors out into hooks the same way React UI logic does.

VCS revert & per-attempt snapshots

Smithers records the current JJ change ID in _smithers_attempts.jj_pointer per attempt. Revert any attempt with a recorded JJ pointer to its exact workspace state:
Useful when an experiment leaves the worktree in a bad state.

Time travel: fork, replay, diff

Fork makes a child run without starting it (add --run to start immediately); replay also makes a child run but immediately resumes it. --restore-vcs checks out the original revision so re-execution sees the same source.

Scoring tasks

Scorers run after the task and never block. Sample expensive scorers with ratio.

Eval suites for regressions

Use eval suites when you need repeatable workflow-level checks. Assertions support status, output (exact match), and outputContains (partial match). Reports land in .smithers/evals/<suite>.json; the command exits non-zero on failures.

Continue-as-new for very long runs

A run with too much accumulated state hands off to a fresh run with carried state.
Avoids unbounded SQLite growth in long-lived loops.

Hot reload while authoring

Edits to the workflow source apply on the next render frame without losing in-flight task state. Schema changes still require a fresh run.

Fork agent session context

Every agent task produces a reusable session snapshot. fork starts a new task from a copy of another task’s final context, without mutating the source.
fork adds the source as a dependency (the forked task waits for it), copies its conversation into a fresh session, then submits the new prompt. Both branches above start from the same investigation and never affect each other. Chain it for follow-ups (plan → implement → verify); inside a <Loop> it forks the latest completed snapshot for that id. See <Task> fork.