smithers

agent
Security Audit
Warn
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 314 GitHub stars
Code Warn
  • fs module — File system access in .github/workflows/sota-research.yml
  • process.env — Environment variable access in .smithers/agents.ts
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Durable runs for coding agents: survive crashes, pause for human approval, rewind mistakes. Claude Code, Codex, Gemini, any model.

README.md

Smithers

Long agent jobs shouldn't die when your terminal does.

npm
CI
License: MIT
Docs
Awesome Smithers

Tell your coding agent to do real, multi-step work, then Smithers runs it for minutes or
days with crash recovery, retries, human approvals, and full observability. The same
workflow runs across Claude Code, Codex, Pi, AI SDK models, and remote sandboxes.

Watch every step of a workflow run, pause execution, approve gates, and rewind to an
earlier checkpoint. Independent steps can run at the same time.

image

What you get

  • 🛡️ Durable runs that survive crashes: every completed step is persisted the moment it
    finishes, so a run resumes from where it stopped instead of starting over.
  • 🔌 Any agent, any model: Claude Code, Codex, Pi, Antigravity, and more, plus any model
    through the AI SDK. Swap the harness without rewriting the workflow.
  • 🛠️ Higher-quality output: review loops, human approvals, and evals give agents the
    structure that real work demands.
  • 🧩 Dozens of ready-to-run workflows: planning, implementation, review, debugging,
    tickets, audits, and long-horizon missions. Your agent can author new ones.

When to use Smithers

You want to… Smithers?
Get one answer from one prompt No, call the model directly
Let a coding agent change a repo across many steps Yes
Pause for a human approval, then resume later Yes
Run several agents that review, retry, and converge Yes
Survive crashes and replay, fork, or rewind a run Yes

Smithers is the durable runtime for coding-agent work: when the unit of work is an agent
editing a real repository over many steps, and you need that work to be inspectable,
approvable, and recoverable.

Why not just let my agent orchestrate itself?

Claude Code, Codex, and the other harnesses already fan out subagents, and for work that
fits in one sitting they are the right tool. The fan-out is ephemeral, though: it lives
inside one session, one vendor, and one terminal.

Built-in subagent fan-out A Smithers run
Dies when the session ends or crashes Persists and resumes from the last finished step
One vendor per session Claude, Codex, Gemini, and Pi share one workflow
An approval blocks the terminal An approval suspends the run durably, overnight if needed
A bad decision means starting over Rewind, fork, or replay from any step
Orchestration is a prompt you retype A workflow is a file you version, review, and rerun

When the work has to survive the session, hand the fan-out to Smithers. Your agent still
drives everything; the run just stops being disposable. The longer argument is in
the open, durable version of agent workflows.

Get started

Smithers is driven by your coding agent, not a GUI you click. Your agent runs Smithers
on your behalf: it scaffolds workflows, kicks off runs, watches them, and handles
approvals.

One command sets everything up. From inside your project:

bunx smithers-orchestrator init

init does everything:

  • Installs the smithers skill into the coding agents on your machine (Claude Code,
    Pi, and more), so your agent knows how and when to use Smithers. No mkdir, no curl.
  • Scaffolds .smithers/ with ready-made workflows (hello, implement, plan,
    review, debug, and more) your agent can pick from.

Then just ask:

"orchestrate an agent to add rate limiting and keep iterating until the tests pass."

Your agent picks the right workflow, starts the run, and keeps going through retries and
review loops until the work is actually done.

To wire the MCP server into every detected agent too, run bunx smithers-orchestrator mcp add. See Agent Support for the full per-agent
matrix, and skills/smithers/ for the onboarding skill itself.

What a workflow looks like

A workflow is a JSX tree of tasks. You usually don't write these by hand: you prompt your
agent, and it writes them from the same primitives the built-in pack uses. Each example
below starts with the prompt that produces it.

1. Two tasks, typed and persisted

"make me a smithers workflow that analyzes a bug report, then fixes it"

import { createSmithers, Sequence, OpenAIAgent } from "smithers-orchestrator";
import { z } from "zod";

