Skip to main content
import { Branch } from "smithers-orchestrator";

Props

PropTypeDefaultDescription
ifboolean(required)Condition. true executes then; false executes else.
thenReactElement(required)Element to render when true.
elseReactElementundefinedElement to render when false. If omitted, nothing executes.
skipIfbooleanfalseSkip the entire branch regardless of condition. Returns null.

Basic usage

<Workflow name="deploy-pipeline">
  <Task id="test" output={outputs.test}>
    {{ passed: true, error: null }}
  </Task>

  <Branch
    if={ctx.output(outputs.test, { nodeId: "test" }).passed}
    then={
      <Task id="deploy" output={outputs.deploy}>
        {{ url: "https://prod.example.com" }}
      </Task>
    }
    else={
      <Task id="notify-failure" output={outputs.notifyFailure}>
        {{ message: "Tests failed, skipping deploy." }}
      </Task>
    }
  />
</Workflow>

Without an else branch

<Branch
  if={ctx.input.needsReview}
  then={
    <Task id="review" output={outputs.review} agent={reviewAgent}>
      Review the changes.
    </Task>
  }
/>

Complex sub-graphs

Each branch accepts any workflow element. Wrap multiple elements in <Sequence> or <Parallel>:
<Branch
  if={ctx.output(outputs.triage, { nodeId: "triage" }).severity === "critical"}
  then={
    <Sequence>
      <Task id="hotfix" output={outputs.hotfix} agent={codeAgent}>
        Write a hotfix for the critical issue.
      </Task>
      <Task id="emergency-deploy" output={outputs.emergencyDeploy}>
        {{ deployed: true }}
      </Task>
    </Sequence>
  }
  else={
    <Task id="add-to-backlog" output={outputs.backlog}>
      {{ queued: true }}
    </Task>
  }
/>

Conditional skipping

<Branch
  skipIf={ctx.input.dryRun}
  if={testsPass}
  then={<Task id="deploy" output={outputs.deploy}>{{ ok: true }}</Task>}
/>

Condition evaluation

The if prop is evaluated at render time. Smithers re-renders the tree each frame, so conditions can depend on outputs of completed tasks:
const check = ctx.outputMaybe(outputs.check, { nodeId: "check" });

return (
  <Workflow name="adaptive">
    <Task id="check" output={outputs.check} agent={checkAgent}>
      Check whether the system is healthy.
    </Task>
    <Branch
      if={check?.healthy === true}
      then={<Task id="proceed" output={outputs.proceed}>{{ ok: true }}</Task>}
      else={<Task id="remediate" output={outputs.remediate} agent={fixAgent}>Fix it.</Task>}
    />
  </Workflow>
);
Use ctx.outputMaybe() when the upstream task may not have completed yet.

Rendering

<Branch> renders the selected child wrapped in a <smithers:branch> host element. Only the selected branch’s tasks are mounted. The other branch is absent from the task graph.

Notes

  • Only one branch executes per render frame.
  • then and else each accept a single ReactElement. Wrap multiple elements in <Sequence> or <Parallel>.
  • Conditions are re-evaluated each render frame, enabling data-dependent control flow.