Nested subagents: children spawned by a subagent are always async (regardless of run_in_background), completion notifications never reach the subagent parent, and TaskStop fails with ownership errors after resume

Open 💬 10 comments Opened Jul 7, 2026 by mof086999-code

Environment

  • Claude Code v2.1.201, macOS (Darwin 27.0.0), CLI + desktop session
  • Reproduced across models (Opus 4.8 and Fable 5 orchestrators, Sonnet children)

Summary

When an agent spawned via the Agent tool (an "orchestrator" subagent) spawns its own children via the Agent tool, three related failures occur reliably. We ran a controlled experiment (10+ orchestrator runs over two days) and can share reproduction data.

1. Children are effectively async regardless of run_in_background
Even when the orchestrator's Agent call does not set run_in_background (or sets it to false/null), the child runs detached: the orchestrator's turn does not block on it, no completion notification is delivered to the orchestrator, and the orchestrator is never auto-resumed. Transcript inspection shows run_in_background: null on the calls, yet the parent proceeded and later ended its turn "waiting for the child's completion notification" — which never arrives. Result: the orchestrator stalls permanently unless externally poked.

  • Frequency: in our first experiment round, all 4 of 4 orchestrator runs (2 models × 2 tasks) stalled at least once with "I'll wait for the implementer's completion notification".
  • Docs mismatch: the docs suggest the top-level subagent's summary returns to the caller; for nested spawns nothing returns to the intermediate parent.

2. Child completion notifications are misdelivered to the main conversation
When the child finishes, its completion notification (task-notification) is delivered to the main conversation that spawned the orchestrator — not to the orchestrator that actually spawned the child. We observed 6+ instances. The orchestrator meanwhile believes the child is still running.

3. TaskStop fails with ownership errors after a SendMessage resume
If the main conversation resumes a stalled orchestrator via SendMessage ("was stopped; resumed it"), the resumed orchestrator can no longer stop children it spawned before the resume: TaskStop fails with an ownership/permission error (observed in 3 of 4 runs that attempted it). The un-stoppable child keeps writing to the shared working tree, racing the parent.

Minimal reproduction sketch

  1. Main conversation: spawn orchestrator O via Agent (run_in_background: true).
  2. O's prompt: "delegate an implementation task to a child via the Agent tool (foreground), then verify its result".
  3. O spawns child C without run_in_background.
  4. Observe: O's turn continues immediately (C is detached); O ends its turn stating it will wait for C.
  5. C completes → notification arrives in the main conversation, not in O. O never resumes.
  6. Main resumes O via SendMessage → O attempts TaskStop on C → ownership error.

Workaround that eliminated the stalls for us

Prompting orchestrators with a "delegation set" removed the stalls completely (0 stalls in 4 subsequent runs, vs 4/4 + 3 more in control runs):

  • children must write their report to an agreed absolute path (write to a temp name, then mv to the final name for atomicity),
  • the parent runs a bounded foreground wait loop in the same turn (for i in $(seq 1 60); do [ -f REPORT ] && break; sleep 15; done),
  • never end a turn depending on a child's completion; on timeout, checkpoint and continue solo (children can't be stopped anyway).

This works but burns a foreground Bash slot for polling; native completion delivery to the spawning parent would remove the need.

What we can provide

Timestamped transcripts (JSONL) for all runs showing: run_in_background: null spawns behaving async, stall messages, misdelivered notifications (with origin.kind metadata), and TaskStop ownership errors. Happy to share extracted excerpts.

Related issues

  • #69212 (open) — overlaps with symptom 2 here (notification misrouting). This issue adds symptoms 1 (always-async nested children) and 3 (TaskStop ownership errors after resume), plus controlled-experiment frequency data and a prompting workaround.
  • #69249 (closed as duplicate of the above).

View original on GitHub ↗

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