Skip to main content
The JSX API is Smithers’ component-based authoring layer. You describe the workflow as a tree of <Workflow>, <Task>, and control-flow components, and Smithers renders that tree into an execution plan. Use JSX when you want:
  • component composition and reusable workflow fragments
  • explicit control-flow nodes like <Approval>, <Parallel>, <MergeQueue>, and <Worktree>
  • render-time branching driven by ctx.outputMaybe(...)
  • MDX prompt templates
  • a TSX-first workflow authoring model

What JSX Looks Like

/** @jsxImportSource smithers-orchestrator */
import { createSmithers, Sequence, Task } from "smithers-orchestrator";
import { z } from "zod";

const analysisSchema = z.object({
  summary: z.string(),
});

const { Workflow, smithers, outputs } = createSmithers({
  analysis: analysisSchema,
});

export default smithers((ctx) => (
  <Workflow name="analyze-repo">
    <Sequence>
      <Task id="analyze" output={outputs.analysis}>
        {{ summary: `Analyze ${ctx.input.repo}` }}
      </Task>
    </Sequence>
  </Workflow>
));
The outputs object returned by createSmithers maps each schema key to its Zod schema. Passing output={outputs.analysis} instead of a magic string gives you compile-time type checking — a typo like output={outputs.anaylsis} is a type error, not a runtime surprise.

How JSX Execution Works

The JSX API is render-driven:
  1. Smithers renders the workflow tree with the current ctx.
  2. It extracts executable task descriptors from the rendered tree.
  3. It runs the ready tasks and persists their outputs.
  4. It renders again with the updated outputs in ctx.
That means branching and task visibility are usually expressed with normal JSX conditions:
const analysis = ctx.outputMaybe(outputs.analysis, { nodeId: "analyze" });

return (
  <Workflow name="code-review">
    <Task id="analyze" output={outputs.analysis}>...</Task>
    {analysis ? (
      <Task id="fix" output={outputs.fix}>...</Task>
    ) : null}
  </Workflow>
);

Two Common JSX Styles

Schema-driven JSX

Use createSmithers(...) with Zod schemas and the returned outputs object. This is the fastest JSX path and the best default for new workflows. The output prop is type-checked against the registered schemas.

Manual JSX

Use smithers(db, build) with explicit Drizzle table objects when you want lower-level control over persistence. Both styles compile to the same JSX renderer and execution engine.

How It Relates to the Other APIs

  • TOON is the declarative path. It is better when prompts are the main thing you are authoring.
  • Effect Builder is the low-level typed graph API. It is better when you want explicit step handles and heavy Layer composition.
  • JSX sits in the middle: more dynamic than TOON, less explicit than the Effect builder.

Next Steps

  • JSX Installation — Set up TypeScript, TSX, and optional MDX prompts.
  • JSX Quickstart — Build a two-step workflow.
  • Approval — Add a first-class approval node to the graph.
  • MergeQueue — Serialize a subtree with a concurrency cap.
  • Workflow — Start with the root component reference.