Dynamic Workflows: Orchestrate Subagents at Scale
A workflow is a graph of agents connected by data flow: agent-A produces output, agent-B consumes it, agent-C fans out to 5 subagents in parallel. Claude Code SDK lets you define workflows as Python/TypeScript scripts that spawn subagents, route data, handle errors, and validate outputs.
This guide shows the workflow lifecycle: plan → fan-out → collect → validate → merge. We'll trace a real audit workflow: one parent agent dispatches 10 subagents to audit different packages in a monorepo, collects their reports, validates coverage, and synthesizes a final report. The key challenge: subagent failures. If 1 of 10 audits fails, do you retry, skip, or halt the whole workflow? We'll show the recovery patterns.
Script-Driven Multi-Agent Orchestration
A workflow script is your agent's script—the one that spawns subagents. Instead of one agent doing everything, you break it into tasks, assign each to a subagent, and orchestrate the flow.
The pattern: parent agent reads a job (e.g., 'audit the monorepo'), spawns subagents ('audit package/ui', 'audit package/api', ...), waits for results, and synthesizes output. Each subagent runs independently (possibly in parallel) with its own context, worktree, and tools.
Quick reference
- Parent agent: orchestrator, dispatcher, result aggregator.
- Subagent: worker, completes one task, returns structured result.
- Spawn syntax:
claude.spawn_agent(name, input, worktree, timeout). - Wait for completion: blocking or async (depends on SDK).
- Collect results: aggregate into a list/dict keyed by subagent ID.
Remember this
Script-driven orchestration: spawn subagents (serial or parallel), collect results, synthesize output.
Fan-Out and Sequential Patterns
Fan-out: dispatch N subagents in parallel (all start at once). Sequential: dispatch one, wait for it, then dispatch the next. Most workflows are mixed: fan-out for independent work, sequential for dependencies.
Fan-out is faster but requires more resources (N concurrent agents, N worktrees). Sequential is slower but simpler. Choose based on dependency graph: if task-B depends on task-A's output, they must be sequential. If independent, fan them out.
The failure mode: one subagent fails. In fan-out, do you wait for all or cancel the rest? In sequential, do you retry or abort? We'll cover recovery below.
Quick reference
- Fan-out: spawn all subagents, store futures/promises, wait for all.
- Sequential: spawn one, wait, spawn next (blocking).
- Hybrid: spawn first batch (fan-out), wait, spawn second batch (fan-out), etc.
- Timeout per subagent: if exceeds timeout, cancel and mark as failed.
- Cancellation: send SIGTERM to subagent; cleanup resources.
Remember this
Fan-out for parallel, sequential for dependencies. Choose based on task graph. Mix both for efficiency.
Workflow State and Context Passing
Each subagent needs context from the parent: which package to audit, the repo state, any config. You pass this as the input string or a context dict. Subagents don't share memory; they only see what you explicitly pass.
After a subagent finishes, its output becomes input for downstream tasks. Example: subagent-A analyzes test coverage, returns a coverage report. Subagent-B takes that report as input, flags low-coverage modules, and suggests improvements.
The pattern: define a state object (dict or JSON) that flows through the workflow. At each step, one agent reads state, updates it, and passes to the next.
Quick reference
- Pass context in input string: 'Audit package/ui with these constraints: ...'
- Structured context: JSON dict with config, constraints, previous results.
- Subagent reads context, performs task, returns new state.
- Parent merges subagent output into state.
- Downstream subagents see accumulated state.
Remember this
State flows: parent → subagent (input), subagent → parent (output), downstream (next input).
Error Handling and Retries
Subagents can fail: timeout, tool error, out of memory, or Claude returns an error. Your workflow must decide: retry, skip, or abort.
Best practice: exponential backoff (retry with delay). Retry up to 3 times; if still failing, mark as failed and continue (unless critical). For critical tasks, abort the entire workflow.
The challenge: detecting failure. A subagent might return valid JSON but with an 'error' field instead of real data. You need output validation (covered in the next section).
Quick reference
- Catch subagent exceptions: timeout, process exit, exception.
- Retry logic: attempt 1, wait 2s, attempt 2, wait 4s, attempt 3.
- Mark as failed if retries exhausted.
- For critical tasks: abort workflow and alert.
- For optional tasks: skip and log.
Remember this
Retry with exponential backoff. Catch exceptions. Mark failures and continue. Validate outputs.
Output Contracts and Validation
A subagent should return structured output (JSON). Before you use the output downstream, validate it matches the contract. Contract: field names, types, required vs optional fields.
Example contract: audit result must have {coverage: float 0-100, issues: list<string>, status: 'pass'|'fail'}. If a subagent returns {coverage: 'unknown'} (string instead of float), validation fails. You can then retry or use a fallback.
Validation prevents garbage data from propagating. It's cheap (just schema check) and catches bugs early.
Quick reference
- Define output schema (JSON Schema or Pydantic model).
- After subagent.wait(), validate result against schema.
- If invalid: log, use fallback, or retry.
- Schema version: if subagent API evolves, update schema and backward compatibility.
- Strict vs lenient: strict fails on any mismatch; lenient fills defaults.
Remember this
Define output schema. Validate each subagent result. Use fallback if invalid. Prevents garbage data.
Real Example: Codebase Audit with Parallel Tasks
A monorepo with 8 packages (ui, api, core, auth, db, mobile, web, docs). You want a complete audit: test coverage, security scan, performance analysis, documentation check. Normally, this takes hours. With parallel subagents, it takes 15 minutes.
Workflow: parent agent dispatches 8 subagents (one per package) in parallel. Each runs a suite of checks. After all complete, parent synthesizes a report: which packages pass, which need work, overall score.
If an audit fails (e.g., api package timeout), parent retries once. If it still fails, marks it as incomplete and includes a note in the final report.
Quick reference
- Parent: orchestrator; reads job 'audit monorepo'.
- Subagent: auditor; given package name and checklist.
- Checklist: tests (pass/fail), coverage (%), security (issues), docs (complete %).
- Fan-out: dispatch 8 subagents in parallel.
- Collect: wait for all; validate each output.
- Synthesize: aggregate results; compute overall score.
Remember this
Parallel subagents reduce time. Structured results + validation = reliable reports.
Debugging Workflows
When a workflow fails, you need to know why. Logs help: what was each subagent's input? what output did it produce? what validation errors occurred? The debugging pattern: save workflow state at each step, re-run from a checkpoint, or debug individual subagents in isolation.
Best practice: detailed logging. For each subagent spawn, log the input, timeout, and worktree. For each result, log the output and validation status. When something fails, you can replay from the logs and pinpoint the issue.
Quick reference
- Log subagent spawning: name, input, worktree, timeout.
- Log subagent result: raw output, validation status, error if any.
- Checkpoint state after each stage (e.g., after all fan-out completes).
- Replay from checkpoint: load state, continue from next stage.
- Isolated debug: spawn a single subagent with a known input, check output.
Remember this
Log every subagent spawn and result. Checkpoint after stages. Replay from checkpoint to debug.
Key takeaway
Dynamic workflows orchestrate teams of agents. Spawn subagents, route data, validate outputs, and recover from failures. For managing hundreds of concurrent agents, read Agent View. For deeper agent SDK patterns, see Agent SDK Quickstart. For large-scale monorepo orchestration, see Monorepo Setup.
Polo Khan
Lead Author & Systems ArchitectSoftware engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.
Related Articles
Explore this topic