When you give Claude tools, everything about them — names, descriptions, JSON Schemas for parameters — is serialized into the prompt and counted toward the context window as billable input. Official docs are explicit: tool definitions, like the system prompt and messages, count on every request. Multiply a 5,000-token tool catalog by every step of every agent session and it can quietly become one of your largest line items.
Know your fixed overhead first
Before optimizing your own schemas, know the baseline you can't remove. Enabling tool use adds a system-prompt overhead that varies by model and tool_choice: on Claude Opus 4.8 it is 290 tokens with auto/none and 410 with any/tool; on Sonnet 5, 354/474; on Haiku 4.5, 496/588. Anthropic-defined tools carry published definition costs too — the bash tool adds 325 input tokens on Opus 4.8, the text_editor_20250429 tool adds 700, and the computer-use tool definition adds 735 on Claude 4.x models. These are per-request, fixed, and worth including in any cost model. Everything beyond that is your schema — and yours to shrink.
Four cuts that don't break function
1. Tighten descriptions. The description is prompt text: it should say what the tool does, when to use it, and what it returns — not restate the parameter list or include three worked examples. Clear beats long; a well-named tool with a two-sentence description usually outperforms a paragraph of hedging.
2. Compress parameter names — within reason. customer_account_identifier_string and account_id parse identically to the model, but one costs more on every request and on every generated tool call, since Claude writes parameter names back out in its tool-use output (billed at output rates, which run 5x input on current models). Stop short of cryptic: a1 saves tokens and destroys reliability.
3. Trim enums and optional parameters. A 40-value enum of country codes or a grab-bag of "maybe someday" optional fields inflates the schema on every call. Keep enums to values the model must choose among; validate the long tail in your own code. If you use strict tool use ("strict": true for guaranteed schema-valid calls), note the documented complexity limits — at most 20 strict tools and 24 total optional parameters across strict schemas per request — which are a useful forcing function even when you're under them.
4. Send fewer tools per request. The cheapest schema is the one you didn't send. If your agent has 30 tools but a given step needs 5, scope the tool list to the task phase.
Then make what remains nearly free
Tool definitions are cacheable, and they sit first in the caching hierarchy (tools → system → messages). A stable tool catalog cached with a cache_control breakpoint bills at 0.1x the input price on every hit — turning, say, 4,000 tokens of schemas on Opus 4.8 from $0.02 to $0.002 per request. The flip side of sitting first in the hierarchy: modifying any tool definition invalidates every cache level after it. Dynamically assembled per-user tool sets are a documented silent cache killer. Reconcile this with cut #4 by defining a small number of stable tool bundles per task phase rather than composing a bespoke list per request.
/v1/messages/count_tokens) accepts tool definitions, so you can diff a schema slim-down in seconds — count with the old catalog, count with the new, subtract. Recount when migrating models: Opus 4.7+ and Sonnet 5 use a tokenizer that produces roughly 30% more tokens for the same text.Where to go next
See tool call overhead for the full request-loop economics and the caching ROI walkthrough for the discount math applied above.