A dynamic workflow is a JavaScript script that orchestrates subagents at scale. You describe a task, Claude writes the script, and a runtime executes it in the background — spawning dozens to hundreds of agents — while your session stays responsive. The script holds the loop, the branching, and the intermediate results, so only the final answer reaches Claude's context window.
Reach for one when a task needs more agents than a single conversation can coordinate, or when you want the orchestration codified as a script you can read and rerun: a codebase-wide bug sweep, a 500-file migration, or research that cross-checks its own sources. Below are 24 ready-to-run scripts you can copy, plus the full trigger, API, and runtime reference.
Subagents, skills, agent teams, and workflows can all run a multi-step task. The difference is who holds the plan — and a workflow moves it into code.
Subagents
Skills
Agent teams
Workflows
What it is
A worker Claude spawns
Instructions Claude follows
A lead supervising peers
A script the runtime executes
Who decides what runs next
Claude, turn by turn
Claude, per the prompt
The lead agent, turn by turn
The script
Where results live
Claude's context
Claude's context
A shared task list
Script variables
What's repeatable
The worker definition
The instructions
The team definition
The orchestration itself
Scale
A few per turn
Same as subagents
A handful of peers
Dozens to hundreds per run
Interruption
Restarts the turn
Restarts the turn
Teammates keep running
Resumable in the session
A workflow can also apply a repeatable quality pattern — independent agents adversarially reviewing each other's findings, or a plan drafted from several angles and weighed against each other — for a more trustworthy result than a single pass.
How to trigger a workflow
The ultracode keyword
Put the keyword ultracode in any prompt to run that single task as a workflow without changing the session effort level. Asking in your own words ("use a workflow") works too.
Ultracode effort mode
Set /effort ultracode to combine xhigh reasoning with automatic workflow orchestration — Claude then plans a workflow for every substantial task. Lasts the session; drop back with /effort high.
Bundled /deep-research
The built-in workflow: fans out web searches, cross-checks sources, votes on each claim, and returns a cited report with unsupported claims filtered out. Needs the WebSearch tool.
Saved workflows
After a run does what you want, open /workflows, select it, and press s to save its script as a command. It then runs as /<name> in future sessions and accepts input via args.
Repeatedly fan out finders across the repo, dedupe against everything seen, then have independent skeptics try to refute each bug before it is reported.
When: You suspect latent bugs but have no single entry point. Keeps spawning finders until two consecutive rounds turn up nothing new.
One agent per OWASP-style dimension reviews the codebase; each finding is verified by a focused skeptic as soon as its review lands — no barrier between stages.
When: Pre-release hardening or a periodic security review across an entire service or repo.
Scout every route handler first, then check each one for an authorization guard in parallel. The official docs use this exact shape as the canonical ultracode example.
When: Confirming every endpoint under a routes directory enforces auth before a release.
Plan a rename (including docs, tests, and config), then apply it file-by-file in isolated worktrees, skipping unrelated same-named symbols.
When: Renaming a widely-used symbol when a naive find-and-replace would clobber unrelated matches.
What you type
#rename#refactor#pipeline#worktree
export const meta = {
name: 'rename-symbol',
description: 'Plan and apply a project-wide rename without clobbering unrelated matches',
phases: [{ title: 'Plan' }, { title: 'Apply' }],
}
const from = (args && args.from) || 'Account'
const to = (args && args.to) || 'Workspace'
const PLAN = { type: 'object', properties: { files: { type: 'array',
items: { type: 'string' } } }, required: ['files'] }
const APPLY = { type: 'object', properties: { applied: { type: 'boolean' },
skipped: { type: 'number' } }, required: ['applied'] }
phase('Plan')
const { files } = await agent(`List every file that references the symbol "${from}" (code, tests, docs, config). Exclude unrelated same-named identifiers.`,
{ schema: PLAN })
log(`renaming "${from}" -> "${to}" across ${files.length} files`)
const applied = await parallel(files.map((f) => () =>
agent(`In ${f}, rename "${from}" to "${to}" — only where it refers to the intended symbol. Skip unrelated matches and report how many you skipped.`,
{ label: `apply:${f}`, phase: 'Apply', isolation: 'worktree', schema: APPLY })
.then((r) => ({ file: f, ...r }))))
return applied.filter(Boolean)
Cross-checked deep research
Research & Planning Fan-out → cross-check → synthesize
Search a question from several angles, fetch and read the sources, vote on each claim, and synthesize a report with unsupported claims filtered out. This is the shape behind the bundled /deep-research.
When: Any research question where a single search pass is not trustworthy enough and sources must be checked against each other.
Draft a plan from several independent angles, score each with parallel judges, then synthesize a final plan from the winner while grafting the best ideas from the runners-up.
When: A hard design decision worth more than one pass before you commit — architecture, a rollout, a tricky refactor.
What you type
#planning#judge-panel#design#parallel
export const meta = {
name: 'plan-panel',
description: 'Draft a plan from competing angles, judge them, synthesize the winner',
phases: [{ title: 'Draft' }, { title: 'Judge' }, { title: 'Synthesize' }],
}
const goal = (args && args.goal) || 'YOUR PLANNING GOAL HERE'
const ANGLES = ['MVP-first / smallest shippable slice', 'risk-first / de-risk the hardest part early',
'user-first / fastest visible value']
const SCORE = { type: 'object', properties: { score: { type: 'number' },
strengths: { type: 'string' }, risks: { type: 'string' } }, required: ['score'] }
phase('Draft')
const drafts = await parallel(ANGLES.map((angle) => () =>
agent(`Draft a concrete plan for: ${goal}. Take the "${angle}" angle. Include steps, risks, and a rollback.`,
{ label: `draft:${angle.split('/')[0].trim()}`, phase: 'Draft' })
.then((plan) => ({ angle, plan }))))
const judged = await parallel(drafts.filter(Boolean).map((d) => () =>
agent(`Score this plan 0-10 for ${goal}. Note strengths and risks.\n\n${d.plan}`,
{ label: 'judge', phase: 'Judge', schema: SCORE })
.then((s) => ({ ...d, ...s }))))
const ranked = judged.filter(Boolean).sort((a, b) => (b.score || 0) - (a.score || 0))
phase('Synthesize')
return await agent(`Write the final plan for "${goal}". Base it on the top plan below, grafting the best ideas from the others.\n\nTOP:\n${ranked[0].plan}\n\nOTHERS:\n${ranked.slice(1).map((r) => r.plan).join('\n---\n')}`)
Codebase understanding map
Research & Planning Parallel readers → synthesis
Point one reader at each subsystem to summarize its responsibilities and key files, then merge the summaries into a single architecture map.
When: Onboarding to an unfamiliar repo, or producing an up-to-date architecture overview on demand.
What you type
#understand#architecture#parallel#onboarding
export const meta = {
name: 'codebase-map',
description: 'Summarize each subsystem in parallel, then synthesize an architecture map',
phases: [{ title: 'Identify' }, { title: 'Read' }, { title: 'Synthesize' }],
}
const SUBSYSTEMS = { type: 'object', properties: { subsystems: { type: 'array', items: {
type: 'object', properties: { name: { type: 'string' }, dir: { type: 'string' } },
required: ['name', 'dir'] } } }, required: ['subsystems'] }
const SUMMARY = { type: 'object', properties: { responsibility: { type: 'string' },
keyFiles: { type: 'array', items: { type: 'string' } }, dependsOn: { type: 'array', items: { type: 'string' } } },
required: ['responsibility'] }
phase('Identify')
const { subsystems } = await agent('Identify the top-level subsystems of this repo (name + directory).',
{ schema: SUBSYSTEMS })
const summaries = await parallel(subsystems.map((s) => () =>
agent(`Read ${s.dir}. Summarize ${s.name}'s responsibility, its key files, and which other subsystems it depends on.`,
{ label: `read:${s.name}`, phase: 'Read', schema: SUMMARY })
.then((r) => ({ name: s.name, dir: s.dir, ...r }))))
phase('Synthesize')
return await agent(`Write an architecture map of this codebase from these subsystem summaries. Include a dependency overview.\n\n${
JSON.stringify(summaries.filter(Boolean), null, 2)}`)
Incident root-cause analysis
Research & Planning Multi-modal sweep → synthesis
Investigate an incident from several blind angles at once — recent diffs, error logs, config changes, dependency bumps — then synthesize the most likely root cause.
When: A regression appeared and you want parallel lines of inquiry instead of one serial hunt.
What you type
#debugging#rca#multi-modal#parallel
export const meta = {
name: 'incident-rca',
description: 'Investigate an incident from multiple angles and synthesize a root cause',
phases: [{ title: 'Investigate' }, { title: 'Synthesize' }],
}
const incident = (args && args.incident) || 'the regression under investigation'
const ANGLES = [
`Review recent diffs touching code paths related to: ${incident}. What changed?`,
`Look for error/exception patterns and stack traces relevant to: ${incident}.`,
`Check recent config, env, and feature-flag changes that could cause: ${incident}.`,
`Check recent dependency and version bumps that could cause: ${incident}.`,
]
const LEAD = { type: 'object', properties: { lead: { type: 'string' },
confidence: { enum: ['low', 'medium', 'high'] }, evidence: { type: 'string' } },
required: ['lead', 'confidence'] }
phase('Investigate')
const leads = await parallel(ANGLES.map((p, i) => () =>
agent(p, { label: `angle-${i + 1}`, phase: 'Investigate', schema: LEAD })))
phase('Synthesize')
return await agent(`Given these independent leads, what is the single most likely root cause of "${incident}"? Rank the leads and propose the next verification step.\n\n${
JSON.stringify(leads.filter(Boolean), null, 2)}`)
Review the diff across dimensions (correctness, security, performance, tests), then have each finding adversarially verified before it is surfaced — the canonical review pattern.
When: A review you run on every branch. Save it and it runs the same orchestration each time.
What you type
#code-review#diff#pipeline#verify
export const meta = {
name: 'pr-review',
description: 'Review the diff across dimensions and adversarially verify each finding',
phases: [{ title: 'Review' }, { title: 'Verify' }],
}
const DIMENSIONS = [
{ key: 'correctness', prompt: 'Find correctness bugs and edge cases the diff misses.' },
{ key: 'security', prompt: 'Find security issues introduced by the diff.' },
{ key: 'perf', prompt: 'Find performance regressions or N+1 patterns in the diff.' },
{ key: 'tests', prompt: 'Find behavior changed by the diff that has no test coverage.' },
]
const FINDINGS = { type: 'object', properties: { findings: { type: 'array', items: {
type: 'object', properties: { title: { type: 'string' }, file: { type: 'string' },
line: { type: 'number' } }, required: ['title', 'file'] } } }, required: ['findings'] }
const VERDICT = { type: 'object', properties: { isReal: { type: 'boolean' },
severity: { enum: ['nit', 'minor', 'major'] } }, required: ['isReal'] }
const results = await pipeline(
DIMENSIONS,
(d) => agent(`Review the current git diff. ${d.prompt} Report title, file, line.`,
{ label: `review:${d.key}`, phase: 'Review', schema: FINDINGS }),
(review) => parallel((review?.findings || []).map((f) => () =>
agent(`Adversarially verify this review finding against the actual diff — is it real? ${f.title} (${f.file}:${f.line ?? '?'})`,
{ label: `verify:${f.file}`, phase: 'Verify', schema: VERDICT })
.then((v) => ({ ...f, ...v }))))
)
return results.flat().filter(Boolean).filter((f) => f.isReal)
Test-coverage gap finder
Review & QA Per-module fan-out
For each module, identify behaviors with no test, rank by blast radius, and propose the specific test cases that would close each gap.
When: Deciding where to invest test effort, or hardening a module before a risky change.
Find public functions lacking documentation and write accurate doc comments for each in an isolated worktree so parallel writes never conflict.
When: Bringing an under-documented public API up to standard in one pass.
What you type
#docs#jsdoc#parallel#worktree
export const meta = {
name: 'docstring-backfill',
description: 'Write doc comments for every undocumented public function',
phases: [{ title: 'Find' }, { title: 'Document' }],
}
const TARGETS = { type: 'object', properties: { files: { type: 'array', items: { type: 'string' } } },
required: ['files'] }
const DONE = { type: 'object', properties: { documented: { type: 'number' } }, required: ['documented'] }
phase('Find')
const { files } = await agent('List files that export public functions missing doc comments.', { schema: TARGETS })
log(`${files.length} files to document`)
const done = await parallel(files.map((f) => () =>
agent(`In ${f}, add accurate doc comments to every exported function missing one. Describe params, return, and thrown errors. Do not change behavior.`,
{ label: `doc:${f}`, phase: 'Document', isolation: 'worktree', schema: DONE })
.then((d) => ({ file: f, ...d }))))
return done.filter(Boolean)
Test generation for a module
Generate & Document Plan cases → write → verify
Enumerate the test cases a module needs, write each as a test, then run the suite to confirm the new tests pass and actually exercise the code.
When: Backfilling tests for a critical module before you refactor it.
What you type
#tests#generation#pipeline
export const meta = {
name: 'test-generation',
description: 'Plan, write, and verify a test suite for a module',
phases: [{ title: 'Plan cases' }, { title: 'Write' }, { title: 'Verify' }],
}
const target = (args && args.dir) || 'src/billing/'
const CASES = { type: 'object', properties: { cases: { type: 'array', items: {
type: 'object', properties: { name: { type: 'string' }, behavior: { type: 'string' } },
required: ['name', 'behavior'] } } }, required: ['cases'] }
const WRITTEN = { type: 'object', properties: { written: { type: 'boolean' }, testFile: { type: 'string' } },
required: ['written'] }
const RUN = { type: 'object', properties: { pass: { type: 'boolean' }, failures: { type: 'number' } },
required: ['pass'] }
phase('Plan cases')
const { cases } = await agent(`Enumerate the test cases ${target} needs: happy paths, edge cases, and error paths. Name each.`,
{ schema: CASES })
log(`${cases.length} cases planned`)
const written = await pipeline(
cases,
(c) => agent(`Write a test for "${c.name}": ${c.behavior}. Add it to the appropriate test file for ${target}.`,
{ label: `write:${c.name}`, phase: 'Write', isolation: 'worktree', schema: WRITTEN })
.then((w) => ({ case: c.name, ...w }))
)
phase('Verify')
const run = await agent(`Run the test suite for ${target}. Report pass and failure count.`, { schema: RUN })
return { cases: written.filter(Boolean), suite: run }
Changelog / release notes builder
Generate & Document Per-commit classify → group
Classify each commit since the last release by type and audience impact, drop the noise, and group the rest into human-readable release notes.
When: Turning a messy commit range into clean release notes without hand-curating every line.
What you type
#changelog#release#parallel
export const meta = {
name: 'changelog',
description: 'Classify commits since the last release and group into release notes',
phases: [{ title: 'List commits' }, { title: 'Classify' }, { title: 'Group' }],
}
const COMMITS = { type: 'object', properties: { commits: { type: 'array', items: {
type: 'object', properties: { sha: { type: 'string' }, subject: { type: 'string' } },
required: ['sha', 'subject'] } } }, required: ['commits'] }
const CLASS = { type: 'object', properties: { type: { enum: ['feature', 'fix', 'perf', 'docs', 'internal', 'noise'] },
userFacing: { type: 'string' } }, required: ['type'] }
phase('List commits')
const { commits } = await agent('List the commits since the last release tag (sha + subject).', { schema: COMMITS })
log(`${commits.length} commits`)
const classified = await parallel(commits.map((c) => () =>
agent(`Classify commit "${c.subject}" (type) and, if user-facing, write a one-line note.`,
{ label: `classify:${c.sha.slice(0, 7)}`, phase: 'Classify', schema: CLASS })
.then((k) => ({ ...c, ...k }))))
const keep = classified.filter(Boolean).filter((c) => !['internal', 'noise'].includes(c.type))
phase('Group')
return await agent(`Group these into Markdown release notes under Features / Fixes / Performance / Docs headings:\n${
keep.map((c) => `- (${c.type}) ${c.userFacing || c.subject}`).join('\n')}`)
Onboarding guide generator
Generate & Document Parallel readers → synthesis
Have agents read setup, architecture, conventions, and the dev loop in parallel, then synthesize a single onboarding doc a new engineer can follow start to finish.
When: Producing a "day one" guide for a repo that has none, grounded in what the code actually does.
What you type
#docs#onboarding#parallel#synthesis
export const meta = {
name: 'onboarding-doc',
description: 'Read the repo from several angles and synthesize an onboarding guide',
phases: [{ title: 'Read' }, { title: 'Synthesize' }],
}
const SECTIONS = [
{ key: 'setup', prompt: 'How do you install deps, configure env, and run this project locally? Cite the real files.' },
{ key: 'architecture', prompt: 'What are the main subsystems and how do they fit together?' },
{ key: 'conventions', prompt: 'What code conventions, patterns, and gotchas should a new contributor know?' },
{ key: 'devloop', prompt: 'What is the day-to-day dev loop: build, test, lint, deploy?' },
]
const NOTE = { type: 'object', properties: { content: { type: 'string' } }, required: ['content'] }
const notes = await parallel(SECTIONS.map((s) => () =>
agent(s.prompt, { label: `read:${s.key}`, phase: 'Read', schema: NOTE })
.then((n) => ({ key: s.key, content: n?.content }))))
phase('Synthesize')
return await agent(`Write a single, well-structured ONBOARDING.md from these grounded notes. Keep it practical and ordered for a new engineer's first day.\n\n${
JSON.stringify(notes.filter(Boolean), null, 2)}`)
Keep spawning audit rounds until the token budget you set with a "+Nk" directive is nearly spent — depth scales to what you are willing to pay for.
When: You explicitly want maximum coverage and have set a token target for the turn; the script self-paces to fill it.
What you type
#budget#loop-until-budget#scale
export const meta = {
name: 'budget-scaled-audit',
description: 'Run audit rounds until the turn token budget is nearly spent',
phases: [{ title: 'Audit' }],
}
const ISSUES = { type: 'object', properties: { issues: { type: 'array', items: {
type: 'object', properties: { area: { type: 'string' }, issue: { type: 'string' } },
required: ['area', 'issue'] } } }, required: ['issues'] }
const found = []
const seen = new Set()
// Guard on budget.total: with no "+Nk" target, remaining() is Infinity.
while (budget.total && budget.remaining() > 50_000) {
const round = await agent(
'Audit a slice of this repo for correctness, security, and maintainability issues not already reported. Return new issues only.',
{ phase: 'Audit', schema: ISSUES })
const fresh = (round?.issues || []).filter((i) => !seen.has(i.issue))
if (!fresh.length) { log('no new issues — stopping early'); break }
fresh.forEach((i) => seen.add(i.issue))
found.push(...fresh)
log(`${found.length} issues, ~${Math.round(budget.remaining() / 1000)}k tokens left`)
}
return found
Script API reference
The hooks available inside a workflow script. Default to pipeline() — it runs each item through every stage with no barrier between stages. Reach for parallel() only when a stage genuinely needs all prior results at once.
Run each item through every stage independently — NO barrier between stages. The default for multi-stage work. A throwing stage drops that item to null.
parallel()parallel(thunks) → Promise<any[]>
Run thunks concurrently and await all of them — a barrier. A failing thunk resolves to null, so filter(Boolean) before use. Reach for it only when you need all results together.
phase()phase(title)
Start a new progress group; later agent() calls are shown under it in /workflows.
log()log(message)
Emit a progress line to the user above the progress tree.
argsargs: any
The input passed to a saved workflow, verbatim. undefined if none. Read it for a question, target paths, or a config object.
budgetbudget: { total, spent(), remaining() }
The turn token target from a "+Nk" directive. total is null if unset; remaining() is Infinity then. The target is a hard ceiling — agent() throws once it is hit.
workflow()workflow(nameOrRef, args?) → Promise
Run another saved workflow inline as a sub-step. Nesting is one level deep.
Running & managing workflows
/workflows keys
↑ / ↓Select a phase or agent
Enter / →Drill into a phase, then an agent, to read its prompt, tool calls, and result
EscBack out one level
j / kScroll within an agent detail when it overflows
pPause or resume the run
xStop the selected agent, or the whole workflow when focus is on the run
rRestart the selected running agent
sSave the run as a /<name> command
Behavior & limits
16 concurrent agents
Fewer on machines with limited CPU cores. Excess calls queue and run as slots free up.
1,000 agents per run
A backstop against runaway loops, far above any real workflow.
No mid-run input
Only agent permission prompts pause a run. For sign-off between stages, run each stage as its own workflow.
No direct FS / shell
The script coordinates agents; agents read, write, and run commands.
Resumable in-session only
Completed agents return cached results. Exiting Claude Code restarts the workflow fresh next session.
Requires v2.1.154+
On all paid plans, Anthropic API, Amazon Bedrock, Vertex AI, and Microsoft Foundry. On Pro, enable it from the Dynamic workflows row in /config.
Enable / disable
/config
Toggle the Dynamic workflows row. Persists across sessions.
"disableWorkflows": true
Set in ~/.claude/settings.json (or managed settings for a whole org) to turn workflows off.
CLAUDE_CODE_DISABLE_WORKFLOWS=1
Environment variable read at startup; applies wherever you set it.
Ultracode keyword trigger
Turn off in /config to stop the ultracode keyword from triggering runs.
Frequently asked questions
What is a dynamic workflow in Claude Code?
A dynamic workflow is a JavaScript script that orchestrates subagents at scale. Claude writes the script for the task you describe, and a runtime runs it in the background — spawning dozens to hundreds of agents — while your session stays responsive. The script holds the loop, branching, and intermediate results, so only the final answer lands in Claude's context.
How do I start a dynamic workflow?
Include the keyword ultracode in your prompt (or just ask for "a workflow"), and Claude writes a workflow for that task. Or set /effort ultracode so Claude plans a workflow for every substantial task in the session. You can also run the bundled /deep-research, or any workflow you have saved.
What is ultracode?
Ultracode is a Claude Code setting that combines xhigh reasoning effort with automatic workflow orchestration. With it on, Claude decides when a task warrants a workflow and a single request can become several workflows in a row. It lasts for the session and resets when you start a new one.
When should I use a workflow instead of subagents or a skill?
Reach for a workflow when a task needs more agents than one conversation can coordinate, or when you want the orchestration codified as a repeatable script — codebase-wide audits, large migrations, and research that must cross-check its sources. With subagents, skills, and agent teams, Claude orchestrates turn by turn; a workflow moves the plan into code.
How much do dynamic workflows cost?
A workflow spawns many agents, so one run can use meaningfully more tokens than the same task in conversation. Runs count toward your plan usage and rate limits. To gauge spend, run on a small slice first — one directory, or a narrow question — and watch per-agent token usage in /workflows.
Can I save and reuse a workflow?
Yes. After a run does what you want, open /workflows, select it, and press s to save its script to .claude/workflows/ (shared in the repo) or ~/.claude/workflows/ (just you). It then runs as a /<name> command and can accept input through args.
Can a workflow resume if I interrupt it?
Within the same session, yes — agents that already finished return their cached results and the rest run live. Resume from /workflows with p, or ask Claude to relaunch the same script. Exiting Claude Code while a run is going starts it fresh next session.
What are the limits on a dynamic workflow?
Up to 16 concurrent agents (fewer on limited CPUs) and 1,000 agents total per run. The script itself has no direct filesystem or shell access — agents do that work. There is no mid-run user input beyond agent permission prompts; for sign-off between stages, run each stage as its own workflow.