const { Workflow, Task, smithers, outputs } = createSmithers({
  input: z.object({ description: z.string() }),
  analyze: z.object({
    summary: z.string(),
    severity: z.enum(["low", "medium", "high"]),
  }),
  fix: z.object({
    patch: z.string(),
    explanation: z.string(),
  }),
});

const analyzer = new OpenAIAgent({ model: "gpt-5.6-terra" });
const fixer = new OpenAIAgent({ model: "gpt-5.6-luna" });

export default smithers((ctx) => (
  <Workflow name="bugfix">
    <Sequence>
      <Task id="analyze" output={outputs.analyze} agent={analyzer}>
        {`Analyze the bug: ${ctx.input.description}`}
      </Task>

      <Task id="fix" output={outputs.fix} agent={fixer} deps={{ analyze: outputs.analyze }}>
        {(deps) => `Fix this issue: ${deps.analyze.summary}`}
      </Task>
    </Sequence>
  </Workflow>
));

Each task output is validated against its Zod schema and persisted to SQLite the moment it
completes. deps gives the fix task typed access to the analysis and mounts it only after
analyze finishes. If the process crashes, the run resumes without re-running finished
work.

This page is the 90-second version. The Tour is the
15-minute version: it builds a real code-review workflow one capability at a time.

2. Loop until a reviewer approves

"implement this request and keep iterating until a reviewer signs off"

import { createSmithers, Loop, CodexAgent } from "smithers-orchestrator";
import { z } from "zod";

const { Workflow, Task, smithers, outputs } = createSmithers({
  input: z.object({ request: z.string() }),
  impl: z.object({ summary: z.string(), filesChanged: z.array(z.string()) }),
  review: z.object({ approved: z.boolean(), feedback: z.string() }),
});

const coder = new CodexAgent({
  model: "gpt-5.6-luna",
  config: { model_reasoning_effort: "medium" },
});
const reviewer = new CodexAgent({
  model: "gpt-5.6-sol",
  config: { model_reasoning_effort: "xhigh" },
  sandbox: "read-only",
});

export default smithers((ctx) => (
  <Workflow name="implement-reviewed">
    <Loop until={ctx.latest(outputs.review, "validate")?.approved} maxIterations={5}>
      <Task id="implement" output={outputs.impl} agent={coder}>
        {`Implement: ${ctx.input.request}
Address this reviewer feedback first: ${ctx.latest(outputs.review, "validate")?.feedback ?? "none yet"}`}
      </Task>

      <Task id="validate" output={outputs.review} agent={reviewer}>
        {`Review the working-tree changes for: ${ctx.input.request}.
Approve only when the change is correct and tested.`}
      </Task>
    </Loop>
  </Workflow>
));

This is the loop a one-shot agent call can't give you: implement, review, feed the
feedback back in, repeat until approved. Every iteration is persisted, so a crash mid-loop
resumes at the current iteration instead of iteration one.

3. A small engineering team in one file

"split this request into tickets, implement them in parallel worktrees with review
loops, and after I sign off merge the approved branches one at a time"

import {
  createSmithers, Sequence, Parallel, Loop, Worktree, MergeQueue,
  Approval, CodexAgent, approvalDecisionSchema,
} from "smithers-orchestrator";
import { z } from "zod";

const { Workflow, Task, smithers, outputs } = createSmithers({
  input: z.object({ request: z.string() }),
  triage: z.object({
    tickets: z.array(z.object({ id: z.string(), description: z.string() })),
  }),
  impl: z.object({ ticketId: z.string(), summary: z.string() }),
  review: z.object({ ticketId: z.string(), approved: z.boolean(), feedback: z.string() }),
  shipApproval: approvalDecisionSchema,
  merge: z.object({ ticketId: z.string(), status: z.enum(["merged", "conflict"]) }),
});

const planner = new CodexAgent({
  model: "gpt-5.6-sol",
  config: { model_reasoning_effort: "xhigh" },
  sandbox: "read-only",
});
const coder = new CodexAgent({
  model: "gpt-5.6-luna",
  config: { model_reasoning_effort: "medium" },
});
const reviewer = new CodexAgent({
  model: "gpt-5.6-sol",
  config: { model_reasoning_effort: "xhigh" },
  sandbox: "read-only",
});

