Background Bash task completion never resumes in-process subagents — they idle forever while finished work sits on disk

Status Open
Reported on v2.1.214
Maintainer reply None cached
Activity 5 comments · opened Jul 18, 2026

Summary

When a subagent spawned via the Agent tool (an in-process teammate / named background agent) starts a Bash tool call with run_in_background: true and then ends its turn to wait, the background task's completion never re-invokes that subagent. The main session gets background-task completion notifications; in-process subagents do not. The subagent sits idle (idleReason: "available") forever while its finished work sits unread on disk.

Repro shape

  1. Main session spawns a named agent via the Agent tool.
  2. That agent runs Bash with {command: "<long-running command>", run_in_background: true}.
  3. The agent ends its turn, expecting to be woken on completion (the Bash tool description tells the main loop it will be re-invoked when a background task exits).
  4. The background command completes minutes later — the task .output file is written, the process exits cleanly.
  5. The agent is never resumed. An inbound SendMessage from the parent does resume it (the wake path itself works), but no wake ever fires on task completion.

Evidence

Two independent occurrences on 2026-07-18, Claude Code 2.1.214, macOS (Darwin 25.5.0), same shape, different agents:

  • Agent A: launched a background Bash task at 01:38Z, sent one status message at 01:39Z, idle since. The background command completed ~01:56Z (harness task .output file under /private/tmp/claude-<uid>/…/tasks/ frozen at completion; the command's on-disk results fully written). No resume ever fired; the subagent transcript simply ends after the status message.
  • Agent B: same pattern at 01:53Z — this agent even backgrounded a pure blocking wait command specifically to be woken on completion. The command completed ~02:10Z. No resume.

In both subagent transcripts the last event is a clean text turn; the parent transcript shows only idle_notification from each agent afterward. Full transcripts available on request.

Expected

Either background task completion re-invokes the owning subagent (as it does the main session), or the harness should make the asymmetry explicit — e.g., reject/warn on run_in_background in subagent context — so agents don't silently deadlock on a notification that structurally cannot arrive.

Impact

Any delegation pattern where a subagent backgrounds a long command and waits deadlocks silently: the work completes, the results sit on disk, and the agent never reports. This presents to the operator as "my agents are frozen" even though nothing is running or stuck. (Related in spirit to #75559 — subagent context/tool-surface gaps.)

View original on GitHub ↗

4 Comments

kcarriedo · 1 month ago

This is a significant gap for any orchestration pattern where agents are expected to self-drive after completing background work -- essentially every "fire and forget, check in when done" workflow breaks silently here.

The asymmetry you describe (parent gets completion notifications, in-process subagents do not) suggests the wake-on-completion path is only wired to the main session's event loop and not to the per-agent event loop. Which means the problem isn't the wake mechanism itself -- it works for the parent -- it's that named agents don't get a copy of the notification.

A visible symptom worth checking: does the subagent's idleReason stay as "available" even after the background task file is written? If so, that's strong evidence the event was dispatched to the wrong listener scope. The agent is ready to run but the completion event that should trigger its next turn went somewhere else.

Tracking this for Claudiverse (fleet visibility tooling for multi-agent Claude Code sessions). Background task completion reliability is load-bearing for the class of workflows we're building on top of the agent system. Happy to share structured repro transcripts if useful.

yasyf · 1 month ago

Consolidated evidence plus a working external workaround, for anyone hitting this and for prioritization.

Confirmed scope. This is a scheduler gap, not notification plumbing: an in-process subagent has no wake inlet at all — it advances only on a synchronous tool-call return or an inbound SendMessage. The same missing inlet surfaces independently in #77578, #76594, #76681, #75043, #68749, #77300, #78434, and #20754, and is framed as a feature request in #76203 ("a subagent has no interrupt inlet"). Two sharp edges from our repros: Monitor arms inside a subagent but its wake is dropped, not queued (#77300 has a timestamped repro), while top-level Monitor and background-Bash wakes deliver fine — the asymmetry is subagents only.

Working workaround, verified live on 2.1.214. We rebuilt our codex-dispatch plugin around an external steering plane (a per-user daemon with a per-agent directive mailbox) and confirmed the harness already exposes enough seams to deliver an external wake, through four rungs:

  1. Park (primary): the subagent calls a long-poll MCP tool; progress notifications hold the call open past idle timers; the external completion releases the park, returning as the child's own tool result — no priming needed.
  2. PreToolUse additionalContext injection on the child's next tool call.
  3. A SubagentStop stop-gate that drains pending directives at stop.
  4. A parent-side SendMessage relay for a child that finished before delivery — children must be primed by a greeting directive first, or they refuse the relayed wake as prompt injection.

Rung 1 fully substitutes for the missing background-completion wake: the child dispatches async, parks, and is woken on completion with its result on disk. So the capability is schedulable today — it just takes a daemon, an MCP server, and a hook pack to reach what a first-class wake inlet would give directly.

searayca · 1 month ago

**Another repro (macOS, Claude Code, Opus 4.8) — a subagent idles while its own background Bash task runs to completion**

Environment: Claude Code CLI, macOS (Darwin 25.5). A background subagent spawned via the Agent tool with run_in_background: true, which then launched a long-running (~5–10 min) background Bash task (a build → push → cloud-update pipeline). So the shape is nested: background subagent → background Bash task.

Observed sequence:

  1. Subagent starts the background Bash task and messages the parent "retrying now / in progress."
  2. Subagent immediately emits idle_notification { idleReason: "available" } — repeatedly — carrying a stale summary ("retrying now") that no longer reflects reality.
  3. The background Bash task keeps running and eventually completes successfully, but the subagent is never resumed and never posts the completion or results. The finished work sits done with no notification.
  4. The parent session can only learn the true state by independently polling external systems (querying the artifact registry / the deployed revision) — never from the subagent itself.

Impact: wasted wall-clock and actively misleading status. The parent repeatedly believed work was stalled or un-started when it had in fact progressed or finished. In our case the parent's out-of-band poll even crossed with the subagent's still-in-flight task, yielding contradictory status between the two.

Additive to the original report:

  • Reproduces specifically when the background task is a shell pipeline launched by a subagent (the nested case), not just a top-level Bash task.
  • The misleading element isn't only silence — it's stale idle_notification summaries emitted while the task is genuinely mid-run (looks related to #73647).
  • Related: #68922 (model asserting a background agent is done before the task-notification arrives).

What would fix the pain: resume/notify the spawning subagent when its background Bash task exits (success or failure), and don't emit idle_notifications whose summary describes an action that hasn't actually run yet.

IgorGanapolsky · 1 month ago

This is a resume-path bug with real cost: the subagent ends its turn waiting on background Bash, the work finishes on disk, and nothing wakes the teammate — so the main session either redoes the work or leaves half-finished state.

Pattern that has worked as a host-side guard until the runtime wires completion into the subagent mailbox:

  1. Treat run_in_background: true from an in-process subagent as unsupported unless the product documents a wakeup channel for that subagent id.
  2. If you must use it, the subagent should poll a concrete marker (exit file / task id) with a deadline, not go idle waiting for a notification that only the main session receives.
  3. On main-session idle, scan for orphaned background Bash results that no agent has acknowledged — those are free wins and also the audit trail for this bug.

The "finished work sits on disk while the agent idles forever" case is worse than a crash; it burns tokens on silence.

Showing cached comments. Read the full discussion on GitHub ↗