Skip to main content
Run bunx smithers-orchestrator init first to scaffold a .smithers/ folder with ready-to-use workflows. This guide builds a custom workflow from scratch.

Step 1: Create the Workflow

workflow.tsx:
/** @jsxImportSource smithers-orchestrator */
import { createSmithers, Sequence, Task } from "smithers-orchestrator";
import { ToolLoopAgent as Agent } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";
import ResearchPrompt from "./prompts/research.mdx";
import ReportPrompt from "./prompts/report.mdx";

const { Workflow, smithers, outputs } = createSmithers({
  research: z.object({
    summary: z.string(),
    keyPoints: z.array(z.string()),
  }),
  report: z.object({
    title: z.string(),
    body: z.string(),
  }),
});

const researcher = new Agent({
  model: anthropic("claude-sonnet-4-20250514"),
  instructions: "You are an expert research assistant.",
});

const writer = new Agent({
  model: anthropic("claude-sonnet-4-20250514"),
  instructions: "You are a concise technical writer.",
});

export default smithers((ctx) => (
  <Workflow name="research-report">
    <Sequence>
      <Task id="research" output={outputs.research} agent={researcher}>
        <ResearchPrompt topic={ctx.input.topic} />
      </Task>

      <Task id="report" output={outputs.report} agent={writer} deps={{ research: outputs.research }}>
        {(deps) => (
          <ReportPrompt
            summary={deps.research.summary}
            keyPoints={deps.research.keyPoints}
          />
        )}
      </Task>
    </Sequence>
  </Workflow>
));
deps={{ research: outputs.research }} makes report wait for research. The child render function receives deps.research with the inferred schema type.

Step 2: Run It

main.ts:
import { runWorkflow } from "smithers-orchestrator";
import workflow from "./workflow";

const result = await runWorkflow(workflow, {
  input: { topic: "The history of the Zig programming language" },
});

console.log(result.status);
console.log(JSON.stringify(result.output, null, 2));
bun run main.ts

What Happened

  1. Smithers rendered the JSX tree. Only research was mounted.
  2. research ran, validated output against Zod, and persisted it.
  3. Re-render made the output available to report via deps.
  4. report mounted on the second render with typed deps.research.

Next Steps