In-process subagents are never re-invoked when their own run_in_background Bash / Monitor task completes

Status Open
Reported on v2.1.238
Maintainer reply None cached
Activity 0 comments · opened Aug 21, 2026

Version: 2.1.238 (also reproduced from a 2.1.227 transcript). Linux, native binary, interactive session.

Summary

When an in-process subagent (spawned with the Agent tool, taskKind: in_process_teammate) launches a Bash command with run_in_background: true (or a Monitor) and then ends its turn, the completion notification is never delivered to that subagent. It is enqueued into the lead session's command queue and then removed at dequeue without being delivered to anyone. The subagent stays idle indefinitely; a manual SendMessage from the lead resumes it instantly.

The Bash tool description promises the opposite ("keeps running across turns and re-invokes you when it exits"), and that promise holds for the main session. Inside a subagent it silently does not.

Reproduction (≈2 min)

  1. In an interactive session, spawn an agent:

``
Agent({ subagent_type: "build", name: "bg-repro", prompt:

  1. Run with Bash, run_in_background: true: sleep 100; echo REPRO_DONE; exit 0
  2. Reply "LAUNCHED <task-id>" and end your turn. Do not poll, do not use Monitor, do not sleep in the foreground.
  3. When you are notified that the command completed, write /tmp/DONE.md and reply "WROTE DONE.md".` })

```

  1. The lead receives idle_notification for bg-repro within seconds. The task exits at t≈100 s ([exited with code 0] in its .output file).
  2. /tmp/DONE.md never appears. The agent's transcript (<session>/subagents/agent-*.jsonl) ends at "LAUNCHED".
  3. SendMessage({to: "bg-repro", message: "your command finished"}) → DONE.md appears in ~5 s.

Evidence

Main-session transcript (<session-id>.jsonl) for the repro above — the completion is enqueued in the lead's queue, carrying the subagent's tool-use-id:

{"type":"queue-operation","operation":"enqueue","timestamp":"2026-08-21T01:19:42.607Z","sessionId":"c2d04765-…","content":"<task-notification>\n<task-id>btq2dsynu</task-id>\n<tool-use-id>toolu_0194Yn3Zw2FJEhSxjPbaRgpj</tool-use-id>\n<output-file>…/tasks/btq2dsynu.output</output-file>\n<status>completed</status>\n<summary>Background command \"repro sleep\" completed (exit code 0)</summary>\n</task-notification>"}

toolu_0194Yn3Zw2FJEhSxjPbaRgpj is the Bash call in subagents/agent-abg-repro-*.jsonl. No task-notification ever appears in that agent transcript, and no user-role message with that task-id ever appears in the lead transcript either — the record is later removed ("operation":"remove") in a batch.

Across a full 8-hour session on 2.1.227 (two Opus teammates running long sweeps), classifying every queued <task-notification> by who launched the task:

| owner of the task | enqueued into lead queue | delivered as a user message to anyone |
|---|---|---|
| lead session | 3 | 3 |
| subagent (Bash run_in_background + Monitor) | 32 | 0 |

Monitor events fail the same way (<summary>Monitor event: …</summary><event>…</event> records enqueued to the lead, never delivered). The agent transcript has 0 task-notification lines; the lead's has 128 (all its own).

Expected

The completion re-invokes the subagent that owns the task, the same way it re-invokes the main session — or, at minimum, the lead receives it so it can relay.

Impact

Any orchestration where a teammate backgrounds long compute (model sweeps, builds, benchmarks) degrades from autonomous to "the lead polls ps and hand-nudges". The idle_notification the lead receives is indistinguishable between "done" and "stalled waiting on its own task".

Workaround that works

Append a message directly to the teammate's inbox file ~/.claude/teams/<team>/inboxes/<name>.json (same shape SendMessage writes: {from,text,summary,timestamp,msgV,msg_id,type:"message",read:false}); the harness polls it and the idle agent resumes within a few seconds. I run a small per-session daemon (spawned from a SubagentStart hook) that tails the lead transcript for the orphaned queue-operation enqueue record, maps the task-id to the owning agent via subagents/*.meta.json, and writes that message. That confirms the wake path exists — only the routing of the completion event is missing.

View original on GitHub ↗