---
title: Why React?
description: Smithers is a JSX runtime because agents are extraordinarily good at writing React.
---

The first thing people ask is some version of: *React is for UI. Why is your workflow engine pretending to be a frontend?*

Short answer: **agents are incredible at writing React.** That's the whole pitch. Every other property of Smithers, including durability, time travel, hot reload, and composability, falls out for free once you accept that one premise.

This page is the long answer.

## The shape of the runtime

Forget orchestration for a minute. Here is everything Smithers does:

- **State lives in a durable store.** Every task output, every frame, every approval, and every signal is persisted through Smithers' storage adapter (SQLite, PGlite, or Postgres).
- **Workflows return a React tree.** The tree describes which tasks should run and in what order. It is not a UI; the host elements are `smithers:task`, `smithers:sequence`, `smithers:parallel`, `smithers:branch`, and `smithers:ralph`, exposed to workflow authors as the React components `<Task>`, `<Sequence>`, `<Parallel>`, `<Branch>`, and `<Loop>` (`<Loop>` is an alias for `<Ralph>`).
- **As tasks finish, React rerenders.** The next render reads the updated durable state, and the tree comes back different. Branches that were missing before now mount. Loops grow another iteration. Conditionals flip.
- **Every frame is stored durably.** Each render produces a snapshot of the workflow plan, indexed by frame number, alongside the outputs that triggered it.

That's it. Render → execute → persist → render. The render is pure. The persistence is durable. The loop is the program.

<Frame caption="Four stages, one cycle. The render is a pure function of state; persistence makes it durable; the re-render is what makes the plan evolve as tasks finish.">
  <img src="/images/why/render-loop.svg" alt="The Smithers runtime loop: render the workflow tree, extract ready tasks, execute them, persist outputs, then re-render against the new state" />
</Frame>

## What you get for free

Once the runtime has that shape, a stack of useful properties just *appear*:

**Agents inspect state easily through one control plane.** Ask what happened on
frame 17 of run `abc123` and the agent uses Gateway `getDevToolsSnapshot`,
`getNodeOutput`, or the public `tree`/`inspect` CLI. It does not need to know
which storage backend the workspace uses, and it must not query runtime tables
directly.

**Time travel is real, because every frame is a snapshot.** Smithers records a snapshot of each frame (nodes, outputs, and the jj pointer that was active when the frame ran) in the durable store. When you rewind to frame 5, Smithers calls revertToJjPointer to restore the working tree to that recorded jj state, then replays the workflow forward against the exact source code that ran the original. Not "logs of what happened," but the actual state.

<Frame caption="Because every frame is durable, the Gateway can fork a run from an earlier snapshot while the original timeline stays intact.">
  <img src="/images/why/task-fork.gif" alt="A Smithers run rewinds to an earlier frame and forks into a second branch that retries the work a different way" />
</Frame>

**The whole React hook ecosystem becomes available for orchestration.** `useMemo`, `useContext`, custom hooks: they all work. Want to factor the "wait for approval, then branch" pattern into a `useApprovalGate()` hook? Go ahead. The reconciler doesn't know the difference between a Task and a `<div>`.

**Complex workflows are easier for humans to read.** React is functional and composable. A 30-task pipeline reads like a component tree, not a YAML graph. A reviewer can `cmd+click` a `<TicketPipeline>` to see what it expands to. Reuse is just import-and-render.

**LLM prompts can be MDX files that take props.** A prompt is a component. It accepts inputs, embeds expressions, and renders to a string the agent sees. Versioning prompts means versioning files. Testing prompts means rendering them.

These are real benefits. But they're all *secondary*.

## The actual reason: agent experience

The real reason Smithers is React is that agents are unusually, disproportionately good at writing it.

Think about what that means. Every workflow engine asks the agent (or the human writing on its behalf) to learn a new DSL. A custom YAML schema. A node-and-edges graph format. A state-machine transition table. Each one is a domain the agent has seen a small amount of training data for.

React, on the other hand, is one of the most heavily represented domains in the entire training corpus of every modern model. JSX, hooks, conditional rendering, composition patterns, prop drilling, state colocation: agents have encountered millions of examples of all of it. They write it fluently, idiomatically, and without coaching.

So Smithers does the obvious thing: **map orchestration onto a domain agents are already optimized for.** A workflow becomes a component tree. A dependency becomes a conditional render. A loop becomes `<Loop>` with the same `key` semantics agents already know. An iteration's previous output is read with the same mental model as state in a parent component.

This is what we mean by agent experience. Just as DX (developer experience) is the discipline of designing tools humans love to use, agent experience is the discipline of designing tools agents are good at. A great way to set up an agent to perform well on a hard problem is to express the problem in a domain the agent has already mastered.

That is why, as Smithers has stabilized, it has become the orchestration tool agents reach for: not because it's the most powerful (other engines are more featureful), and not because the API is small (it isn't), but because **agents write workflows that run correctly more often, with less back-and-forth coaching, than they do with bespoke DSLs.** They write a workflow, it runs. They debug a failed task, they fix it. They refactor a 200-task pipeline, they don't break it.

## The objection, answered

If you're still skeptical, the objection usually goes: *"But React is for views. You've taken a tool designed for one job and forced it to do another."*

This gets the history backwards. React is not fundamentally about the DOM. It's a reconciler, a general-purpose engine for diffing a declarative tree against a previous version and producing a minimal set of imperative operations. React Native uses it to drive native views. Ink uses it to drive terminal UIs. React Three Fiber uses it to drive a 3D scene graph. Smithers uses it to drive a task graph.

The reconciler is the abstraction. The DOM was just the first host. We're a different host.

## Read next

- [How It Works](/how-it-works): the render → execute → persist loop in detail.
- [JSX API](/jsx/overview): setup, tsconfig, and the minimal workflow.
- [Tour](/tour): six-step worked example.
