A pre-spawn decision layer for Claude Code's Agent tool: given a delegation request, it picks the cheapest model, tool allowlist, turn budget, and isolation mode that still meets the task's success bar instead of defaulting to a capable model with full tool access for every spawn.
See subagent-spawn-optimizer-spec.md for
the full problem statement and design.
| Path | Role |
|---|---|
.claude/spawn-policy.md |
The data: task buckets, model-fit table, tool allowlists, budget bands. Edit this to tune defaults; no code changes needed. |
.claude/skills/spawn-optimizer/SKILL.md |
The procedure: consulted before every Agent call. Classifies the task, looks up the bucket's defaults, and logs the outcome. |
.claude/agents/spawn-*.md |
Bucket-specific subagent types (spawn-read-lookup, spawn-review, spawn-write, spawn-verify) with tool allowlists baked into the agent definition, not just advisory. |
.claude/hooks/spawn-policy-check.sh |
A PreToolUse hook (wired via .claude/settings.json) that hard-enforces two of the policy's rules (see below). |
.claude/scripts/spawn-log-append.sh |
Appends one outcome record to .claude/spawn-log.jsonl after a spawn completes. |
.claude/scripts/spawn-log-report.sh |
Reads .claude/spawn-log.jsonl and prints the per-bucket summary table below. |
Two rules are enforced by spawn-policy-check.sh, not just written down:
isolation: worktreeon a read-only subagent type is denied: it's pure overhead when nothing gets mutated.- A full-tool-access type (
general-purpose/claude) used on a prompt that reads like a mechanical read-only lookup triggers an ask, a nudge to usespawn-read-lookupinstead.
Everything else (full bucket classification, model-tier fit for the other buckets, budget bands) is advisory: followed via the skill's procedure, not hard-blocked, since keyword-based classification into all 5 buckets was judged too fragile to hard-enforce without causing false-positive friction.
Every spawn appends one JSON line to .claude/spawn-log.jsonl:
{"ts":"2026-07-25T13:34:31Z","bucket":"code-review","subagent_type":"spawn-review","model":"opus","tokens":41200,"turns_used":11,"escalated":true,"overridden":false,"outcome":"success"}Run .claude/scripts/spawn-log-report.sh to get a per-bucket summary:
| Bucket | Spawns | Escalation rate | Override rate | Avg tokens | Avg turns |
|---|---|---|---|---|---|
| code-review | 1 | 1/1 (100%) | 0/1 (0%) | 41200 | 11 |
- Bucket: which of the 5 task buckets the spawn was classified into (read-only lookup, investigation, code review, write/edit, verification).
- Spawns: how many logged spawns fall in this bucket. Treat rates below as noisy until this is at least ~5; a 100% rate on 1 spawn is one data point, not a pattern.
- Escalation rate: fraction of this bucket's spawns where the model used
was a tier above the bucket's stated default (e.g. Sonnet default, Opus
used). High and sustained (roughly >60% over ≥5 spawns) means the
policy's default model for that bucket is miscalibrated: the fix is to
raise the default in
spawn-policy.md, not to keep escalating case by case. - Override rate: fraction where the subagent_type itself deviated from
the bucket's recommended one (e.g.
general-purposeused instead ofspawn-read-lookup). A high override rate points at a different problem than escalation rate: it means the bucket classification is missing cases, not that the model tier is wrong. - Avg tokens: mean
subagent_tokensper spawn in this bucket, pulled from the completion notification (not from theSubagentStophook, which has no usage field). This is the primary cost signal the whole policy exists to bring down over time. - Avg turns: mean tool-call count per spawn. A bucket whose avg turns
keeps creeping toward its
max_turnsbudget band (seespawn-policy.md§4) is a sign the budget is too tight for what that bucket actually needs, not that the subagent is behaving badly.
Rows with only 1–2 spawns (like the table above) are illustrative, not yet statistically meaningful; the report is only useful for spotting real patterns once each bucket has accumulated a handful of real spawns.