On the treadmill
Every six months, the “right” way to build an AI agent changes.
If you coupled your infrastructure to any one of these patterns, you’ve already rebuilt at least twice. And you’ll rebuild again.The cadence is speeding up beyond humans changing their minds. Wrap a workflow in a self-improving outer loop (the Hermes-shaped thing: one agent watches another’s traces and edits the workflow’s source) and the meta moves on its own. By next Thursday the workflow your agent runs is one no human author ever wrote. That raises two problems Smithers exists to solve:
- Authoring a complex workflow from scratch is hard.
- Maintaining, changing, and reusing it as the meta shifts is harder.
On the substrate
Here’s the thesis: there’s a layer that doesn’t change. Durable orchestration: steps, events, state, retries, observability.Smithers is that layer: underneath the JSX surface is an Effect.ts runtime, and users who already think in
Effect.gen can use the lower-level Effect API for full access to the substrate. The same review workflow:
On the framework trap
Agent frameworks aren’t libraries. They’re bets on which agent pattern wins. When the pattern shifts, you don’t refactor; you rewrite.The trap is the topology, not the framework: an abstraction over the substrate (durable steps, retries, persistence, suspension, observability) ages fine, while one over the topology (graphs, crews, swarms, role-based agents, conversational multi-agent) ages out as soon as the topology does. The mistake: conflating the two and throwing both away when one expires. Smithers doesn’t pick a topology for you: it hands you a primitive (a durable, retryable, observable task) and lets you compose it into whatever shape your problem and model want this quarter, or this minute.
On abstracting the right thing
Abstract the primitives: steps, retries, state. Don’t abstract the topology.The test of “did you abstract the primitives well enough” is whether the topologies you keep building can stop being snowflakes. If your primitives are good, named patterns fall out as compositions, not runtime opinions, and Smithers ships these as components on top of the substrate, never in place of it:
None of these are baked into the runtime;
<ReviewLoop> is roughly:
On the five primitives
Five primitives show up underneath every pattern: durable steps, persistent external state, parallel work coordination, event-driven control flow, structured execution observability.These are five capabilities the substrate has to provide, not five sealed primitives, delivered in Smithers as uniform Effect.ts effects.
A retry policy is just a
Schedule. A dependency is a Layer. A timeout is Effect.timeout. We didn’t invent a parallel ecosystem; we borrowed one that already does this well.
On background agents
The next major pattern shift is already happening: from synchronous chat agents to asynchronous background agents. This is where most infrastructure falls apart, and where durable orchestration becomes non-negotiable.Synchronous chat is forgiving: the user’s staring at the screen, retries are free, a five-minute Lambda timeout is fine. Background agents are a different shape: they run for hours, survive deploys, pause for a human approval that won’t arrive until tomorrow, and wake back up at the right step when the human finally shows up. You can build this with a queue and a database, but you’ll be reinventing 60% of what Smithers (or any honest durable execution layer) already does, more poorly. In Smithers, it’s all one shape:
<Approval> durably suspends the workflow; a reviewer answers tomorrow morning via CLI, web UI, or HTTP. The supervisor (bunx smthrs supervise) watches for stale heartbeats and resumes runs that died, none of it application code you write.
On sandboxes
Sandboxes operate at the compute layer: they answer “where does the agent run?” Some pause and resume the full VM state, which is powerful, but it’s a runtime snapshot, not a workflow snapshot.The essay stops one step short of the practical question: do you sandbox the whole graph, each task, or some mix? In production the answer is “it depends, and we want to change it without rewriting.” A single shared sandbox is fine until two parallel agents fight over port 5173 in one end-to-end test, and then you want per-task isolation, or a hybrid where the planner runs in a long-lived sandbox and each implementation step gets its own throwaway one. Smithers exposes a
Sandbox component that runs a child workflow, or a single step, in an isolated runtime: whole-graph, per-step, or mixed, with a pluggable provider.
This is the part of Smithers where we keep changing our mind on the right abstraction: per-task isolation that’s clean locally and in the cloud, generic over providers, is hard to nail. Expect this surface to lock down soon.
On conflating layers
The two layers are complementary, but conflating them is a costly mistake on the road to production.We’ve watched teams burn six months on this exact mistake. Sandbox providers solve isolation; orchestration solves “which step is in flight, which is done, which crashed, which is blocked on a human, what the dependency graph is, how to resume.” Stack them, don’t merge them.
On composability
Durable orchestration isn’t just about reliability. It’s about composability.Composability is what lets the named patterns above exist as libraries instead of runtime opinions, and what lets the workflow author (increasingly an agent) refactor the flow without breaking the substrate.
On the missing fourth layer (and our one disagreement)
The orchestration layer (stable). The agent layer (fluid). The model layer (volatile).The three-layer model misses a fourth: the authoring layer. In 2026 a lot of workflow code is written and re-tuned by other agents, so the authoring surface has to be legible both to the agents increasingly editing it and to the humans auditing what they wrote. That’s why we picked React, above. It’s also where we have our one real disagreement with the essay: it treats event-driven control flow as a substrate primitive, where events fire, handlers run, and handlers schedule the next thing. Smithers has the same machinery: callbacks fire on task completion, agent outputs auto-decode and write to SQLite, retries are scheduled by the substrate, and
<Signal>/<WaitForEvent> durably suspend. You can wire events directly to scheduling decisions in the Effect API if you want, but we don’t recommend it.
We recommend one-way data flow instead: events update state; state is the source of truth; the plan is a pure function over state. New event arrives → SQLite updates → re-render the plan → diff against what’s already scheduled → schedule the diff: the same flow React uses for the DOM, applied to a workflow graph.
The reasons are the same ones behind picking React for the authoring surface:
- Agents are better at writing declarative trees than imperative graphs, and the model’s JSX-shaped prior shows it: an LLM refactors, extends, and debugs state-driven JSX at a rate no imperative graph matches.
- Humans audit declarative trees better too. A complex JSX tree reads top to bottom, steps and control flow and data flow all visible. Understanding one run of an event-driven graph means mentally simulating which events fire which handlers in what order with what side effects, a cost that grows non-linearly; declarative orchestration stays linear, which matters at 3am when something’s gone wrong.
On readiness
Background agents aren’t coming. They’re here. The only question is whether your infrastructure is ready to let them run, or whether you’re about to rebuild it again.Our answer is the rest of these docs. Durable steps with retries by default. Prometheus and SQLite observability with no setup. Approval, Signal, HumanTask, Sandbox. Named composition components on top of the substrate, not in place of it. The focused default pack gives agents
create-workflow, create-skill, and docs-driven-development; the former starter patterns remain copyable examples. A managed hub if you don’t want to run the dashboard yourself.