94% Context Limit Shows Why Claude Code Workflows Scale

94% Context Limit Shows Why Claude Code Workflows Scale

Right around the point where context usage climbs toward the ceiling, Claude Code starts summarizing its own plan back to you instead of actually finishing the job. During a large file sweep, it silently dropped already flagged directories without throwing a single error. None of the docs mention that a saved workflow is just a snapshot of orchestration logic at save time, not a spec that adapts when the codebase structure shifts underneath it. Dynamic workflows exist specifically to remove this kind of context pressure, but a saved script can go stale and quietly match fewer files than it should, with nothing telling you it happened. So the real question is when a workflow actually solves that problem, and when it just moves the same risk somewhere harder to spot.


A dynamic workflow in Claude Code is a JavaScript script. Claude writes it based on the task you describe in plain language, then a runtime executes that script in the background while your actual session stays free to do other things. The core move is simple to state and genuinely different in practice: instead of Claude acting as a live orchestrator deciding turn by turn what to spawn next, with every subagent result flowing back into its own context window, the orchestration logic becomes code. Loops, branching, retries, intermediate results, all of it lives in the script now, not in Claude's head. Claude's context only has to hold the final answer.


That distinction sounds academic until you've watched a long-running review eat its own context trying to hold forty file diffs in working memory. Once you've seen that happen, moving the loop into a script instead of a running conversation stops being theoretical and starts being obvious.


Explaining Why Subagents Alone Stop Scaling

Two Orchestration Models Compared

Live Subagent Orchestration (context bound)

1. Spawn subagent
→
2. Result to context
→
3. Context fills
→
4. Silent compression

Result: flagged directories silently dropped, no error thrown

Dynamic Workflow (script bound)

1. Claude writes script
→
2. Runtime executes loop
→
3. State in file/var
→
4. Final answer only

Result: Claude's context holds only the finished output, not every intermediate result

Source: Based on article description of Claude Code workflow mechanics


The standard Claude Code subagent model works fine for a bounded task. You ask for a review of three files, Claude spins up a subagent or two, results come back, done. The problem shows up at the edges: a codebase-wide bug sweep across two hundred files, a migration touching five hundred, a research task needing a dozen independent source checks before it can synthesize anything. In those cases, Claude is still deciding, conversation turn by conversation turn, what to spawn next and where to route each result. Every one of those results has to land somewhere, and that somewhere is the context window of your active session.


I ran into this directly trying to get Claude Code to sweep a Django codebase for a deprecated settings pattern that had drifted into a large number of files over time. Early on, it worked the way you'd expect. It spawned a subagent per directory, each one reported back, Claude aggregated the results. Partway through, the session started compressing earlier findings to make room, and by the end it had quietly lost track of a couple of directories it had already flagged as clean. No crash, no error. Just a silent gap that only showed up when I diffed the final report against the subagent logs by hand.


That's the actual argument for workflows. Not a benchmark number, not a marketing line. When the orchestration lives in a script, each subagent's output gets written, read, and routed by code that doesn't get sleepy and start compressing itself halfway through. The script holds state the way a program should: explicitly, in a variable or a file, not implicitly in a context window with a ceiling it will eventually hit.


Raising the context limit or using a bigger model wouldn't fix this, because the failure wasn't a capacity problem. The session had room left when it started dropping directories. It compressed early findings on its own schedule, not because it ran out of space. The fix is moving state out of the context window entirely, which is exactly what a script does.


Running A Dynamic Workflow In Practice

Where Orchestration Logic Lives, By Workflow Type

Approach State Held In Failure Mode
Live Subagents Context window Silent self compression, dropped results
Saved Workflow Static snapshot script Goes stale, matches fewer files silently
Dynamic Workflow Script variable or file None reported, explicit state tracking

Source: Based on article comparisons of subagent, saved workflow, and dynamic workflow approaches


So if the fix is moving orchestration into a script, what does actually running one look like day to day? You don't write the JavaScript yourself, at least not at first. You describe the task, Claude drafts the orchestration script, and a runtime executes it in the background while your main session stays responsive enough to answer other questions or start a second task. That background execution detail matters more than it sounds like it should. On a task that would've otherwise locked up a session for twenty minutes, being able to keep working in the same window while the workflow runs is the difference between a background job and an excuse to go get coffee.


A workflow script for a migration task ends up looking roughly like this, simplified from a run I did against a smaller test repo:



async function migrateFile(filePath, agentPool) {
  const agent = await agentPool.acquire();
  const result = await agent.run({
    task: "migrate-settings-pattern",
    file: filePath,
    retries: 2
  });
  if (result.status === "failed") {
    await logFailure(filePath, result.error);
    return { filePath, ok: false };
  }
  return { filePath, ok: true, diff: result.diff };
}

async function runMigration(fileList) {
  const pool = createAgentPool({ concurrency: 8 });
  const results = await Promise.allSettled(
    fileList.map(f => migrateFile(f, pool))
  );
  return summarize(results);
}

What that script buys you isn't raw speed, though concurrency helps. It's that the retry logic, the failure logging, and the summarization step are all explicit and rerunnable. If a handful of files fail on the first pass because of a lint rule you didn't account for, you fix the rule and rerun the script against just those files, instead of re-explaining the whole task to Claude from scratch and hoping it remembers what it already handled correctly.


