Skip to main content

Orchestration

The <Orchestration> component provides top-level control over multi-agent workflows, including global timeouts, stop conditions, and cleanup.

Basic Usage

import { Orchestration, SmithersProvider, Claude } from "smithers";

async function MyWorkflow() {
  return (
    <SmithersProvider db={db} executionId={executionId}>
      <Orchestration
        globalTimeout={3600000}  // 1 hour max
        onComplete={() => console.log("Workflow complete")}
        onError={(err) => console.error("Workflow failed", err)}
      >
        <Claude model="sonnet">
          Do the work.
        </Claude>
      </Orchestration>
    </SmithersProvider>
  );
}

Props

globalTimeout
number
Maximum time in milliseconds for the entire workflow. The workflow is stopped if this timeout is exceeded.
<Orchestration globalTimeout={3600000}>  {/* 1 hour */}
stopConditions
StopCondition[]
Array of conditions that can stop the workflow early.
<Orchestration
  stopConditions={[
    { type: "total_tokens", value: 100000 },
    { type: "total_agents", value: 50 },
    { type: "report_severity", value: "critical" },
  ]}
>
snapshotBeforeStart
boolean
Create a VCS snapshot before starting (useful for rollback).
<Orchestration snapshotBeforeStart>
cleanupOnComplete
boolean
Run cleanup operations when workflow completes.
onComplete
() => void
Callback when workflow completes successfully.
onError
(error: Error) => void
Callback when workflow fails.
onStopRequested
() => void
Callback when a stop is requested (via stop condition or manual request).

Stop Conditions

Stop conditions allow automatic workflow termination based on various criteria:

Token Limit

Stop when total tokens exceed a threshold:
<Orchestration
  stopConditions={[
    { type: "total_tokens", value: 100000 }
  ]}
>

Agent Limit

Stop after a certain number of agent invocations:
<Orchestration
  stopConditions={[
    { type: "total_agents", value: 20 }
  ]}
>

Time Limit

Stop after a duration:
<Orchestration
  stopConditions={[
    { type: "total_time", value: 1800000 }  // 30 minutes
  ]}
>

Report Severity

Stop when a critical report is logged:
<Orchestration
  stopConditions={[
    { type: "report_severity", value: "critical" }
  ]}
>

CI Failure

Stop when CI fails:
<Orchestration
  stopConditions={[
    { type: "ci_failure" }
  ]}
>

Custom Condition

Define your own stop logic:
<Orchestration
  stopConditions={[
    {
      type: "custom",
      fn: (result) => result.output.includes("ABORT"),
      message: "Agent requested abort"
    }
  ]}
>

Combining with Ralph

For iterative workflows, combine Orchestration with Ralph:
<SmithersProvider db={db} executionId={executionId}>
  <Orchestration
    globalTimeout={3600000}
    stopConditions={[
      { type: "total_tokens", value: 50000 }
    ]}
  >
    <Ralph maxIterations={10}>
      <Phase name="implementation">
        <Claude
          model="sonnet"
          onFinished={(result) => {
            // Update state, triggering next iteration
          }}
        >
          Implement the feature.
        </Claude>
      </Phase>
    </Ralph>
  </Orchestration>
</SmithersProvider>

Manual Stop Requests

Request a stop programmatically using the SmithersProvider context:
function EmergencyStop() {
  const { requestStop, isStopRequested } = useSmithers();

  return (
    <Claude
      onFinished={(result) => {
        if (result.output.includes("CRITICAL ERROR")) {
          requestStop();
        }
      }}
    >
      Check system health.
    </Claude>
  );
}

function Workflow() {
  const { isStopRequested } = useSmithers();

  return (
    <Orchestration onStopRequested={() => console.log("Stop requested!")}>
      {!isStopRequested() && <EmergencyStop />}
      {!isStopRequested() && <MainWorkflow />}
    </Orchestration>
  );
}

Phases and Steps

Organize workflow structure with phases and steps:
<Orchestration globalTimeout={3600000}>
  <Phase name="research">
    <Step name="find-files">
      <Claude allowedTools={["Glob", "Grep"]}>
        Find relevant files.
      </Claude>
    </Step>
    <Step name="analyze">
      <Claude allowedTools={["Read"]}>
        Analyze the code.
      </Claude>
    </Step>
  </Phase>

  <Phase name="implementation">
    <Step name="write-code">
      <Claude allowedTools={["Edit", "Write"]}>
        Implement the solution.
      </Claude>
    </Step>
    <Step name="test">
      <Claude allowedTools={["Bash"]}>
        Run the tests.
      </Claude>
    </Step>
  </Phase>
</Orchestration>

VCS Snapshots

Create snapshots for rollback:
<Orchestration
  snapshotBeforeStart
  onError={async (error) => {
    // Rollback to the snapshot
    const snapshots = await db.vcs.getSnapshots(1);
    if (snapshots.length > 0) {
      await execSync(`git checkout ${snapshots[0].commitRef}`);
    }
  }}
>

Error Handling

Handle errors at the orchestration level:
<Orchestration
  onError={async (error) => {
    // Log the error
    await db.vcs.addReport({
      type: "error",
      severity: "critical",
      title: "Workflow Failed",
      content: error.message,
    });

    // Notify
    await sendSlackNotification(`Workflow failed: ${error.message}`);
  }}
>

Best Practices

Prevent runaway workflows:
<Orchestration globalTimeout={3600000}>  {/* 1 hour */}
Prevent unexpectedly high API costs:
<Orchestration
  stopConditions={[
    { type: "total_tokens", value: 100000 }
  ]}
>
Create rollback points:
<Orchestration snapshotBeforeStart>

Next Steps