export default smithers((ctx) => {
  const plan = ctx.outputMaybe(outputs.triage, { nodeId: "triage" });
  return (
    <Workflow name="ship-tickets">
      <Sequence>
        <Task id="triage" output={outputs.triage} agent={planner}>
          {`Split this request into independent tickets: ${ctx.input.request}`}
        </Task>

        <Parallel maxConcurrency={4}>
          {plan?.tickets.map((t) => (
            <Worktree key={t.id} path={`.worktrees/${t.id}`} branch={`ticket/${t.id}`}>
              <Loop until={ctx.latest(outputs.review, `review-${t.id}`)?.approved} maxIterations={4}>
                <Task id={`implement-${t.id}`} output={outputs.impl} agent={coder}>
                  {`Implement ticket ${t.id}: ${t.description}
Reviewer feedback: ${ctx.latest(outputs.review, `review-${t.id}`)?.feedback ?? "none yet"}`}
                </Task>
                <Task id={`review-${t.id}`} output={outputs.review} agent={reviewer}>
                  {`Review the work for ticket ${t.id}. Approve only when correct and tested.`}
                </Task>
              </Loop>
            </Worktree>
          ))}
        </Parallel>

        <Approval
          id="ship"
          output={outputs.shipApproval}
          request={{ title: `Merge ${plan?.tickets.length ?? 0} reviewed branches?` }}
          onDeny="fail"
        >
          <MergeQueue id="merge" maxConcurrency={1}>
            {plan?.tickets.map((t) => (
              <Task key={t.id} id={`merge-${t.id}`} output={outputs.merge} agent={coder}>
                {`Rebase ticket/${t.id} onto main, run the test gate, and merge.`}
              </Task>
            ))}
          </MergeQueue>
        </Approval>
      </Sequence>
    </Workflow>
  );
});

Triage fans the request into tickets. Each ticket gets its own git worktree and its own
implement-review loop, with a frontier model planning, a fast model implementing, and a
different lab's model reviewing. Nothing merges until a human approves, and the merge
queue then lands branches one at a time. Kill the process at any point and resume:
finished tickets are skipped, in-flight ones re-run.

The full version of this pattern (dependency-ordered waves, a researcher agent for blocked
implementers) is examples/parallel-tickets.jsx.

Durable by default

Durability is the differentiator. Runs survive crashes, restarts, and flaky tools because
every completed step is persisted to SQLite the moment it finishes. The runtime always
knows what's done and what to run next. Approvals, human questions, retries, and replay are
first-class.

prompt → render workflow → run task → validate output → persist to SQLite → re-render → resume · inspect · replay

That loop is the whole model: a task runs, its output is validated against a schema and
written down, then the workflow re-renders from persisted state to decide the next task. A
crash at any point resumes from the last write, not from the top.

A run killed mid-task, then resumed: the completed task is skipped, the interrupted task re-runs, the run finishes.

A Smithers run is killed partway through, then resumes: the completed task is skipped, the in-flight task re-runs as a new attempt, and the run finishes
bunx smithers-orchestrator up workflow.tsx --input '{"description":"Fix bug"}'
bunx smithers-orchestrator up workflow.tsx --run-id abc123 --resume true   # resume after a crash
bunx smithers-orchestrator rewind abc123 --frame 4                          # time-travel to an earlier frame
bunx smithers-orchestrator fork abc123                                      # branch an alternate timeline
bunx smithers-orchestrator replay abc123                                    # replay from a checkpoint

Drive and watch your runs

Prefer the CLI? The seeded workflows run directly, and whether your agent started a run or
you did, you can see exactly what's happening:

bunx smithers-orchestrator workflow run hello   # smallest possible run; prompt lives at .smithers/prompts/hello.mdx
bunx smithers-orchestrator workflow run plan --prompt "add rate limiting and API key rotation"

bunx smithers-orchestrator ps              # list active, paused, and recently completed runs
bunx smithers-orchestrator inspect RUN_ID  # steps, agents, approvals, and outputs for one run
bunx smithers-orchestrator logs RUN_ID     # tail the event log
bunx smithers-orchestrator chat RUN_ID     # read the agent's chat output

ps shows you what needs attention (a paused approval, a recent failure); inspect drills
into a single run so you can follow each step and agent as it works. Run
bunx smithers-orchestrator starters to browse plain-English starters.