The part that actually surprised me: when a subagent inside the workflow hit a rate limit mid-run, the script's own retry logic handled it silently, and I only found out by checking the run log afterward. In a live, conversation-driven subagent setup, that kind of transient failure tends to surface as Claude narrating the problem to you in real time, reassuring but noisy. The workflow version just handles it and tells you after the fact. Whether that's an improvement depends entirely on whether you wanted to know in the moment.


Saving A Workflow For Reuse Without Losing The Plot

Scale Of The Sweep That Broke Live Orchestration

3
Files in a bounded task, subagents work fine
200
Files in the codebase wide bug sweep that strains context
500
Files in a migration task cited as pushing past limits
0 errors thrown
During the Django sweep where previously flagged clean directories were silently dropped from the final report

Source: Based on article's Django codebase sweep anecdote and stated task scales


Running a workflow once solves a single task. The feature that actually changes how I think about repeat tasks is the save step. Once a workflow has run, you can run /workflows, pick the run you want to keep, and press s to save that run's script as a reusable command. A save dialog lets you tab between two save locations, which in practice means choosing between keeping it scoped to the current project or making it available more broadly.


This turns a one-off orchestration into something closer to a Makefile target. A code review run against every branch before merge, a dependency audit run monthly, a documentation consistency check across a docs folder that keeps drifting from the actual API: these are exactly the repeatable tasks where re-describing the orchestration to Claude every time wastes your time. Save it once, invoke it as a command going forward.


Here's roughly what that saved invocation looks like once it's in place, assuming you kept it project scoped:



first run, Claude writes the workflow from a natural language description

claude "sweep the repo for any use of the old settings.DEPRECATED_FLAG pattern and migrate it"

after reviewing the run with /workflows and pressing s to save

claude /run branch-review --target=origin/main

rerun on a fresh branch weeks later, same script, same logic

claude /run branch-review --target=feature/payments-v2

The honest caveat, and this didn't come through clearly in my first pass through the documentation, is that a saved workflow is a snapshot of the orchestration logic at the moment you saved it. It's not a living spec that adapts if your codebase structure changes. I saved a workflow for a lint sweep, then restructured the repo into a monorepo layout two months later, and the saved script's file path assumptions quietly broke. No loud error, it just silently matched fewer files than it should have. Same kind of silent gap as the directory sweep earlier, just triggered by a path change instead of context compression. Rerunning any saved workflow after a structural change to the project is worth treating as a checkpoint, not a formality.


That raises a real question about maintenance. A workflow is code, and code needs the same upkeep any other script in your repo needs. Who owns that upkeep when the author of the workflow was Claude, not a person on the team?


Comparing Workflows To Agent Teams And Skills


That maintenance question only matters if a workflow is the right tool in the first place. Worth placing workflows against the other two coordination features Claude Code offers. Agent teams let multiple Claude instances work a shared task with Claude still deciding the routing live, turn by turn, so you get the benefit of adaptive reasoning mid-task, but you also inherit the context pressure problem once the task gets large enough. Skills package up a reusable capability, like a specific kind of code review or a particular refactor pattern, but they're invoked within a single agent's turn, not spread across a fleet of subagents running in parallel.


A dynamic workflow sits one level further out. It's the right layer when the orchestration itself, the branching, the retry logic, the aggregation step, is complex enough that you want it inspectable and rerunnable as its own artifact, independent of any one conversation. If the task is small enough that Claude deciding live doesn't strain the context window, reaching for a workflow is overhead you didn't need. I tried wrapping a three-file refactor in a workflow once just to test the save and rerun flow. It worked, but it was obviously the wrong tool for a task that size. The script added a layer of indirection with no payoff.


Where workflows still earn their place is a quality pattern I noticed almost in passing while testing one: because the orchestration is explicit code, you can have one set of subagents produce an artifact and a separate, independent set of subagents critique it, with the script enforcing that the critics never see the producers' reasoning, only their output. That's a genuinely different pattern from a single Claude instance reviewing its own work, which tends to inherit whatever blind spot produced the error in the first place. Building that independence into the structure of the script is much easier than hoping a single model holds two opposing stances in its head at once.


So the choice isn't really workflows versus agent teams versus skills as competing options. It's a question of which layer the complexity actually lives at for the task in front of you.


Knowing When The Overhead Is Not Worth It


Picking the right layer before paying the cost of a wrong choice means being honest about what a workflow costs, not just what it fixes. Writing a correct script is still a drafting problem, and Claude drafting JavaScript to orchestrate other Claude instances is one more layer where a subtle bug can hide. I hit a case where the generated workflow's concurrency pool was set high enough that it tripped a secondary rate limit I didn't even know existed on a shared API key, and the resulting failures were logged but not surfaced clearly until I went looking. A conversation-driven subagent run would likely have surfaced that same rate limit as a visible pause, not a line buried in a log file you have to think to check.


There's also a team dynamics question the documentation rarely addresses, because it's not really a documentation problem. Once a workflow is saved and shared, a colleague a few months later is going to run it without having watched it get written. If it breaks silently, like my restructured repo one did, that colleague has no intuition for why. A workflow script, unlike a quick subagent task, is an artifact that outlives the session that created it, which means it inherits all the normal obligations of code you didn't personally write. Someone has to read it before trusting it blindly.


None of that is a reason to avoid the feature. The question from the start was whether moving orchestration into a script actually removes the context pressure problem or just relocates it. It removes it, but only for context. The script still needs a human to rerun it as a checkpoint after any structural change, and to read it before trusting it a second time. Treat a saved workflow the way you'd treat any generated code you plan to run again in three months: read it once before the second run, not just the first.