Filter the list, or split the agent
Lesson 5 of 5 in Tool Selection at Scale: Forty Tools, One Context.
Everything so far is one family of answers: keep one agent, and control what it sees. There is a second family: stop having one agent. Both are legitimate, they cost very different amounts, and the failure mode is picking the expensive one first — or, more common, quietly stacking all of them until nobody can explain why a tool was not called.
Here is the ladder, cheapest and most reversible at the base.
The tool-scale ladder — climb only as far as your catalog forces you
- Consolidate — free, and usually sufficient
Merge overlapping tools, delete dead ones, reshape endpoint-mirrors into task-shaped tools. Most “we have too many tools” problems are really “we have too many similar tools”, and this rung fixes those permanently rather than hiding them. It is also the only rung that makes the model’s job easier rather than merely smaller. Do this first, always — and note that a catalog you have not pruned in a year will lose 20–30% of its entries to this step alone.
- Task loadouts in code — an afternoon, fully deterministic
A hand-written map from task (or surface, or run phase) to tool list. Reviewable in a pull request, free at runtime, incapable of a recall miss, and trivially explainable in an incident: this surface exposes these nine tools. This rung solves the large majority of real catalogs. Its ceiling is maintenance — when the map changes weekly because other teams own the servers, you have outgrown it.
- Progressive disclosure — context cost stops growing with the catalog
Expose a small stable set plus two meta-tools: one that lists capabilities in a domain, one that invokes by name. Context cost becomes roughly constant in catalog size, and the model discovers what it needs. The costs are real: an extra round trip before any work happens, weaker argument validation at the outer boundary because the invoke tool takes a name and a payload, and models that under-use discovery — guessing a plausible tool name instead of listing first. Prompt for it explicitly, and make a failed invoke return the available names rather than a bare error.
- Retrieval-based selection — a learned component in your control path
Everything from lesson two: worth it when the catalog is too large or too volatile to hand-maintain. You are now operating a retriever — recall measured on a labeled set, a floor set that cannot be filtered away, the exposed set logged on every call, and a monthly never-retrieved audit. Adopt it for that reason, not because the catalog feels big.
- Split by toolset — buys clean contexts, pays the multi-agent tax
Give each coherent toolset its own specialist — a subagent or a separate agent behind a handoff — each with a small, stable, cacheable loadout and its own evals. This is the only rung that fixes the context problem structurally rather than by filtering. It is also the only rung that adds coordination cost, information loss at the boundary, and multi-agent failure modes. Split when the toolsets have genuinely different jobs, contexts, and owners — not merely because there are many tools.
Which rung does your catalog actually need?
Interactive decision tree — outcomes:
- Prune first — you are not at scale yet, you are at sprawl
Every mechanism above this rung will faithfully preserve your duplicates and dead tools while adding a failure mode. Merge the overlaps, delete the never-called, reshape the endpoint mirrors. Re-run this tree afterwards; many catalogs never need the next rung.
- Hand-written task loadouts — stop here
Deterministic, reviewable, free, and immune to recall misses. Add a floor set (escalate/ask_human) that no filter can remove, log the exposed set anyway so future bugs are falsifiable, and revisit only when maintaining the map becomes the bottleneck.
- Progressive disclosure over the tail
Keep the stable core always present; put the tail behind list-then-invoke. Budget for the extra round trip, prompt explicitly for discovery before guessing, and make failed invokes return the available names. Your context cost stops tracking catalog growth.
- Retrieval-based selection — and its operating obligations
Justified: too large and too diffuse to hand-maintain, no clean core/tail split. Take on the whole package — hybrid retrieval, a labeled set with recall@k in CI, a floor set, the exposed set logged on every call, and a monthly never-retrieved audit. Skipping those makes the silent failure mode permanent.
- Split by toolset into specialists
The right answer when the groups are different work: each specialist gets a small cacheable loadout, its own evals, and an owner. Now pay the tax deliberately — a brief at every boundary, information loss when one agent summarises for another, and coordination failure modes that single agents cannot have. Read the subagent module before committing.
Interactive flashcard deck.
Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.