[BUG] Agent Teams: background sub-agents idle for 30+ minutes after work completion; SendMessage ping required to wake them and trigger final report
Summary
Background sub-agents spawned via the Agent tool with run_in_background: true in Agent Teams mode (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, in-process mode on Windows) consistently sit idle 30+ minutes after their last meaningful tool call (verified via downstream artifacts like git commits) before submitting their final report and triggering a <task-notification> to the parent session. Sending SendMessage to the stuck agent reliably wakes it within seconds, after which it submits its closeout normally.
The completion-notification path that does exist is unreliable on Windows — extending the symptom set previously reported in #21048 (closed without fix, locked) and consistent with the architectural root-cause analyses in #24108 (closed; the reporter's "polling-only-between-turns" hypothesis) and #26426 (closed; InboxPoller is a React UI hook tied to TUI rendering).
This issue is filed fresh because all three prior issues are closed and locked.
Environment
- OS: Windows 11 Pro 10.0.26200
- Claude Code: v2.1.131 (running via VS Code native extension)
- Node: v22.13.1
- Mode:
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, in-process teammates (Windows-required per docs) - Platform per system prompt:
win32
Reproducer
- Spawn one or more sub-agents via
Agent({run_in_background: true, ...})in agent-teams mode. - Sub-agents do real work (tool calls, file edits, commits, tests).
- After the sub-agent's last meaningful tool call, observe: parent receives no
<task-notification>and the sub-agent does not submit its final report. - Send
SendMessage({to: \"<agent-name>\", message: \"...\"})from the parent. - Within seconds, the sub-agent submits its report and the
<task-notification>arrives.
Concrete evidence from a real session
Three consecutive sub-agents in the same session, all on Windows in-process mode:
| Agent | Real work span (git commit cadence) | Reported runtime | Idle gap |
|---|---|---|---|
| api-dev (Sonnet, impl) | 22:11–22:59 (~48 min) | 78 min | ~30 min |
| test-author (Sonnet, tests) | 22:20–22:59 (~38 min) | 86 min | ~48 min |
| api-dev round 2 (Sonnet) | last commit 23:56 yesterday; submission still pending after multiple SendMessage pings into the next day | not yet reported | ongoing |
A fourth agent in the same session (auditor, Opus, source review only — no commits) ran 4 minutes with no idle gap. The differentiating factor is that its last action was a tool call writing the report, with no post-completion idle state.
The \"submit IMMEDIATELY after final pytest run, do not idle\" instruction was added explicitly to the briefs after the first two occurrences and did NOT prevent the bug — consistent with #24108's analysis that no prompt can force earlier polling because the polling loop isn't active in the post-completion state.
Why this matters operationally
- Wall-clock cost: ~30–48 minutes of dead time per parallel-teammate round, multiplied by the number of teammates.
- Cost overhead: the parent session pays for token streaming during idle periods if it monitors; if it doesn't monitor, the user has no signal that work has completed.
- No documented monitoring path:
TaskOutputis deprecated forlocal_agenttasks (its own docstring warns that reading the output file overflows context). WithoutSendMessagepolling, there's no way for the parent to detect the post-completion idle state. - Architectural fix understood, not shipped: #24108 and #26426 reporters both correctly diagnosed the polling-only-between-turns / React-UI-hook-tied root causes. The pattern of bot auto-close on inactivity (see #21048's lock) prevents accumulation of evidence.
Ask
One of the following, in priority order:
- A non-UI inbox polling mechanism for non-interactive sub-agents (#26426's suggested fix) so the polling loop is active in idle states.
- A
TaskCompleteNotificationinjection that fires when a sub-agent's work-done sentinel is detected (similar to the Bash-completion notification path that #21048 already partially implements, but reliably on Windows). - At minimum: a documented monitoring API (e.g., a
Statustool surface) that lets the parent agent distinguish idle-but-alive from dead without reading the JSONL transcript — addresses #24246 / #29271.
If 1 or 2 are infeasible short-term, document the recommended SendMessage polling cadence in the Agent Teams docs so users don't have to discover it through GitHub issue archaeology.
Workaround in use
Parent agent runs a ScheduleWakeup-driven 4-minute polling loop after spawning each background teammate, sending SendMessage pings until the teammate submits. 4 minutes balances cache-warm boundary (per ScheduleWakeup's docstring) against bounded idle gaps. The SendMessage ping is correctly delivered on tool-call boundaries during active work, so it's non-disruptive.
Cross-references
- #21048 (closed and locked; Windows background-task completion notification)
- #24108 (closed; tmux split-pane idle, reporter's polling-between-turns hypothesis)
- #26426 (closed; non-interactive
InboxPollerReact-UI-hook root cause) - #24246 (idle-vs-dead state ambiguity)
- #29271 (lead can't distinguish idle from dead)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