[Feature Request] Increase concurrent workflow agent limit for hosted sandboxes

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 3 comments · opened Jul 20, 2026

Bug Description
Workflows limit the number of concurrent agents that you can have running to the number of cores minus two, or 16, whichever is lower. On the Claude Code mobile app, when the sandbox is hosted by you guys, the number of cores is four, so the maximum number of concurrent workflow agents that can run is two, which makes workflows run very slowly (almost x10 slower in some cases). I'm asking for a feature where I can pay more or have more cores so I can run workflows faster (with more parallel workflow agents).

Environment Info

  • Platform: darwin
  • Terminal: iTerm.app
  • Version: 2.1.215
  • Feedback ID: ac8f7b9c-e857-4d7d-a6e9-eb8d075a0059

Errors

[]

View original on GitHub ↗

3 Comments

kcarriedo · 1 month ago

The min(cores - 2, 16) cap makes sense on a local machine where the cap is protecting your own hardware, but on a hosted sandbox where you're paying per token and not sharing cores with anything else, the cap becomes an artificial throttle on what you can actually do with the quota you're spending.

The pain here is compounded because the cap is static -- it doesn't adjust to the actual workload. A workflow with 8 short parallel tasks hits the same cap as one with 8 long-running tasks, but the short ones release slots quickly anyway. A dynamic cap (or at minimum a user-configurable override) would let the hosted sandbox use its actual capacity.

Worth noting in the bug for Anthropic's triage: on a 4-core hosted sandbox, cores - 2 = 2 means two sequential agents run at a time. If each agent takes 5 minutes, a 10-agent workflow takes 25 minutes wall-clock that could be 8-10 minutes with full parallelism. That's the "almost 10x slower" you're seeing in practice.

The most direct near-term fix would be an environment variable (e.g., CLAUDE_CODE_MAX_WORKFLOW_CONCURRENCY) that lets the caller override the cap independently of core count, with the hosted sandbox environment setting a safe default higher than 2. A user-visible "increase parallelism" tier or credit would be a longer-term product decision.

rjlasko · 17 days ago

Adding a corroborating use case for the "raise it" side: a corpus-scale research workflow (many independent per-partition lookups — registry/EOL/vulnerability fetches, then judgment passes grouped by ecosystem/family) dispatched entirely through pipeline()/parallel() against the tool's own native pool, deliberately not defining a bespoke concurrency argument of its own — the design assumed the harness's native cap was the right layer to own this, precisely so we wouldn't have to build and maintain redundant pool/queue code. That assumption holds fine on a modest host, but on a well-resourced one the fixed 16 ceiling (vs. a query-bound external API, not local compute) becomes the same "artificial throttle on quota you're already paying for" described above. +1 on a user-configurable override — the env var idea (or a workflow.maxConcurrentAgents settings key, as floated in #63938) would let hosts opt out of the CPU-derived default without every workflow author reinventing chunking/backoff.

oconnorjoseph · 7 days ago

Still present at 2.1.241. Adding implementation details, since I went looking for an existing override and there isn't one — plus a measurement suggesting the cap is keyed to the wrong resource.

The exact cap

In the 2.1.241 binary it's computed once at module load:

function kvT(e){ return Math.min(16, Math.max(2, e - 2)) }
AvT = kvT(require("os").availableParallelism());   // then: j = Zh(AvT, ie)

Two things worth surfacing for triage:

  • There's a Math.max(2, …) floor that the usual cores - 2 shorthand hides — and it's exactly what produces the behaviour @aloysiusmud reports. On the 4-core hosted sandbox, max(2, 4-2) = 2, so "two at a time" is the floor doing its job rather than an incidental result.
  • AvT has exactly one assignment, and availableParallelism() is its only input. No env var, no settings key, nothing in the config schema. Worth stating explicitly because there is LLM-generated advice circulating that recommends adding "maxParallelAgents": 16 to .claude/settings.json — that string does not occur anywhere in the 325 MB binary, and the key does nothing.

The cap is coupled to the wrong resource

+1 to @SomeoneKong's point in #63938, with a measurement. On a 10-core Apple Silicon Mac the cap resolves to 8. I raised it locally and ran a 12-agent parallel() fan-out in which each agent's entire job was sleep 20:

START 0..11  — all twelve within the same second
END   0..11  — all twelve within the same second

Agent slots are overwhelmingly network-bound waiting on the API, not CPU-bound, so a CPU-derived divisor is sizing against something that isn't the constraint. The workable ceiling is min(what the host can stand, what the account's rate limit allows) — and only the user knows the second term.

The change looks close to free

There is already a CLAUDE_CODE_WORKFLOW_* env namespace (CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS, CLAUDE_CODE_WORKFLOW_SIZE_WARNING_AGENTS), and a validated-integer env helper (min: 1, digitsOnly) already in use by CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS. So:

AvT = env.CLAUDE_CODE_WORKFLOW_MAX_CONCURRENCY ?? kvT(os.availableParallelism())

One call site, one existing validator, no new config surface.

Two requests on the semantics:

  1. Have the override replace the CPU-derived default rather than only raise it. #63938 carries a concrete case for setting it lower than the default, to avoid a self-inflicted 429 storm on a high-core-count host with a plan that can't sustain 16.
  2. Keep the hard 16 ceiling out of the override path — that ceiling is precisely what makes the setting useless to anyone who has already outgrown it.

Happy to test a build.