Summary
When a team agent (teammate) terminates via the shutdown_request → shutdown_approved protocol, the SubagentStop hook does not fire. This leaves external systems that track agent lifecycle via hooks with phantom agent counts that never decrement.
Reproduction
- Enable agent teams:
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- Register a
SubagentStop hook that logs to a JSONL file (or any observable side effect)
- Create a team and spawn teammates
- Send
shutdown_request to teammates
- Observe that
shutdown_approved is received, teammate_terminated system message appears, but SubagentStop hook never fires
Evidence
JSONL event log showing 6 team agents with agent.start events and no matching agent.stop:
# Team 1: resilience-architect and test-architect
{"ts":"2026-04-08T01:54:13Z","event":"agent.start","agent_id":"aacd2d977d5b10367","agent_type":"resilience-architect"}
{"ts":"2026-04-08T01:54:26Z","event":"agent.start","agent_id":"ad43c61987f3d60bd","agent_type":"test-architect"}
# Both received shutdown_approved — no agent.stop events ever appeared
# Team 2: three review agents
{"ts":"2026-04-08T02:09:22Z","event":"agent.start","agent_id":"a712f607506a003a7","agent_type":"reuse-reviewer"}
{"ts":"2026-04-08T02:09:22Z","event":"agent.start","agent_id":"a912c5cfbfc5e9ae4","agent_type":"quality-reviewer"}
{"ts":"2026-04-08T02:09:23Z","event":"agent.start","agent_id":"ab21e0518d3daf119","agent_type":"efficiency-reviewer"}
# All three received shutdown_approved — no agent.stop events
Meanwhile, regular subagents (non-team) and team agents that go through idle→wake cycles (via SendMessage) DO correctly fire SubagentStop. The issue is specifically the shutdown_request → shutdown_approved termination path.
Expected behavior
SubagentStop should fire for every agent that triggered SubagentStart, regardless of how the agent terminates (normal completion, shutdown protocol, or error).
Impact
Any plugin or hook that tracks agent count via SubagentStart/SubagentStop pairs will show permanently inflated counts after team sessions. This affects resource management tools that gate behavior on active agent count.
Environment
- Claude Code v2.1.94
- macOS Darwin 25.3.0
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
Context
Discovered while building coolant, a resource management plugin that tracks agent lifecycle via hooks to drive a thermal monitoring dashboard. The breathing agent icons stay lit indefinitely after team agent shutdown because the stop events never arrive.
Summary
When a team agent (teammate) terminates via the
shutdown_request→shutdown_approvedprotocol, theSubagentStophook does not fire. This leaves external systems that track agent lifecycle via hooks with phantom agent counts that never decrement.Reproduction
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1SubagentStophook that logs to a JSONL file (or any observable side effect)shutdown_requestto teammatesshutdown_approvedis received,teammate_terminatedsystem message appears, butSubagentStophook never firesEvidence
JSONL event log showing 6 team agents with
agent.startevents and no matchingagent.stop:Meanwhile, regular subagents (non-team) and team agents that go through idle→wake cycles (via
SendMessage) DO correctly fireSubagentStop. The issue is specifically theshutdown_request→shutdown_approvedtermination path.Expected behavior
SubagentStopshould fire for every agent that triggeredSubagentStart, regardless of how the agent terminates (normal completion, shutdown protocol, or error).Impact
Any plugin or hook that tracks agent count via
SubagentStart/SubagentStoppairs will show permanently inflated counts after team sessions. This affects resource management tools that gate behavior on active agent count.Environment
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1Context
Discovered while building coolant, a resource management plugin that tracks agent lifecycle via hooks to drive a thermal monitoring dashboard. The breathing agent icons stay lit indefinitely after team agent shutdown because the stop events never arrive.