You spawn a subagent with the Task tool. The subagent runs for a few minutes, prints its log messages, finishes — and then the main Claude Code session either shows a totally generic summary, claims the subagent “is still running,” or skips the result entirely and moves on. The architecture under the hood is: the subagent runs in an isolated context, then its final assistant message is the only thing relayed back to the parent. If that final message is missing, oversized, or buried under tool noise, the parent has nothing useful to consume. The fix is almost always about how the subagent ends its turn, not about whether it did the work.
Common causes
Ordered by hit rate, highest first.
1. Subagent ended with a tool call instead of a final assistant message
If the subagent’s last action is a Write or Bash call and it never produces a closing assistant text message, the parent receives an empty or fragmentary result. Subagents must end with a real text reply.
How to judge: In the transcript JSON for the subagent, look at the last entry. If it is tool_use or tool_result rather than assistant.text, that is the bug.
2. Final message exceeded the relay buffer
Subagent results are passed back as a single message. Extremely long output (10k+ tokens) can be truncated or rejected silently, so the parent sees only a header or nothing.
How to judge: Check the subagent’s last message length. If it is dumping entire file contents instead of summarizing, it is probably oversize.
3. Subagent crashed or hit usage limit, no result emitted
If the subagent ran out of tokens, hit a rate limit, or threw an internal error, it can exit without ever producing a final message. The parent often interprets the missing return as “still running.”
How to judge: Look at the subagent’s last few entries for an error, a usage_limit_reached, or a max_tokens truncation flag.
4. The parent’s prompt did not tell the subagent how to report back
Subagents follow the instructions they were given. If you said “do X” but never said “return the result as Y,” they may print to logs only, assuming the parent will read those — which it cannot.
How to judge: Re-read the Task description you wrote. Does it say “reply with the file path and a one-paragraph summary”? If not, that is the gap.
5. Subagent wrote results to disk but never mentioned the path
Many subagents save large output to a file and finish with “done.” The parent has no idea where to read. From the parent’s perspective the result is “done” — useless.
How to judge: Ask the parent “what file did the subagent create?” If it cannot answer, the subagent forgot to include the path in its final message.
6. Stale parent state — the parent moved on before the subagent finished
In rare cases (especially with interactive Ctrl-C) the parent advances its own turn before the subagent posts back. The result lands in the transcript but is never consumed by the next assistant turn.
How to judge: Inspect the message ordering. If a parent-side assistant message appears between the subagent dispatch and the subagent return, you hit this race.
Before you start
- Decide whether you can re-run the subagent or whether the work is too expensive to repeat.
- Save the subagent transcript (Claude Code keeps it under
~/.claude/projects/...) before it gets overwritten. - Note exact wording of the Task prompt; you will likely rewrite it.
- Have a small reproduction task ready for testing your fix.
Information to collect
- Claude Code version:
claude --version. - The full Task prompt you used to spawn the subagent.
- The subagent transcript JSON from
~/.claude/projects/<project>/. - The parent’s response after the subagent supposedly finished.
- Any files the subagent created (paths and sizes).
- Token usage shown at session end, if available.
Step-by-step fix
Step 1: Locate the subagent transcript
ls -lt ~/.claude/projects/*/sessions/ | head -10
Open the most recent session JSON and find the subagent block. The last entry tells you exactly how it ended.
Step 2: Confirm the final message exists
A healthy subagent ends like:
{ "role": "assistant", "content": [ { "type": "text", "text": "Done. Wrote /tmp/report.md ..." } ] }
If the last entry is tool_result with no following assistant text, the subagent never produced a final reply.
Step 3: Rewrite the Task prompt to demand a structured reply
Instead of “investigate X,” say:
Investigate X. When done, reply with exactly:
- File paths you created or modified (absolute)
- A 3-bullet summary of findings
- Any open questions
Do not end on a tool call.
Explicit format requests reduce relay failures dramatically.
Step 4: Cap the subagent output size
Tell the subagent to summarize rather than dump:
If the result is longer than ~500 words, write the full
output to a file and reply with the path plus a short summary.
This avoids the relay-buffer truncation case.
Step 5: Re-run with a small reproduction
Spawn the same subagent with a trivial task (“list 3 files under src/”). If the relay works for the small case, the original failure was size or format. If it fails even small, suspect crashes or usage limits.
Step 6: Inspect for usage-limit or token-cap errors
Search the subagent transcript for usage_limit, max_tokens, or error. If found, reduce the subagent’s scope or split the task across two subagents.
Step 7: For race conditions, rerun without Ctrl-C interrupts
Avoid pressing Ctrl-C while a subagent is in flight; let it finish on its own. If you must cancel, cancel the whole turn and start fresh rather than half-interrupting.
Verify
- The parent’s next assistant message references the subagent’s actual findings, not a generic “done.”
- Files the subagent wrote are mentioned by path in the parent’s response.
- A repeat run on the same prompt produces a consistently relayed result.
- The subagent transcript ends in an assistant text message, not a tool call.
Long-term prevention
- Keep a snippet for Task prompts that includes “reply with structured summary, do not end on a tool call.”
- Use file-based handoff for any subagent producing more than a few hundred lines of output.
- Set hard scope limits on subagent work; one subagent, one well-defined task.
- Periodically review transcripts to spot recurring relay failures and update your prompt template.
- Prefer multiple small subagents over one long-running one when the scope grows.
Common pitfalls
- Assuming the parent can “see” the subagent’s intermediate logs. It cannot; only the final message is relayed.
- Letting the subagent dump entire file contents back instead of summarizing.
- Cancelling halfway with Ctrl-C and then expecting the parent to recover gracefully.
- Forgetting that the subagent runs in an isolated context, so it cannot reference parent variables or files unless you tell it.
- Spawning a subagent for a task that does not actually benefit from isolation; sometimes inline is better.
FAQ
- Why does my parent say the subagent is still running when it finished? The final message was missing or empty. The parent has no signal that work is done, so it waits or guesses.
- Can the parent read the subagent’s tool calls? No, only the closing assistant text message is relayed. Anything else is discarded.
- What is the size limit on relayed messages? Practically a few thousand tokens. Beyond that, summarize or write to disk.
- Does this affect plugin-defined agents too? Yes — any subagent spawned via the Task tool has the same relay contract.
- Should I always demand a structured reply? Yes. A structured reply is the single biggest reliability improvement.
- How do I see the subagent transcript? It is saved under
~/.claude/projects/<project>/sessions/. Open the latest JSON.