Subagent (Task tool) re-invoked ~9× after finishing, with no new input — result becomes a trailing closer instead of the deliverable
Environment: Claude Code CLI (version visible in session jsonl). Custom subagents + plugins present; see caveat.
Summary
When a subagent is dispatched via the Task tool, it produces its full deliverable in an early turn, then is re-invoked ~9 times consecutively with no new user input. Each re-invocation the model emits a short throwaway closing remark ("Acknowledged.", "Session complete.", "Closing."). The harness returns the last assistant text block as the subagent's result, so the orchestrator receives a useless closer instead of the deliverable.
Evidence (from subagent transcript jsonl)
- Deliverable appears intact and verbose in an early turn (e.g. a 6746-char report).
- Then 8–9 consecutive
type:assistantturns follow, several withstop_reason:end_turn, with zero user/tool turns between them. - Each is a distinct real generation: distinct
requestIdper turn. - The re-invocations carry
input_tokens:0(fully cached; nothing new is injected) — confirming the harness re-queries with no added content. - Deterministic: always ~9 turns over ~30s, for any task including a trivial "return the string FOO".
What was ruled out
- Hooks: all SubagentStop hooks were neutralized to no-op simultaneously and the loop persisted (still 9 turns). Stop hooks were instrumented and confirmed not to fire for subagent stops. No hook returns
decision:blockunder any condition (tested withstop_hook_activeboth true and false). - Reasoning effort: dispatching the same trivial task at
effort:lowvseffort:highproduced identical 9-turn loops — rules out a thinking-budget-drain explanation.
Impact
Subagent text returns are unreliable: the orchestrator receives a trailing acknowledgment instead of the work product. Workaround on our side = read the deliverable directly from the subagent transcript (subagents/agent-<id>.jsonl), never trusting the returned text.
Caveat (honest scope)
Observed in an environment with plugins installed. We neutralized all Stop/SubagentStop hooks and confirmed Stop hooks do not fire for subagents, which points to harness-native behavior — but we did not reproduce on a fully vanilla Claude Code install. A vanilla repro would confirm. Transcripts available on request.
Ask
Is this expected? What termination condition drives the post-end_turn re-invocation of a subagent, and can the harness return the substantive turn (or the first end_turn) instead of the last closer?