[BUG] Agent teams: Monitor events and background-task notifications never wake an idle teammate — dropped, not queued (only SendMessage wakes it)
[BUG] Agent teams: Monitor events and background-task notifications never wake an idle teammate — dropped, not queued (only SendMessage wakes it)
Environment
- Claude Code version: 2.1.206
- OS: macOS (darwin 25.3.0)
- Mode: interactive REPL, agent teams; teammates spawned via the Agent tool (named, background)
- Models: main session on claude-fable-5; teammates on haiku / sonnet (reproduces on both)
Summary
A teammate/subagent that has ended its turn (idle) is never re-invoked by:
Monitortool events firing on a background Bash task's stdout it armed earlier, nor- completion notifications of its own background Bash tasks (
run_in_background: trueprocess exiting).
The pending notification is also not injected when the teammate is later woken by a SendMessage — transcript inspection shows the Monitor event never enters the subagent's transcript at all while idle or at wake; at best it trickles in mid-turn after the agent is already active again (observed arriving only after the awake agent had manually tail'd the watched file). The only channel that wakes an idle teammate is a harness-native SendMessage.
The main session is not affected — its Monitor events re-invoke it between turns, as documented. The asymmetry is teammates/subagents only.
Practical impact: any teammate that relies on a Monitor-watched stream (inter-agent messaging, log watchers, dev-server supervision) silently stops processing the moment it idles. It looks alive (its background process keeps running and consuming) but reacts to nothing until a human or the lead notices the silence and pings it over SendMessage. In a real multi-agent session this produced repeated multi-ten-minute coordination gaps.
Reproduction
Setup: any long-running background process that emits lines on stdout. Ours was a file-tailing message CLI; a tail -f on a growing file should do.
- Main session spawns a named teammate via the Agent tool with these instructions:
- Start the long-running emitter via Bash
run_in_background: true(stdout only). - Arm
Monitoron that shell's stdout. - Confirm readiness via SendMessage, then end the turn (idle; no polling).
- On any wake: report exactly what woke it and whether the watched line was already in context.
- While the teammate is idle, cause a new line to appear on the watched stdout (we sent a message through the CLI; provable delivery — the line lands in the background task's output file on disk within ~1s).
- Wait. Nothing happens — we observed a 95s controlled gap and, in the wild, gaps of tens of minutes. The teammate transcript gains zero entries in this window.
- Send the teammate a
SendMessage. It wakes immediately. Its wake context contains only the SendMessage (+ housekeeping attachments) — no Monitor event, no watched-line content. - The teammate finds the line only by manually reading the task output file. In one run, its own Monitor then fired a late task-notification for that same line — after the manual read, mid-turn.
Variant: replace the stream+Monitor with a background process that exits when the line arrives (completion-notification path). Same result: process exited cleanly with the line printed while the teammate was idle; no wake (teammate confirmed: "task completion did not wake me; the content was not in my context — the task-notification system reminder appeared AFTER your teammate message woke me").
Timeline from a controlled run (UTC, 2026-07-13)
20:52:47 teammate arms Monitor on background stream (tool_use OK in transcript)
20:52:55 teammate ends turn -> idle
20:53:04 new line emitted on watched stdout (on disk at 20:53:05, verified)
... 95s: teammate transcript = ZERO entries ...
20:55:00 lead sends SendMessage nudge -> teammate wakes instantly
wake bundle: nudge + deferred-tools delta + skill listing. NO monitor event.
20:55:07 teammate manually tails the output file -> finds the line
20:55:1x teammate's own Monitor fires a LATE notification for that same line (post-read)
Subagent transcript (~/.claude/projects/<project>/<session>/subagents/agent-<name>-*.jsonl) confirms: between the idle boundary and the SendMessage there are no entries of any type.
Expected behavior
Either of:
- Monitor events / background-task completions re-invoke an idle teammate the same way they re-invoke the main session (preferred), or
- at minimum, pending Monitor/task notifications are injected into the teammate's context when it is next woken, instead of being dropped.
Prior art / related issues
- #39632 (closed, stale) — same mechanism class root-caused for headless main sessions: notification enqueued after the idle-poll loop exited;
queueChangedemission only re-triggersrun()forpriority="now". The REPL main session is immune because its store drains every emission. Our report is the teammate-scoped sibling of this race, still live on 2.1.206. - #76681 (open) — background-task notification enqueued but never delivered when the owning subagent already completed; closest analog for the task-exit variant.
- #69732, #69621, #66219 — same notification/teammate-lifecycle subsystem (misrouting, under-documentation, over-delivery).
- Changelog 2.1.183 "Fixed background tasks started by a teammate being killed when the teammate finishes a turn" — adjacent fix in the same subsystem; the wake side is still missing.
Workaround
Dual-channel protocol: keep payloads on a durable channel (file/cursor-based), and pair every send to a possibly-idle teammate with a SendMessage nudge; the woken teammate must actively drain the watched file because the missed notifications are never replayed. Works, but costs an orchestration round-trip per message and only helps senders who know the recipient might be idle.