Dynamic workflows
Orchestrating many subagents from a script Claude writes — the ultracode keyword, /workflows, saving runs as commands, limits, resume, and cost.
A dynamic workflow is a JavaScript script that orchestrates subagents at scale. You describe the task, Claude writes the script, and a runtime executes it in the background while your session stays responsive.
The point isn’t just “more agents”. It’s that the plan moves into code: the loop, the branching, and the intermediate results live in script variables instead of in a context window. Claude’s context only holds the final answer.
When it’s worth it
Subagents, skills, agent teams, and workflows can all run a multi-step task. The difference is who holds the plan:
| Subagents | Skills | Agent teams | Workflows | |
|---|---|---|---|---|
| What it is | A worker Claude spawns | Instructions Claude follows | A lead supervising peer sessions | A script the runtime executes |
| Who decides what’s next | Claude, turn by turn | Claude, following the prompt | The lead agent, turn by turn | The script |
| Where intermediate 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 tasks per turn | Same as subagents | A handful of long-running peers | Dozens to hundreds per run |
| Interruption | Restarts the turn | Restarts the turn | Teammates keep running | Resumable in the same session |
Reach for a workflow when the task is bigger than one conversation can coordinate, or when the same step has to run across many items: a codebase-wide bug sweep, a 500-file migration, a research question whose sources need cross-checking, a hard plan worth drafting from several angles first.
Width or depth
The feature workflows are most often confused with isn’t subagents — it’s /goal,
because both let Claude run a long way without you. They point in different directions:
/goal |
Workflows | |
|---|---|---|
| Shape | Depth — one line of work, many passes | Width — many lines of work, one pass each |
| Stops when | A condition you wrote evaluates as met | The script finishes |
| The unit | Iterations against a target | Agents against a work-list |
| Fails by | Looping, if “done” was never crisp | Costing a lot, if the fan-out was too broad |
/goal all tests pass and the linter is clean keeps working until that’s true. A workflow fans a
hundred agents across a hundred files once, then synthesizes. Both punish a vague brief — one by
never converging, the other by spending in parallel.
They compose (a workflow inside a goal loop), which is powerful and an excellent way to spend a lot of money quickly. Bound the scope and name the deliverable before either.
Starting one
Per prompt
Put ultracode in the prompt, or just ask in your own words — “use a workflow” counts as the
same opt-in.
For the whole session
/effort ultracode — xhigh reasoning plus automatic orchestration. Claude then plans a
workflow for every substantive task.
ultracode: audit every API endpoint under src/routes/ for missing auth checks
Claude Code highlights the keyword in your input and writes a script instead of working turn by turn. The keyword only changes how the work is structured — the run stays inside the session’s permission mode and sandboxing.
Say “dynamic workflow”, not just “workflow”
The word workflow shows up in ordinary sentences — “my deploy workflow”, “the review workflow” — and Claude Code highlights it without that meaning you asked for one. If you want a run, ask for it plainly: “set up a dynamic workflow to…”. The highlight is not the opt-in.
Dismissing the keyword
Option+W (macOS) or Alt+W (Windows/Linux) drops the highlight for this prompt; backspace
right after the highlighted word works too. Turn it off for good with Ultracode keyword
trigger in /config.
Where the keyword does nothing
It’s an opt-in only in a prompt you type. It’s ignored in -p prompts, SDK prompts not
stamped as human input, scheduled tasks, and webhook or PR-comment payloads relayed into the
conversation.
Session-wide ultracode costs more
One request can become several workflows in a row — understand, change, verify. It applies to
every task in the session and resets when you start a new one; /effort high puts you back.
Requires v2.1.203+.
The bundled one
/deep-research <question> ships with Claude Code and is the fastest way to see a workflow run. It
fans out web searches across several angles, cross-checks the sources it finds, votes on each claim,
and returns a cited report with the claims that didn’t survive filtered out. It needs the WebSearch
tool available, and it only runs when you invoke it.
Approval
The per-run prompt lists the planned phases with Yes, run it, Yes, and don’t ask again for
this workflow in this project, View raw script (Ctrl+G opens it in your editor), and No.
Tab lets you adjust the prompt before the run starts.
| Permission mode | When you’re prompted |
|---|---|
default, acceptEdits |
Every run, unless you chose “don’t ask again” for that workflow here |
| Auto | First launch only; skipped entirely when ultracode is on |
bypassPermissions, claude -p, Agent SDK |
Never — the run starts immediately |
What the script looks like
Plain JavaScript with top-level await: a meta block, then a body that spawns agents.
export const meta = {
name: 'audit-routes',
description: 'Audit every route handler for missing auth checks',
}
const found = await agent('List every .ts file under src/routes/.', {
schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})
const audits = await pipeline(found.files, file =>
agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)
return audits.filter(Boolean)
| Primitive | What it does |
|---|---|
agent(prompt, options) |
Spawns one subagent. schema constrains its result to JSON; label names it in the progress view. |
pipeline(items, fn) |
Runs one agent per item in a list. |
args |
A global holding the input passed at invocation — structured data, not a string. undefined when nothing was passed. |
Watching and managing a run
/workflows lists running and finished workflows; select one and press Enter for its progress view,
which shows each phase with agent counts, token totals, and elapsed time. A one-line summary also
appears in the task panel below the input box (↓ to focus, Enter to expand).
| Key | Action |
|---|---|
↑ / ↓ |
Select a phase or agent |
Enter / → |
Drill in — a phase, then an agent’s prompt, recent tool calls, and result |
Esc / ← |
Back out one level |
j / k |
Scroll inside a long agent detail |
f |
Filter the phase’s agents by status; press again to cycle |
p |
Pause or resume the run |
x |
Stop the selected agent — or the whole workflow when focus is on the run |
r |
Restart the selected running agent |
s |
Save the run’s script as a command |
Saving a run as a command
Press s in /workflows, then Tab to pick where it lands:
- .claude/
- workflows/
- review-branch.js
- workflows/
- ~/.claude/
- workflows/
- triage-issues.js
- workflows/
Project scripts are shared with everyone who clones the repo; the home directory ones follow you
across projects and are yours alone. Either way the workflow becomes /<name> in future sessions and
shows up in / autocomplete. If both locations define the same name, the project one wins. Workflows
shipped in a plugin live in a workflows/ directory at the plugin root and run namespaced —
/acme-tools:release-audit.
Saved workflows take input through args:
Run /triage-issues on issues 1024, 1025, and 1030
Resuming
A stopped run can be resumed with p from /workflows, within the same session — exiting Claude
Code loses it. Two rules decide what’s kept:
Unfinished agents aren't cached
An agent still running when you stopped starts over on resume.
Replay follows start order
Cached results stop at the first agent that didn’t finish; everything started after it reruns, even if it completed. Stop while B of A–B–C–D is going and C and D both run again.
That’s why a fan-out of many small agents preserves far more progress than one long-running agent.
Limits and cost
| Constraint | Why |
|---|---|
| No mid-run user input | Only permission prompts pause a run. For sign-off between stages, run each stage as its own workflow. |
| No filesystem or shell access from the script | Agents read, write, and run commands; the script only coordinates them. |
| Up to 16 concurrent agents | Fewer on machines with limited CPU cores. |
| 1,000 agents per run | Prevents runaway loops. |
A run can burn meaningfully more tokens than doing the same task in conversation, and it counts
against your plan’s limits like any other session. Claude Code flags a run scheduling more than 25
agents or projected past 1.5M tokens with a Large workflow warning in the task panel — advisory
only, and hidden when ultracode is on.
Size guideline
Advice to Claude about how many agents to aim for, not a cap. Set it with /config (Dynamic
workflow size), /config workflowSizeGuideline=small, or the workflowSizeGuideline settings key.
| Value | Agents Claude aims for |
|---|---|
unrestricted |
No guideline — sized to the task |
small |
Fewer than 5 |
medium |
Fewer than 15 — the default |
large |
Fewer than 50 |
Turning it off
Toggle Dynamic workflows off in /config, set "disableWorkflows": true in
~/.claude/settings.json (or in managed settings for a whole org), or set
CLAUDE_CODE_DISABLE_WORKFLOWS=1. The bundled commands disappear, ultracode stops triggering runs,
and it leaves the /effort menu.