Workflow resumeFromRunId re-dispatches completed agent() calls despite unchanged (prompt, opts)
Summary
Resuming a Workflow run with resumeFromRunId re-dispatched four agent() calls whose results were already in the run's journal.jsonl, even though their (prompt, opts) were byte-identical to the completed calls. The docs say the longest unchanged prefix of agent() calls returns cached results instantly and only edited or new calls run live; here, completed calls past the edit point re-ran.
Environment
- Claude Code 2.1.222, VS Code extension host
- win32 (Windows 11 Pro 10.0.26200)
- Model: claude-fable-5
Repro shape
- Launch a Workflow (ours ran 16
agent()calls: a pipeline of ticket agents followed by verify agents, script passed viascript, later iterated viascriptPath). - Mid-run, stop it with TaskStop ("pause clean").
- Edit the script file: change ONLY the prompts of calls that had never completed (two resume prompts got an audit-first preamble). All completed calls kept byte-identical
(prompt, opts). - Relaunch with
Workflow({scriptPath, resumeFromRunId}).
Expected: completed calls replay from journal.jsonl (their results sit there keyed v2:<sha>); only the edited and never-started calls run live.
Observed: four calls that had completed before the stop were dispatched again as live agents. Their journal entries existed with results. The re-runs cost real tokens and wall clock, and, because these agents mutate a git tree, a re-run of a "build X" prompt against a tree where X already landed can duplicate work or conflict with itself. Ours survived only because the prompts were phrased verify-first, so the re-dispatched agents found the work in git log and no-oped.
Guesses at the cause
The four re-dispatched calls were downstream of a pipeline() whose earlier stages interleave; if the cache key includes call ordinal or some interleaving-sensitive component rather than the content hash alone, a resume that reaches calls in a different order would miss the cache. We did not confirm this; the (prompt, opts) bytes were confirmed identical.
Ask
Either replay completed calls from the journal whenever the content hash matches, regardless of dispatch order, or document that resume caching is prefix-ordered and an interleaved pipeline can invalidate completed calls behind an edit point.