Any agent, any model

Smithers doesn't bet on one lab or one harness. Point a task at whichever agent is best for
the job, mix several in one workflow, and switch freely. The workflow doesn't change when
the model does, so a frontier model can plan, a fast model can fan out, and a specialized
harness can do the edits.

Agents that run tasks

Agent How it runs
Claude Code CLI harness
Codex CLI harness
Pi CLI harness
Antigravity CLI harness
Any AI SDK model SDK agent, with tools, structured output, and MCP

Sandboxes that isolate them

The same <Sandbox> primitive runs an agent locally or on a remote provider with no change
to the workflow:

Target Notes
Local default; syscall-isolated via Bubblewrap or Docker
Docker containerized execution on your machine or CI
Freestyle managed remote sandbox (see the example provider)
Bring-your-own implement the SandboxProvider interface for any backend (gVisor, Kubernetes, Daytona, Cloudflare, …)

Beyond init, bunx smithers-orchestrator mcp add also wires the MCP
server into Cursor, Copilot, Hermes, OpenClaw, and ~20 more coding agents.

Built-in workflows

bunx smithers-orchestrator init installs a pack of ready-to-run workflows: implement,
plan, research, review, debug, tickets-create, kanban, mission, grill-me,
improve-test-coverage, audit, research-plan-implement, and more. Point your agent at
one, or run it yourself:

bunx smithers-orchestrator workflow run implement --prompt "add rate limiting"

See docs/workflows/ for the full pack.

Examples

The examples/ folder has 100+ runnable workflows, one per orchestration
pattern. Copy one as a starting point:

Every orchestration pattern we could find: 100+ real, runnable Smithers workflows in one folder.

Example Pattern
code-review-loop Implement → review → fix, looped until approved.
parallel-tickets Triage, run waves of work in parallel, merge-queue the results.
supervisor A boss agent plans and delegates to workers dynamically.
playwright-test-agent Plan E2E flows, generate Playwright tests, run/heal until stable.
sql-analyst-dashboard Discover schema, check read-only SQL, execute, summarize with a chart.

The folder also covers panels, debates, migrations, RAG citation loops, canary judging,
SLO-breach explainers, repo janitors, and dozens more. Browse the full set in
examples/.

Components

The examples above use a handful of primitives from a much larger set:

Component Purpose
<Workflow> Root container
<Task> AI or static task node
<Sequence> Ordered execution
<Parallel> Concurrent execution
<Branch> Conditional execution
<Loop> Repeat tasks until a condition is met

There are many more: approvals, worktrees, merge queues, sub-workflows, signals, timers,
sagas, and composite patterns. See Components.

Also in the box

Smithers is built for agents that modify real repositories, so control is wired into the
runtime:

  • Approvals: gate destructive or risky steps behind a human approve / deny before
    they run.
  • Inspectable and reversible: every step, tool call, and output is persisted and
    replayable; rewind, fork, or replay any run from a checkpoint instead of living
    with whatever the agent left behind.
  • Isolated: run agents in a sandbox (Bubblewrap, Docker, or a
    bring-your-own remote provider) so edits never touch your host.
  • Observability: every run emits Prometheus metrics and OpenTelemetry traces. Bring up
    the local stack with bunx smithers-orchestrator observability --detach (Grafana, Prometheus, Tempo, OTLP
    collector) and serve metrics with bunx smithers-orchestrator up workflow.tsx --serve --metrics.
  • Evals: run repeatable workflow regressions from JSON/JSONL cases with
    bunx smithers-orchestrator eval workflow.tsx --cases evals/smoke.jsonl --suite smoke; the command exits
    non-zero when any case fails.
  • Prompt optimization: run GEPA-style optimization against an eval suite with
    bunx smithers-orchestrator optimize, which writes an optimized prompt artifact only when the score
    improves.
  • Hot reload: edit prompts, config, agent settings, or JSX structure mid-run with
    bunx smithers-orchestrator up workflow.tsx --hot. In-flight tasks finish on their original code; only
    newly scheduled tasks pick up changes.

Read next

Docs

Full documentation lives at smithers.sh.

License

MIT

Reviews (0)

No results found