Claude Code Dynamic Workflows: Orchestrate 1,000 Agents

It is a JavaScript script that orchestrates subagents at scale. Claude writes the script for the task you describe, and a runtime executes it in the background while your session stays responsive. The loop, the branching and all intermediate results live in script variables, so Claude's context window only ever holds the final answer.
Use a workflow when the same step has to run across many items, or when the task is larger than one agent can hold in context — a codebase-wide audit, a 500-file migration, research that needs sources cross-checked. Subagents and agent teams keep Claude as the orchestrator, so their intermediate results compete with the work for the same context window.
Up to 1,000 agents total per run, with a maximum of 16 running concurrently — fewer when Claude Code detects fewer CPUs, including inside a CPU-limited container. Passing hundreds of items still completes; only about a dozen execute at any one moment while the rest queue.
Completed agents usually return cached results on resume, but replay follows the order agents started, and caching stops at the first agent that did not finish. Any agent that started after that one runs again even if it completed. This is why fanning work across many small agents preserves far more progress than a few long ones.
No. The keyword is an opt-in only in a prompt you type yourself — the interactive prompt, an IDE panel, or a Remote Control client. It deliberately does not trigger from a prompt passed with -p, a scheduled task, or a webhook payload or PR comment relayed into the conversation. Before v2.1.210 it did fire from those routes.

