Your Agent Wastes 40,000 Tokens Before You Ask It a Single Question
I noticed it first in a Claude session I was running last week. I had connected a few MCP servers — a GitHub one for issue management, a Slack one for messages, a database query tool — and was watching the prompt inspector to see what the model actually sees. What I found was absurd: over 9,000 tokens of pure tool definition before the system prompt even finished loading. Before I typed a single word. Before the model could help me with anything.
That’s not a Claude problem. That’s a tool-definition problem. And it gets worse the more tools you add.
Every tool you connect to an LLM ships its full JSON Schema — parameter names, types, descriptions, constraints — and the model has to read all of it before it can pick the right one. A realistic set of 50 tools burns roughly 20,000 tokens just describing themselves. A hundred tools? You’re looking at 40,000 tokens. Every. Single. Request.
Prompt caching makes those tokens cheap, but it doesn’t make them take up less space. And when your context window is filling up with boilerplate parameter descriptions, there’s less room for the actual conversation, the code you’re analyzing, or the documents you’re referencing.

Enter Toolgz — an open-source npm library that compresses tool definitions to about 20% of their original size without losing accuracy. I’ve been testing it for a few days, and the numbers are real. Let me show you how it works and how to set it up.
What Toolgz Actually Does
Toolgz (pronounced “tool-g-z” or “toolgies,” I’m still not sure) is a compression layer for LLM tool definitions. You feed it your existing tool array — the same one you’d pass to Claude, GPT, Gemini, or Grok — and it returns a dramatically smaller version. The model still calls the right tools with the right arguments, and your dispatch code doesn’t change at all.
The library offers three compression levels, but the headline number — 80% reduction — comes from Level 3, which replaces your entire tool list with just two wire-level tools plus a compact lookup map in the system prompt.
The measured results across four frontier models speak for themselves:
- Claude Opus 5: 9,242 → 1,284 tool tokens (−86%), cost −78%
- Grok 4.5: 6,421 → 775 tool tokens (−88%), cost −70%
- Gemini 3.1 Pro: 5,264 → 732 tool tokens (−86%), cost −62%
- GPT 5.6 Sol: 2,752 → 573 tool tokens (−79%), cost −7%
Notice something? OpenAI’s cost saving is smallest because reasoning output dominates the bill — but context-window occupancy still drops by 71%. That’s the real claim here: more room in your context for actual work.
Installing Toolgz
Toolgz is a zero-dependency npm package. If you’re working in a Node.js or TypeScript project, installation is straightforward:
npm install toolgz
That’s it. One dependency. No Rust toolchain, no Python venv, no Docker container. The library is a pure TypeScript module that compiles to about 5KB of JavaScript.
Basic Usage: Three Lines of Code
Here’s the core pattern for Anthropic’s API, which is where tool overhead is most painful thanks to the verbose tool block format:
import { compress, forAnthropic } from "toolgz";
const c = compress(myTools);
const { tools, system } = forAnthropic(c);
That’s it. myTools is your existing tool array — the same one you’re already passing to anthropic.messages.create(). compress() returns a compressed representation, and forAnthropic() formats it for Anthropic’s Messages API, placing a cache_control breakpoint at the right spot.
Then, when the model makes a tool call, resolve it back to the real function:
const r = c.resolve(block.name, block.input);
if (r.kind === "call") await myDispatch(r.name, r.args);
Your dispatch function gets exactly what it got before — the real tool name and the real arguments. Nothing downstream changes. That’s the design philosophy: compress the wire format, leave your application logic untouched.
The Three Compression Levels
Toolgz ships a recommendLevel() function that analyzes your tool set and tells you which level to use. It returns either 1 or 3 — level 2 is, as the maintainer puts it, “dominated by level 3 on every axis.”
Level 1: The Free Lunch
Level 1 keeps each tool as a separate function declaration but compresses the descriptions down to a single line. It’s the safest option — measured to have zero downside: fewer tokens, zero malformed arguments, no extra turns, and latency that’s either flat or better. If you have fewer than about 15 tools, recommendLevel() will tell you to use this level. For most developers connecting a handful of MCP servers, Level 1 is all you need.
Level 3: Maximum Compression
Level 3 replaces every tool on the wire with just two generic tools — a dispatcher and a lookup — plus a short text map in the system prompt that looks like this:
<toolmap>
a0 github_create_issue owner,repo,title
a1 github_search_issues q
b0 slack_post_message channel,text
</toolmap>
The model calls t(f="a0", a={…}) with compact codes, and your library resolves them to the real functions. The measured result: the 80% reduction numbers I showed above.
The tradeoff: at Level 3, the provider’s schema enforcement no longer applies because the model is filling a generic argument object. Toolgz compensates by validating against your original schema server-side, but this adds a validation step you didn’t have before. Leave validate on (it defaults to on) and you’re covered.
Provider Adapters
Toolgz has dedicated adapters for every major provider:
import { forAnthropic, forOpenAI, forOpenAIResponses, forGemini } from "toolgz";
- Anthropic: Places a
cache_controlbreakpoint automatically. Skips deferred tools (which the API rejects anyway). - OpenAI (Responses API): Use
forOpenAIResponsesif you need tools and reasoning together — the old Chat Completions endpoint doesn’t support that combination. - OpenAI (Chat Completions):
forOpenAIhandles the nested tool shape. xAI’s API is OpenAI-compatible — just passbaseURL: "https://api.x.ai/v1". - Gemini:
forGeminiformats your tools as a singlefunctionDeclarationsarray.
MCP Integration
If you’re building on the Model Context Protocol — and in 2026, most of us are — Toolgz composes with your MCP servers naturally. You pull your tool definitions from your MCP server list, pass them through compress(), and send the compressed version to the model. The linked post How to Build Your First MCP Server with FastMCP walks through the MCP basics if you’re new to the protocol.
This combination is especially powerful: MCP lets you dynamically add and remove tools, and Toolgz makes sure those tools don’t eat your entire context window when you do.
Where It Shines (and Where It Doesn’t)
Toolgz is at its best when you have 15+ tools. Below that threshold, recommendLevel() will tell you there’s not much to reclaim. I tested it with my personal setup — about 20 tools across 4 MCP servers — and got a respectable 73% token reduction on the tool block.
Where it’s not magic: on non-frontier models at Level 3. Haiku 4.5, for example, had argument errors in 17 of 30 test runs — all caught and retried, but still a measurable quality drop. If you’re using a smaller model, stick with Level 1.
Also worth noting: this tool doesn’t beat Anthropic’s native tool search on pure tool-block size. What it does is compose with it and work on providers that have no equivalent. On Haiku, Anthropic’s defer_loading flag completed only 6 of 30 tasks — silently — because it lets the model choose whether to discover tools. Toolgz’s dispatcher model makes discovery the entry point, which is more reliable on weaker models.
What This Means for Your API Bill
The cost saving varies wildly by provider. On Anthropic, 78% cheaper is a meaningful number — at $15 per million input tokens for Opus 5, cutting the tool block by 86% saves real money. On OpenAI, the savings are modest (7%) because reasoning output dominates the bill.
But cost is only half the story. If you’ve ever hit a context window limit and watched your agent lose track of earlier instructions, you know that space is the real scarcity. Reclaiming 40,000 tokens from tool definitions means 40,000 more tokens for code, documents, conversation history, or whatever your agent actually needs to do its job. As I discussed in my guide on monitoring AI API spending with Rekon, most developers have no idea where their tokens are going — and tool definitions are among the biggest silent consumers.
The Bottom Line
Toolgz is one of those libraries that makes you wonder why nobody built it sooner. The problem it solves — bloated tool definitions eating your context window — is universal for anyone building LLM-powered agents. The solution is small, well-tested, and shockingly easy to integrate. Three lines of code gets you started, and the default Level 1 has zero measurable downside.
The broader pattern here is something I’ve been thinking about a lot lately. We’re building increasingly complex agent systems with dozens of tools, multiple MCP servers, and elaborate prompt chains — but the foundational plumbing still wastes enormous amounts of context on boilerplate. Tool optimization is one piece of that puzzle — like the hidden costs of AI agents that many developers overlook — but it connects to a bigger conversation about the two AI economies and the economics of building with frontier models.
If you’re running an agent in production — or even just hacking on one in your spare time — install Toolgz and check your before/after numbers. You might be surprised how much context you were leaving on the table.