Your Tool Schemas Are the Bloat
I opened one API call from a working agent session and sorted every token in it by where it came from. The skill descriptions, the kind of prose pruning guides tell you to trim, were 8,534 tokens: 6.5% of the call. The tool schemas were 79,579 tokens: 60.8%. Of the 238 tools declared in that call, the session used four.
Thesis: In an agent wired to a broad set of connectors, the always-loaded cost is the tool array, not the prose. It is re-bought on every request, almost none of it is called, and cutting it takes a set difference, not an ablation study. Measure the call before you edit the prose.
What Was Measured
The instrument is a private one: a local proxy that sits between the coding agent and the model API and records each request body as sent. It partitions a request into labelled lanes (tools, user, tool results, skills, assistant, system), and it keeps the exact tool array of every request, which makes "declared but never called" an observation rather than an estimate.
One caveat governs every number below. The token counts are characters divided by four, not a tokenizer. The lanes reconcile with each other because they share that estimator, so treat them as ratios, not as a bill. The skills lane is itself a labelling decision by a regex classifier; an independent check, summing every skill's name and description from disk, came to about 10,462 tokens against the classifier's 8,534: same order of magnitude.
One Call, Six Lanes
Call #100 of 224 came from one Opus session doing real work; every request in it was a subagent request, across 22 sibling agents. It held about 130,817 tokens in 264 segments.
| Lane | Tokens in call #100 | Share | If carried through all 224 requests |
|---|---|---|---|
| Tool schemas, all 238 declared | 79,579 | 60.8% | ~17.8M |
| … the 230 never called in any session that declared them | 73,726 | 56.4% | ~16.5M |
| … the 4 never called here but called in other sessions | 4,349 | 3.3% | ~1.0M |
| … the 4 the session used | 1,504 | 1.1% | ~0.3M |
| User messages | 19,889 | 15.2% | (changes per call) |
| Tool results | 19,708 | 15.1% | (changes per call) |
| Skill names and descriptions | 8,534 | 6.5% | ~1.9M |
| Assistant | 1,705 | 1.3% | (changes per call) |
| System | 1,502 | 1.1% | ~0.3M |
The last column is arithmetic, not a measurement: the per-call figure times the session's 224 requests, for the lanes loaded on every request. The instrument reports the tool array at 79,579 tokens per request across those 224, and the segment ledger agrees: between calls 99 and 100, 244 segments carried over unchanged, 20 were new and 22 dropped; 92% of the segments were already there.
Prose, spread over the user, skills and system lanes, is at most 22.8% of the call. The tool array alone is 60.8%.
The four tools used were the shell, file read, file write, and a structured-output tool. Four more were never called in this session but were called in others; those are candidates, not cuts. The other 230 (chat, mail, calendar, drive, browser and test-automation connectors, and likely some of the harness's own built-in tools) were never called here or in any other session that loaded them.
A Unit Is Re-Bought, Not Bought
A context unit is not paid for once; it is re-bought on every request for the rest of the session. A 112-token unit that survives 224 requests costs about 25,000 tokens. The largest schema among the ten costliest never-called tools ran to 3,047 tokens; by the same arithmetic, that is about 682,500. The cheapest win is deleting something early, before it is re-bought.
The pattern holds across 35 of my own sessions, whose tool bundles varied from session to session: 423 distinct tools were declared and 15 were ever called (3.5%). Of 59.1M tool-definition tokens paid, 57.4M (97.1%) belonged to tools never invoked once in the session that loaded them. The instrument prices that dead share at $32.18.
That dollar figure is small on purpose. Tool definitions sit in the cached prefix, so they are priced at the cache-read rate; pricing them as fresh input would overstate the waste by roughly an order of magnitude. The argument is the share: three in five tokens of that call went to a surface the agent almost never touches.
What This Corrects
MCP Isn't the Problem already said it in words: a few connected servers can spend 20–30% of context on tool schemas, and every message carries the full tool list. This post measures it: 60.8% of one call, and 97.1% of tool tokens over 35 sessions spent on tools never called.
What it corrects is The alwaysApply Tax, which audited always-on rules and priced them at fresh-input rates. Measured on the wire in a different agent, always-loaded prose came to under a quarter of the call, and the dominant always-loaded cost was a tool array, re-read from cache at a fraction of that price. Its advice to load rules only when relevant still stands. For an agent wired like this one its target was the wrong lane, and for anything in a cached prefix its rate was the wrong one.
The same goes for this site's ablation work. The Gotchas Are Load-Bearing is the right instrument for prose: it finds which rule carries the behaviour. It is the wrong first instrument when skill descriptions are 6.5% of the call and a set difference on the tool array would move nearly nine times as many tokens.
What This Means for an Enterprise Agent
An illustration: picture a platform team that ships a standard agent profile to two hundred engineers. On day one the profile turns on every approved connector: chat, ticketing, calendar, docs, the browser, two internal data services. Together they put a few hundred tool definitions in front of every request, for an engineer whose session is mostly reading files and running tests. Meanwhile a governance review trims the shared instruction file by a third. That review is pruning prose. Nobody owns the 60% lane, because each connector was approved one at a time and nobody signs off on the total.
When the Opposite Wins
Pruning prose is the right move when prose is the large lane. An agent with two or three tools and a long instruction file has the inverse profile; measure it and the prose may dominate. Prose also steers behaviour, which a cost count cannot see. In the ablation post, a directive of about forty-five tokens was the hinge: given only the principle behind it, the agent adopted the vocabulary and made no external calls. This instrument measures cost; it cannot say whether a schema has an effect like that.
Schema count is not the cost when the tools are used. "Dead" here is scoped per session: a tool idle in one session but central in another still counts as dead there. That is the right unit for deciding what a bundle loads, not for deciding a tool is useless. A support agent that queries the ticket system on most requests should keep that schema loaded; lazy-loading it would add a discovery round trip to every task.
Cheaper is not better. Removing 230 unused schemas cuts cost and frees room. Whether it also improves the agent's choices is a separate claim this instrument did not test; that needs an ablation of its own.
What to Do Next
- Measure your own call. Put a recording proxy or your platform's request log on one real session and split one request into lanes before you edit anything.
- Count declared against called. Over a week of sessions, list every tool declared and every tool invoked. The difference is your dead share; it needs no model and no repeats.
- Scope tool sets to the job. Give each agent profile the connectors its work calls; lazy-load the rest where your client supports it. Keep the "called elsewhere" tools as candidates, not cuts.
- Set a per-call budget. Cap the tool lane in tokens per request, the way the alwaysApply post capped rule lines, and make each new connector justify its share of that cap.
- Price it honestly. Use the cache-read rate for anything in the cached prefix, and report the share before the dollars.
Related reading: The alwaysApply Tax, which this post corrects; The Gotchas Are Load-Bearing; MCP Isn't the Problem, whose claim this post measures; MCP as Discovery Protocol; and The Files Are the Memory.