[Feature Request] Add shell execution primitive to Workflow scripts for deterministic operations

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 4, 2026

Feedback: subagent fan-out cost — two findings from an instrumented workflow run

Claude Code, macOS 26.5.2, 18 cores. Measured from one Workflow run's own transcripts
(~/.claude/projects/<project>/subagents/workflows/<runId>/agent-*.jsonl), summing the
usage block on every assistant message. Numbers below are a live snapshot at 23 agents;
the run had not finished.

The measurement

A multi-agent design-review workflow: one mechanical-lint agent, four parallel reviewer
agents, one classifier, N parallel verifier agents (one per finding), one fix agent, looping
in rounds.

| | value |
|---|---|
| agents | 23 |
| assistant turns (all agents) | 1,030 |
| output tokens | 656,079 |
| cache creation | 5,586,784 |
| cache read | 72,733,002 |
| write : read ratio | 1 : 13.0 |
| avg context per turn | 70,614 |
| avg turns per agent | 44 |

Applying the published multipliers (writes 1.25×, reads 0.10×), the two halves are nearly
equal in base-token-equivalent terms: writes ≈ 7.0M, reads ≈ 7.3M. Neither dominates.

For scale on the user side: this single run consumed roughly 3% of a 20x Max weekly
allowance per round
, which puts a 5-round run near 11%. That is the reason for the report —
the cost is real, and most of it is invisible until you sum the transcripts.

Finding 1 — fan-out re-pays cache creation for identical context, N times

Every one of the 23 agents wrote its own cache: 242,903 tokens per agent on average,
5.59M total. A large share of that is the same bytes — the same design document and the
same 10,000-line source file, read independently by each reviewer.

It cannot currently be shared, and the reason is structural rather than a missing feature:

  • Prefix caching requires an identical prefix from token 0. Each subagent's prefix diverges

immediately — different agent-type system prompt, different task prompt.

  • The shared content (a file) arrives later, as a tool result, at a different offset in

each agent. Under prefix caching that position can never be a cache hit.

What would help, in increasing order of effort:

  1. Document the pattern. Callers can capture much of this today by prepending shared

context byte-identically before anything agent-specific, so agents 2..N read instead of
write. Nothing in the Agent/Workflow docs suggests this, and it is not obvious — the
natural way to write a fan-out puts the per-agent instruction first.

  1. A shared-prefix parameter for fan-out — let a caller declare "these N agents share

this prefix", so the platform writes once and reads N−1 times.

What I am explicitly not claiming: that general cross-agent cache sharing is easy or
overlooked. KV entries are position-dependent and conditioned on all preceding tokens, so
splicing a cached block into a different conversation at a different offset is not the same
computation. Relaxing that is a research direction with accuracy tradeoffs, not a flag. I am
reasoning from published prefix-caching semantics and cannot see the implementation.

And the honest bound on the win: cache reads are turns × context, entirely within one
agent — 1,030 turns × 70,614 average context. Sharing between agents does not touch that
half at all.
Best case here is a fraction of the write half, maybe 15–25% of the input bill.
Worth having, not a fix.

Finding 2 — workflow scripts cannot run trivial shell commands, so mechanical steps get priced as agents

This one has no physics behind it and a much better payoff.

Workflow scripts have no filesystem or shell access; every action must be an agent() call.
My workflow's first phase runs a Python linter over a document — 0.2 seconds from a
terminal.
Because the script cannot invoke it, the phase is an agent that shells out and
then interprets the result.

Measured cost of that one phase:

| | |
|---|---|
| wall clock | 11m 46s (serial — it blocks the entire run) |
| tool calls | 45 (25 Bash, 16 Edit, 4 Read) |
| cache read | 5.56M |
| cache write | 333,546 |

11m46s of a 41-minute round, and ~8% of the run's tokens, to run a command that takes 0.2
seconds.
Some of that agent's work was genuine judgment, but the mechanical part — run
script, read exit code, branch — is pure overhead imposed by the missing primitive.

Request: a sh() / exec() primitive in workflow scripts, even a restricted one
(no network, working-directory-scoped, output size capped). Deterministic glue is exactly
what the scripting layer is for; forcing it through a model turns a free step into the
most expensive serial phase in the run.

This also has a correctness dimension, not just cost. The docs rightly push deterministic
control flow into the script and away from model judgment — but with no way to run a check,
every mechanical gate has to be delegated to an agent that may interpret it loosely. A sh()
primitive would let the script compute a gate rather than ask for one.

Reproducing

Any Workflow run leaves per-agent transcripts under
~/.claude/projects/<project>/subagents/workflows/<runId>/agent-*.jsonl. Summing
cache_creation_input_tokens, cache_read_input_tokens and output_tokens across every
usage block reproduces the table above. journal.jsonl gives per-agent start/result events
for the wall-clock figures.

Incidentally: that per-agent accounting was easy to extract and genuinely useful. Surfacing
a token summary per phase in /workflows would let people tune fan-out without writing a
script to parse their own transcripts.

View original on GitHub ↗