Key Takeaway
A Claude Code dynamic workflow is a JavaScript script that orchestrates subagents in the background while your session stays responsive. Claude writes the script, the runtime executes it, and intermediate results live in script variables instead of a context window. One run can spawn up to 1,000 agents, with 16 running concurrently.
The first time I asked Claude to audit every route handler in a project for missing auth checks, it did what a conversation does: read a file, report, read the next, report. Forty files in, the early findings had been compacted away and the summary at the end was a summary of the last eight files. The orchestration was competing with the work for the same context window.
A workflow removes that competition by moving the plan into code. This post covers when a workflow beats the three other ways to parallelise, the script API you will actually read, the pipeline-versus-barrier decision that determines wall-clock time, the runtime caps that shape what you can write, and the resume rule that makes stopping a run mid fan-out much more expensive than it looks.
Subagents, skills, agent teams and workflows can all run a multi-step task. The question that separates them is who decides what runs next, and where the intermediate results land. With the first three, Claude is the orchestrator: it decides turn by turn what to spawn, and every result comes back into a context window. A workflow script holds the loop, the branching and the intermediate results itself, so Claude's context holds only the final answer.
The distinction that actually decides which one you want:
| Dimension | Subagents | Agent teams | Workflows |
|---|---|---|---|
| Who decides what runs next | Claude, turn by turn | The lead agent, turn by turn | The script |
| Where intermediate results live | Claude's context window | A shared task list | Script variables |
| Scale | A few delegated tasks per turn | A handful of long-running peers | Dozens to hundreds of agents per run |
| What is repeatable | The worker definition | The team definition | The orchestration itself |
The quickest way to see the shape is the one bundled workflow. Running deep research fans web searches across several angles, cross-checks the sources against each other, votes on each claim, and returns a cited report with the claims that failed cross-checking already filtered out. Claims the verifiers could not check — after a rate limit, say — are listed as unverified rather than counted as refuted, which is the distinction most research tooling gets wrong.
# Run the one bundled workflow to see the shape first.
/deep-research What changed in the Node permission model in v22?
# Ask for a workflow on your own task. The keyword only works in
# a prompt you type yourself — not from -p, not from a scheduled
# task, and not from a webhook or PR comment relayed into the run.
ultracode: audit every endpoint under src/routes/ for missing auth
# Or let Claude decide for every substantive task this session.
# ultracode = xhigh effort + automatic workflow orchestration.
/effort ultracode
# Watch it. The progress view shows per-phase agent counts,
# token totals and elapsed time.
/workflows
# f filter agents in the phase by status
# p pause or resume the run
# x stop the selected agent, or the whole run
# r restart the selected running agent
# s save this run's script as a reusable /commandThe ultracode keyword is an opt-in only in a prompt you type yourself, at the interactive prompt, in an IDE panel or in a Remote Control client. It deliberately does not start a workflow from a prompt passed with the -p flag, a scheduled task, or a webhook payload or pull request comment relayed into the conversation. Before v2.1.210 it did fire from those routes, which meant a comment on a PR could trigger a hundred-agent run.
Every script opens with a meta block that must be a pure literal — no variables, no template interpolation, no function calls — followed by plain JavaScript with top-level await. The body has five hooks: agent to spawn one subagent, parallel and pipeline to fan out, phase to group progress, and log to narrate. That is nearly all of it.
// .claude/workflows/audit-routes.js — plain JavaScript with
// top-level await. No imports: a script containing import()
// fails before the run even starts.
export const meta = {
name: 'audit-routes',
description: 'Audit every route handler for missing auth checks',
phases: [
{ title: 'Discover' },
{ title: 'Audit' },
{ title: 'Verify' },
],
}
phase('Discover')
const found = await agent('List every .ts file under src/routes/.', {
schema: {
type: 'object',
required: ['files'],
properties: { files: { type: 'array', items: { type: 'string' } } },
},
})
// pipeline() runs each item through EVERY stage independently.
// File A can be in Verify while file B is still in Audit.
const audits = await pipeline(
found.files,
file => agent('Audit ' + file + ' for missing auth checks.', {
label: file, phase: 'Audit', schema: FINDINGS,
}),
review => agent('Adversarially refute: ' + review.claim, {
phase: 'Verify', schema: VERDICT,
}),
)
// An agent you stop, or one that dies on a terminal API error,
// resolves to null — pipeline keeps the null in the array.
return audits.filter(Boolean)This is the decision that decides wall-clock time, and it is the one most hand-written scripts get wrong. A call to parallel is a barrier: it waits for every task before returning anything. A pipeline runs each item through all its stages independently, so item A can be in stage three while item B is still in stage one. Wall-clock time for a pipeline is the slowest single-item chain, not the sum of the slowest item at each stage.
The test I apply: if I wrote a barrier, collected the results, then immediately mapped or flattened or filtered them without any cross-item comparison, the barrier was not needed and the transform belongs inside a pipeline stage. A barrier is genuinely right in only three cases:
Agents in the same run can read each other's prompt cache when they share a model, effort level, agent type, tool set, output schema and working directory. When a fan-out starts several matching agents at once, the runtime holds all but the first until the first response begins, so the rest read the shared prefix instead of each processing it uncached. The hold is capped by an environment variable at five seconds by default.
The runtime is deliberately constrained, and each constraint changes how you structure a script rather than merely limiting it:
You can stop a run and resume it, and agents that already finished usually return cached results. Two rules decide what survives, and the second one is counter-intuitive enough to be worth a diagram.
# Why stopping mid fan-out is expensive.
#
# A script starts four agents in this order: A, B, C, D.
# You stop the run while B is still going.
#
# On resume:
# A -> returns from cache (finished, started before B)
# B -> runs again (never finished)
# C -> runs again (started AFTER B)
# D -> runs again (started AFTER B)
#
# Replay follows START ORDER, and cached results stop at the
# first agent that did not finish. C and D completed and are
# still discarded. Many small agents therefore preserve far
# more progress than one long one.This is the strongest argument for fanning work across many small agents rather than a few long ones: a workflow of forty short agents loses a handful of results when you stop it, while a workflow of four long ones can lose almost everything. Resume also only works within the same Claude Code session — exit the CLI while a workflow is running and the next session starts it fresh.
A workflow spawns many agents, so one run can use meaningfully more tokens than working the same task through conversation. The size guideline in config tells Claude how many agents to aim for when it writes a script: small is under five, medium under fifteen, large under fifty, unrestricted lets Claude size it to the task. The default is medium. It is advice sent to the model rather than a cap, so a prompt that genuinely calls for a different scale still overrides it.
Your permission mode controls only the launch prompt. The subagents a workflow spawns always run in accept-edits mode and inherit your tool allowlist, whatever mode the session is in — file edits are auto-approved. Shell commands, web fetches and MCP tools outside your allowlist can still stop a long run mid-flight to ask you, so add what the agents will need before you start.
Gauge the spend on a slice first: one directory instead of the whole repo, one narrow question instead of a broad one. Claude Code flags a run that schedules more than 25 agents or projects past 1.5 million tokens with a large-workflow warning in the task panel, but the warning is advisory — it does not pause anything. The workflows view shows per-agent token usage as the run progresses, and you can stop there usually without losing completed work.
The rule I settled on is that a workflow earns its keep when the same step runs across many items, or when the task is larger than one agent can hold. Below that line, conversation is cheaper and easier to steer. Above it, the real win is not the extra agents — it is that the orchestration becomes a file you can read, diff against the last run, edit, and rerun on a branch six weeks later and get the same shape of answer.
Sources & further reading