Workflow resume: prefix-based cache re-runs all successful agents after an early failure (docs imply per-call caching)
Environment
- Claude Code v2.1.207, macOS (darwin 25.5.0)
- Model: claude-fable-5
Scenario
A workflow ran 102 parallel agent() calls via pipeline(). 100 succeeded; 2 failed with a terminal API error (Output blocked by content filtering policy). The 4th call in list order was one of the failures.
Resumed with Workflow({scriptPath, resumeFromRunId}) expecting only the 2 failed agents to re-run.
What happened
Only the first 3 calls replayed from cache. Calls 5–102 — 96 already-successful agents — re-executed live, burning several million duplicate tokens before the run was manually stopped. This matches the "longest unchanged prefix" wording in the tool description, since the failed 4th call broke the prefix.
Problems
- Docs contradict themselves. The same tool description also says: "Completed agent() calls with unchanged (prompt, opts) return their cached results instantly; only edited or new calls re-run" — which is per-call keying, not prefix keying. One of the two statements is wrong; the expensive one is true.
- The failure mode is inverted from the main resume use-case. The most common reason to resume is retrying a few failed agents in a large fan-out. With prefix semantics, an early failure guarantees a near-full re-run — resume is then strictly worse than not resuming (same cost, plus overwriting outputs).
- The /workflows UI doesn't distinguish cache-replays from live runs, so the mass re-execution looks like normal progress; the duplicate spend is only discoverable from token counters.
Suggestion
Key the journal cache by (call-site prompt, opts) independent of failed siblings — a failed call should re-run without invalidating later successful calls (unless their inputs changed). If prefix semantics must stay, make the docs unambiguous and have the resume result/UI state clearly how many calls will replay vs re-run before spending.