Skip to content
Skip to main content
A developer watching a branching tree of parallel Claude Code subagents run in the background on a monitor
9 min readBy Carlos Aragon

Claude Code Dynamic Workflows: How I Actually Run Dozens of Subagents

A Claude Code dynamic workflow is a JavaScript script Claude writes to orchestrate subagents at scale, and a runtime runs it in the background while your session stays free. The whole trick is that it moves the plan out of the model's context window and into code— so dozens of agents can work without any of their chatter crowding your conversation. Here are the three primitives, the one rule that decides how fast a run finishes, the caps that stop a runaway, and what it actually costs — from runs I've shipped.

What a Dynamic Workflow Actually Is

Landed alongside Opus 4.8 on May 28, 2026, dynamic workflows fix a specific problem: some jobs are too big for one agent to hold in its head. A repo-wide bug sweep, a migration that touches four hundred files, a research question that only means something once you've cross-checked a dozen sources — try any of those in a single conversation and Claude's context fills with intermediate junk long before it reaches an answer.

A workflow moves the plan into a script. You describe the task, Claude writes a short JavaScript program that spawns subagents, and a runtime executes it in the background. The loop, the branching, and every intermediate result live in script variables — not in Claude's context. Your main conversation only ever receives the final, reduced answer. That's the difference from plain subagents, where Claude orchestrates turn by turn and every worker's output lands back in the context window.

The mental model:

Subagents put Claude in charge of the plan and pay for it in context. A workflow puts a script in charge of the plan, so context stays clean and the orchestration becomes something you can read, rerun, and save.

It needs Claude Code v2.1.154 or later and runs on any paid plan. You don't write the script yourself — you ask for it. Say “use a workflow to…” in plain English, or drop the keyword ultracode in your prompt, and Claude drafts one and shows you the phases before anything runs.

The Three Primitives: agent, parallel, pipeline

Every workflow is built from three building blocks. Once you understand them, you can read any script Claude writes and know exactly what it'll do:

  • agent(prompt) — spawns one subagent and returns its result. The atom of the whole system. Hand it a JSON schema and you get back structured data instead of prose.
  • parallel(tasks) — a synchronization barrier. It launches a batch of agents and waits for all of them before returning. Use it when the next step needs every result at once.
  • pipeline(items, ...stages) — streams each item through the stages with no barrier between them. Item A can be in stage three while item B is still in stage one.

Here's the shape of a small one — a fan-out that lists every route file, then audits each in its own agent:

const found = await agent(
  "List every .ts file under src/routes/.",
  { schema: { /* files: string[] */ } },
)

// one auditor per file, streamed — not batched
const audits = await pipeline(found.files, (file) =>
  agent(`Audit ${file} for missing auth checks.`,
        { label: file }),
)

return audits.filter(Boolean)

That's plain JavaScript with top-level await. The runtime can't touch your filesystem or shell directly — the agents read, write, and run commands; the script just coordinates them.

The One Rule: Default to pipeline(), Not parallel()

This is the mistake I see most, and it's the one that quietly wastes the most wall-clock time. parallel() waits for the slowest agent in the batch before anything moves to the next stage. If you have ten reviewers and one of them takes three times as long as the rest, the other nine sit idle at the barrier doing nothing.

pipeline() has no barrier. Each item flows through the stages on its own, so the run finishes as fast as its slowest single chain— not the sum of the slowest agent in every stage. On a review-then-verify workflow over a couple dozen files, that's the difference between a run that feels snappy and one that feels stuck.

When a barrier is actually right:

Use parallel() only when the next stage genuinely needs the whole set at once — deduplicating findings across every file before you verify them, or an early exit like “zero bugs found, skip verification entirely.” If you're only reaching for it to flatten a list or map over results, that's not a reason. Do the transform inside a pipeline stage and keep streaming.

The pattern that generalizes across almost everything I build is fan out → reduce → synthesize: spawn many agents, each looking at one slice; collect their findings into one list; hand that list to a final agent that ranks, dedupes, and writes the summary. Moving the plan into code also lets you bolt on a quality step a single pass can't — I have workflows where independent agents adversarially review each other's findings before anything gets reported, which kills the plausible-but-wrong results that a lone agent would have handed me with confidence.

A developer relaxing with coffee while a Claude Code workflow fans several subagent tasks out in the background on a laptop
The whole point of a workflow: agents fan out in the background while your session — and you — stay free.

The Caps That Stop a Runaway — and What This Costs

