Skip to main content
The Effect builder API is Smithers’ advanced workflow definition layer. It gives you full access to Effect’s type system, dependency injection, and runtime composition. Most workflows should start with TOON files. Use the Effect builder when you need:
  • Custom Context.Tag services with complex lifecycle
  • Programmatic graph construction
  • Advanced type-level constraints on step dependencies
  • Direct integration with existing Effect application code

Quick Comparison

The same workflow in TOON and Effect builder: TOON:
name: bugfix
input:
  ticketId: string
  description: string

steps[2]:
  - id: analyze
    prompt: "Analyze the bug: {input.description}"
    output:
      summary: string
      severity: "low" | "medium" | "high"

  - id: fix
    prompt: "Fix based on analysis: {analyze.summary}"
    output:
      patch: string
      explanation: string
Effect builder:
import { Context, Effect, Layer, Schema } from "effect";
import { Model } from "@effect/sql";
import { Smithers } from "smithers-orchestrator";

class Input extends Schema.Class<Input>("Input")({
  ticketId: Schema.String,
  description: Schema.String,
}) {}

class Analysis extends Model.Class<Analysis>("Analysis")({
  summary: Schema.String,
  severity: Schema.Literal("low", "medium", "high"),
}) {}

class Fix extends Model.Class<Fix>("Fix")({
  patch: Schema.String,
  explanation: Schema.String,
}) {}

class Coder extends Context.Tag("Coder")<
  Coder,
  {
    readonly analyze: (description: string) => Effect.Effect<Analysis>;
    readonly fix: (analysis: Analysis) => Effect.Effect<Fix>;
  }
>() {}

const Bugfix = Smithers.workflow({
  name: "bugfix",
  input: Input,
}).build(($) => {
  const analyze = $.step("analyze", {
    output: Analysis,
    run: ({ input }) =>
      Effect.gen(function* () {
        const coder = yield* Coder;
        return yield* coder.analyze(input.description);
      }),
  });

  const fix = $.step("fix", {
    output: Fix,
    needs: { analysis: analyze },
    run: ({ analysis }) =>
      Effect.gen(function* () {
        const coder = yield* Coder;
        return yield* coder.fix(analysis);
      }),
  });

  return $.sequence(analyze, fix);
});
The Effect builder is more verbose but gives you typed service injection, explicit dependency handles, and full control over retry policies, timeouts, and Layer composition.

When to Use Effect Builder

ScenarioRecommendation
Prompt-centric workflowUse TOON
Custom services with Context.Tag and LayerUse Effect builder
Programmatic step generationUse Effect builder
Existing Effect application integrationUse Effect builder
Simple sequential stepsUse TOON
Complex branching with typed discriminantsUse Effect builder

Mixing TOON and Effect

TOON and Effect builder workflows coexist in the same project. A TOON workflow can import Effect services through its imports: block, and an Effect builder workflow can reference TOON components. Both compile to the same internal graph and run on the same durable execution engine.

Next Steps