Xzero UI
Pro library

Agent orchestratorPro

A lead agent splits a goal into a plan, fans the subtasks out to parallel worker lanes and merges what comes back, with each lane's model, progress and result in view.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/agent-orchestrator
Live · keyboard ready

Pass a goal and run, which emits plan, dispatch, progress and result events, to show a real orchestration; with no props it plays a sample run.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/agent-orchestrator

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { AgentOrchestrator, type OrchestratorRun } from "@/components/xzero/blocks/agent-orchestrator/agent-orchestrator";

// Yield events from your orchestrator. The block handles timing, pulses, queues and totals.
const run: OrchestratorRun = async function* ({ goal, workers, concurrency, signal }) {
  const plan = await planWithLead(goal, workers);           // your lead model call
  for (const subtask of plan) yield { type: "plan", subtask };

  for await (const update of runWorkers(plan, { concurrency, signal })) {
    // update.kind: "dispatch" | "tool" | "toolDone" | "text" | "usage" | "error" | "retry" | "result"
    if (update.kind === "dispatch") yield { type: "dispatch", subtaskId: update.id };
    if (update.kind === "tool") yield { type: "tool", subtaskId: update.id, tool: update.tool, target: update.target };
    if (update.kind === "text") yield { type: "output", subtaskId: update.id, delta: update.text, newLine: update.first };
    if (update.kind === "usage") yield { type: "usage", subtaskId: update.id, tokens: update.tokens, cost: update.cost };
    if (update.kind === "error") yield { type: "error", subtaskId: update.id, message: update.message, retryInMs: 2000 };
    if (update.kind === "result") yield { type: "result", subtaskId: update.id, text: update.text };
  }

  for await (const delta of streamSummary(signal)) yield { type: "summary", delta };
  yield { type: "done" };
};

export function PricingReview() {
  return (
    <AgentOrchestrator
      goal="Compare our pricing page with four competitors and suggest changes"
      run={run}
      defaultConcurrency={3}
      onComplete={result => saveReport(result.summary, result.cost)}
    />
  );
}

API reference

AgentOrchestrator

A lead agent splits a goal into a plan, fans the subtasks out to parallel worker lanes and merges what they return. The lead writes its plan one subtask at a time, then dispatches each subtask down a connector to its lane; a short pulse runs the connector on dispatch and again when the result comes back. Each lane shows its model, subtask, the current tool (web search, fetch page, read file, write findings), one line of streaming output, rolling tokens and cost, and elapsed time; a lane that fails counts down to a retry. When every lane has returned, the lead streams a summary and a totals row compares the wall time with running every subtask in sequence. A concurrency limit from 1 to 4 holds extra lanes in a visible queue, and clicking a lane opens its compact transcript. Lanes sit side by side on wide cards and stack under a trunk on narrow ones; the connectors are measured from the real layout and follow either arrangement.

PropTypeDefaultDescription
goalstring"Compare our pricing page with four competitors and suggest changes"What the lead agent is asked to do. Shown as the card heading and passed to the run hook.
planOrchestratorSubtask[]samplePlanSubtasks passed to the run hook: { id, title, instruction?, workerId? }. The title heads the lane; the instruction is the line the lead writes in its plan. The built in simulation writes this plan; your own hook may yield a different one with plan events.
workersOrchestratorWorker[]Claude Sonnet 5.5, Claude Haiku 5.5, Gemini 3.8 Flash, GPT-6 LunaThe worker lanes in order: { id, name, mark? }. A subtask lands on the worker named by its workerId, or on the next free worker. Up to four lanes sit side by side; more always stack.
lead{ name: string; mark?: ReactNode }Claude Opus 5.5The lead agent shown at the top of the flow and again on the summary.
run(context: OrchestratorRunContext) => AsyncIterable<OrchestratorEvent>simulateOrchestrationThe run hook. It receives { goal, plan, workers, concurrency(), signal } and yields events: plan, dispatch, tool, toolResult, output, usage, error, retry, result, fail, summary and done. An async generator is the simplest way to write one. The signal aborts on Stop, on Run again and on unmount. Without it the block plays a local simulation and says so in its status region.
concurrencynumber–Controlled concurrency limit from 1 to 4. Leave it out to let the built in control own the value.
defaultConcurrencynumbernumber of workers, at most 4Starting limit when uncontrolled.
onConcurrencyChange(value: number) => void–Called when someone picks a new limit. The run hook reads the live value through context.concurrency(), so raising it mid run releases queued lanes at once.
autoStartbooleantrueStarts the first run when the block scrolls into view. Never starts on its own with reduced motion; the Run button is always there.
onComplete(result: OrchestratorResult) => void–Called once per finished run, after the summary has landed, with { summary, tokens, cost, wallMs, sequentialMs, speedup, lanes }. Each lane reports its subtask, worker, status, text, tokens, cost and time.
classNamestring–Class on the root element.

simulateOrchestration

The default run hook, exported so you can read the event order it produces or wrap it. It plans four subtasks, dispatches them up to the live concurrency limit, runs each lane through scripted tool calls with token usage, fails one fetch with a 503 and retries it after two seconds, then streams the lead's summary. Prices for Claude models are list prices; the others are illustrative sample values.

PropTypeDefaultDescription
contextOrchestratorRunContext–{ goal, plan, workers, concurrency, signal }, as passed by the component.

Keyboard interactions

KeysAction
TabMoves through the concurrency control, the Run or Stop button, each lane, and the copy summary button once a run is done. An open transcript has no controls of its own.
Arrow left / Arrow rightOn the concurrency control, picks a lower or higher limit. Home and End pick 1 and the maximum.
Enter, SpaceOn a lane, opens or closes its transcript. On Run, starts a run; while running the same button stops it; afterwards it runs again.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components