Handing a script the power to spawn hundreds of agents should make you nervous about the bill. It made me nervous. The good news is the guardrails are built into the runtime, not left to you to remember:

  • 16 concurrent agents max at any moment — fewer on machines with limited CPU cores. Pass 500 items to pipeline() and they all complete, but only 16 run at once and the rest queue.
  • 1,000 agents total per run, a hard lifetime cap that exists purely to stop a runaway loop from spawning forever.
  • A large-workflow warning fires when a run is projected past 25 agents or 1.5 million tokens, pointing you to /workflows where you can stop it without losing completed work.
  • A size guideline in /config nudges the scripts Claude writes toward small (under 5 agents), medium (under 15), or large (under 50).

None of that changes the basic truth: a workflow spawns many agents, so one run burns meaningfully more tokens than doing the same task in conversation. Every agent counts toward your plan's usage and rate limits. My rule is to run any new workflow on a slice first — one directory, not the whole repo; one narrow question, not the broad one — read the token totals in the /workflows view, and only then point it at the full job. That's the same instinct behind the hard budgets I put on every autonomous loop, which I broke down in running AI agents on autopilot without torching your budget. And because a workflow's agents each use your session model, switching to a smaller model before a big fan-out — or asking Claude to route cheap stages down a tier — is the fastest lever on cost, the same context-tax thinking I used when measuring what MCP servers actually cost you in tokens.

When a Workflow Beats a Subagent (and When It Doesn't)

Subagents, skills, agent teams, and workflows can all run a multi-step task. The real question is who holds the plan. With subagents and agent teams, Claude decides turn by turn what to run next and everything lands in a context window — great for a handful of delegated tasks, painful past a certain scale. A workflow puts the plan in a script, which buys you three things a turn-by-turn approach can't: dozens-to-hundreds of agents without context bloat, a repeatable orchestration you can save and rerun, and the ability to codify a quality pattern like adversarial cross-checking.

So I reach for a workflow when the task is bigger than one agent can hold, or when the same step has to run across many items: audit every route for missing auth, migrate every component off a dead library (each in its own isolated copy so edits don't collide), keep fixing type errors until tsc passes or two rounds make no progress, or fan readers across changelogs and docs and synthesize. The bundled /deep-research command is a workflow you can watch to see the shape in action.

I don't reach for one on a task a single agent handles fine — a targeted edit, a quick question, a one-file fix. The overhead of spinning up an orchestration isn't free, and the token cost is real. Workflows earn their keep on breadth and repetition, not on speed for small jobs. If you're still weighing whether to build against the raw API or lean on Claude Code's agent tooling for this kind of thing, I laid out the trade-offs in Claude Agent SDK vs raw Anthropic API. For the official reference, Anthropic's dynamic workflows docs document every primitive and limit.

The Payoff: Save a Good Run as a Command

The part that actually changed my week: once a workflow does what I wanted, I press s in the /workflows view and save its script to .claude/workflows/. It becomes a /command I can rerun on every branch, and it accepts input through an argsparameter — so my “review every changed file and merge the findings into one ranked summary” run is now a one-liner I fire before every PR, and my per-file audit takes a list of paths without me editing the script.

That's the shift. A workflow isn't just “more agents” — it's orchestration you write once, read like code, and run forever. The first time you watch nine agents fan out across a codebase in the background while you keep working in the same session, the turn-by-turn way of delegating starts to feel like doing it by hand.

The Short Version

  • A dynamic workflow is a script Claude writes that orchestrates subagents in the background — the plan lives in code, not in Claude's context window.
  • Three primitives: agent() spawns one, parallel() batches and waits, pipeline() streams items through stages with no barrier.
  • Default to pipeline(). parallel() makes every stage wait for its slowest agent — only worth it when a stage needs the whole result set at once.
  • fan out → reduce → synthesize is the pattern; add adversarial cross-checking to kill plausible-but-wrong findings.
  • Caps stop runaways: 16 agents concurrent, 1,000 per run, a warning past 25 agents or 1.5M tokens.
  • It costs more than a plain session. Run a slice first, watch the token totals, drop to a smaller model for a big fan-out.
  • Save a good run with 's' — it becomes a reusable /command that takes args.

Want Multi-Agent Automation That Actually Ships?

I build production AI systems that orchestrate agents at scale — codebase audits, migrations, research pipelines, and autonomous loops with real cost controls wired in from the start, on Claude, the Anthropic API, n8n, and Supabase. If you want fan-out that finishes the job instead of burning the budget, let's talk.

Related Posts