Background tasks started by a non-root sub-agent become permanently orphaned once that sub-agent's turn ends
Title: Background tasks started by a non-root sub-agent become permanently orphaned once that sub-agent's turn ends
Claude Code version: 2.1.208
Summary
A background task (Bash run_in_background: true, likely also applies to a nestedAgent/Task dispatch) started by a sub-agent that is not the root session becomes
completely untrackable — not pollable via TaskOutput, not stoppable via TaskStop,
no completion notification ever surfaces — the moment the spawning sub-agent's own
turn ends. This isn't a routing gap (e.g., "the notification goes to the wrong
place") — the task appears to vanish entirely from the root session's task registry.
Repro steps
- From a root session, dispatch a sub-agent (
Agenttool). - Within that sub-agent's own turn, have it start a Bash command with
run_in_background: true (e.g., sleep 25 && echo done), then immediately report
the assigned task_id in its final message without waiting on it, polling it, or
calling TaskOutput, and stop.
- Back in the root session, once notified that the sub-agent's own turn ended, call
TaskOutput(task_id=<the id the sub-agent reported>, block=false).
Expected: either the background task is discoverable and its eventual completion
is reported to root somehow, or at minimum TaskOutput returns a real status
(running/completed) for a task that verifiably exists.
Actual: TaskOutput returns No task found with ID: <id>. The task is invisible
to root immediately, well before the sleep 25 would even complete. TaskList shows
no trace of it either.
Why this matters
This breaks any multi-level agent architecture where an intermediate (non-root) agent
needs to delegate work asynchronously — e.g., an orchestrator dispatching a persistent
"lead" sub-agent, which itself dispatches further sub-agents for individual work
batches. If any of those non-root dispatches ever background something (intentionally,
or because a tool defaulted to backgrounding despite the caller not asking for it), the
work is silently lost with no way for anything in the session tree — including the
root — to recover it, retrieve its output, or even learn it's stuck.
We hit this as the apparent root cause of real, multi-hour hangs in an autonomous
overnight orchestration workflow (nested sub-agent backgrounds a test run, the
immediate parent waits for it forever, and even the top-level session has no way to
intervene since it can't see the orphaned task at all).
Notes
- A separate, possibly related observation: the harness's own boilerplate
task-notification text states "A task-notification fires each time this agent stops
with no live background children of its own" — in our test, the parent's own
completion notification fired promptly despite it having a live background Bash
child at that moment. Not sure if that's expected behavior for raw Bash children
specifically (as opposed to nested agent children), but flagging it as a possible
related inconsistency.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Confirming this also happens with a nested
Agentdispatch, not just a backgroundedBashcall — the exact case this report's own "Notes" section flagged as unconfirmed ("likely also applies to a nested Agent/Task dispatch"). Second independent occurrence, different repo/session from the original report.What happened:
git log/git branch -amuch later, because a status check on an unrelated ticket surprised me by pointing at unmerged work that should have been done long ago.Why this is worth tracking here rather than as a separate report: same root symptom (a background/async unit of work spawned by a non-root agent becomes invisible to root once the spawning agent's own turn ends), just triggered via the nested-
Agentpath this issue already predicted rather than rawBash. Two separate repos and sessions have now independently hit variants of this same class of bug, which suggests it's a structural gap in how completion notifications propagate through more than one level of agent nesting, not an edge case specific to either report's exact repro.Practical impact: I've had to adopt a defensive habit of periodically re-checking git state / task status directly rather than trusting that "no notification" means "no news" — which defeats a lot of the point of the async notification system for multi-level agent dispatch.
One more data point on the above: this second occurrence was on Claude Code 2.1.215, versus 2.1.208 for the original report — so this isn't specific to one version; it's reproduced across at least two point releases.
Confirming this pattern across two codebases, and adding one observation that may help narrow the root cause.
The common thread across the reports here: the task handle is scoped to the session that spawned it. When a sub-agent dispatches a background task and its own turn ends (whether it completes normally or hits a limit), the task's TaskStop/TaskOutput routing goes with it. The parent session has no forwarding address.
A few things that might help the Anthropic team reproduce this:
For context: we've been building supervisor logic for multi-agent Claude Code workflows (tracking process groups across session boundaries, killing orphaned workers when the parent exits) and the pattern you're describing is the most expensive failure mode we've hit. The fix that worked for us was registering the full process group at spawn time and treating session exit as a kill signal for any descendants that hadn't already completed -- but that only works when you own the orchestration layer. When the sub-agent itself spawns the background task, there's no external hook to catch the orphan.
Happy to share more specifics on the session boundary behavior we've observed if it helps.