general-purpose subagents recursively spawn: 3 requested → 24 ran, 80% of tokens wasted

Status Open
Maintainer reply None cached
Activity 0 comments · opened Jul 30, 2026

What happened

I asked Claude Code to run 3 research subagents (subagent_type: "general-purpose").
24 agents ended up running. Only 4 ever returned a result to the main assistant.
The remaining 20 produced output nothing consumed. This exhausted a monthly spend limit in
roughly 20 minutes.

| | agents | tokens | cache reads |
|---|---|---|---|
| results actually received | 4 | ~172k | 11.3M |
| results never received | 20 | ~725k | 61.7M |
| total | 24 | 897k | 73.0M |
| waste | | 80.8% | 84.6% |

Cache reads dominate. Each spawned subagent re-reads the inherited conversation context, so
cost scales with (agent count x context size) rather than with useful work. In a long session
a single fan-out is disproportionately expensive.

Mechanism

  1. general-purpose is declared with Tools: *, which includes the Agent tool. A research

agent can therefore recursively spawn its own subagents — and did.

  1. Having spawned children, the agent had no primitive to await them, so it **polled with shell

sleeps**, spawning a fresh shell roughly every 30 seconds:
``
eval 'sleep 200; echo done'
eval 'sleep 240; echo done'
eval 'until grep -q '"type":"result"' <path>/agent-<id>.jsonl; do sleep 15; done; echo BOTH_DONE'
``
Peak: 10 concurrent polling shells under the main process.

  1. TaskStop on the parent did not reap these shells — they had to be killed by PPID.

Grandchild agents kept running and trickled results back for ~20 minutes afterwards,
including one that failed with the spend-limit error.

  1. Duplicated work: the main assistant had already computed a 30-year index drawdown table

directly via API before delegating. The spawned agent independently re-downloaded the same
series and recomputed identical statistics.

Why it is hard to catch in time

  • TaskList returned "No tasks found" the entire time. Spawned subagents never appeared there.
  • The only reliable signal was OS-level: ps -eo ppid | awk '$1==<claude pid>' | wc -l.
  • The user noticed first, from the client-side agent count. The assistant did not.

Expected

Delegating 3 research tasks should run approximately 3 agents, and their count should be
visible through the task tools.

Suggested mitigations

  • Don't grant the Agent tool to general-purpose by default, or cap recursion depth at 1.
  • Enforce a per-turn / per-tree spawn budget, surfaced to the model as it approaches the cap.
  • Give subagents a real await primitive so sleep polling is never the best available option.
  • Make TaskStop reap the whole subtree, including descendant agents.
  • Surface spawned subagents in TaskList so the count is visible without ps.

Workaround

Defining a custom agent with an explicit tool list that omits Agent stops the recursion:

---
name: researcher
description: Web/document research. Cannot spawn subagents.
tools: WebSearch, WebFetch, Read, Grep, Glob, Bash
---

Prompt-level instructions alone were not sufficient — the tool list is the actual control.

Environment

  • Claude Code (remote-control mode), Linux 6.8.0, 8 cores
  • Model: Opus

View original on GitHub ↗