[Workflow tool] resumeFromRunId does not restore nested workflow() child runs — in-flight children restart from scratch

Resolved 💬 2 comments Opened Jun 19, 2026 by OTMO123 Closed Jun 22, 2026

Summary

With the Workflow tool (multi-agent orchestration, CLAUDE_CODE_WORKFLOWS=1), resuming a
parent run via Workflow({ scriptPath, resumeFromRunId }) does not restore nested
workflow(name, args) child runs. A child that was in flight at interruption restarts from
its first agent(), discarding every completed agent inside it. For dispatcher/fleet
patterns (a parent that calls a child workflow per work-item) this throws away the bulk of a
long run.

Pattern / environment

  • Parent fleet workflow processes N items via a bounded pool; per item it calls

await workflow('child', { ... }) (one level of nesting).

  • Each child runs ~25–30 agent()/parallel() calls (e.g. lock → context → … → verify).

Repro

  1. Run the parent; 3 children are ~28 agents deep each.
  2. Pause (or hit a session limit / the ~13-min background timeout, cf. #64627).
  3. Resume with Workflow({ scriptPath, resumeFromRunId }).

Expected: completed work inside the children replays from the journal; in-flight children
continue near where they stopped.
Actual: the parent's own agent() calls replay from cache, but every workflow() child
re-invokes from scratch (the child's first phase runs again). ~84 agents of progress
(28 × 3) are discarded. Worse, re-running a child whose first attempt already committed work
can mis-fire downstream gates (e.g. a TDD RED test re-runs against an already-green branch and
fails for the wrong reason).

Mechanism (best understanding)

The resume journal caches the parent run's own agent() calls keyed by (prompt, opts). A
nested workflow() spins up a child run with its own journal that the parent's
resumeFromRunId does not extend into. Child agents share the parent's concurrency cap /
agent counter / token budget, but not the resume journal — so there is no observed way to
resume an in-flight (or even a completed) nested child.

Proposed fix

  1. Journal nested child runs under the parent runId — give each workflow() call a stable

sub-run id (call-site index + args hash) and record its child agent() results in the
parent's journal namespace. On resume, completed child agents replay from cache; an
in-flight child resumes at its last completed agent().

  1. At minimum, cache the return value of a fully-completed workflow() call so a child

that finished before the interruption is not re-run.

  1. Document the resume semantics for nested workflows either way.

Broader principle (the real ask)

Resume today behaves like "re-run the orchestrator with a result cache," not "continue where
it paused." For long autonomous runs that is fragile: an interrupted agent loses its in-flight
context and re-runs. The transcripts already persist
(~/.claude/projects/<project>/<session-id>.jsonl, agent-*.jsonl). It would be far more
robust if Workflow resume could continue in-flight agents session-style — the way
claude --resume reattaches to a CLI conversation — rather than discard and re-run them.
Resume should feel like reattaching to a terminal, not restarting a script.

Related

#65796, #67488, #16607 (resume re-runs completed agents / pick up where interrupted),
#63102 (resume cache unreachable when args aren't byte-exact), #64627 (background runs killed
at ~13-min timeout — a common trigger).

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