anthropic-compact-tools
v0.1.1
Published
Compact-syntax tool calling for the Anthropic TypeScript SDK. Replaces verbose tool_use JSON with a compact wire format to reduce output tokens.
Maintainers
Readme
anthropic-compact-tools
Compact-syntax tool calling for the Anthropic TypeScript SDK.
Replaces verbose tool_use JSON blocks with a compact <call>name k=v</call> or <tool_result name="name">k=v</tool_result> wire format.
The goal: reduce output tokens by reducing the structural overhead the model generates on every tool call. Results vary by model, task complexity, and conversation length. Run the benchmark on your workload to measure the effect.
import { CompactAnthropic } from 'anthropic-compact-tools';
const client = new CompactAnthropic({ apiKey: 'sk-...' });
const response = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 1024,
tools: [{ name: 'get_weather', description: '...', input_schema: { ... } }],
messages: [{ role: 'user', content: 'What is the weather in Austin?' }],
});
// response.content has standard tool_use blocks — works as expectedInstall
npm install anthropic-compact-tools
# or
bun add anthropic-compact-toolsUsage
Basic
import { CompactAnthropic } from 'anthropic-compact-tools';
const client = new CompactAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const response = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 1024,
tools: [{ name: 'get_weather', description: '...', input_schema: {...} }],
messages: [{ role: 'user', content: 'Weather in Austin?' }],
});Wrap an existing client
import Anthropic from '@anthropic-ai/sdk';
import { CompactAnthropic } from 'anthropic-compact-tools';
const raw = new Anthropic({ apiKey: 'sk-...' });
const client = new CompactAnthropic(raw, { syntax: 'tool_result' });Options
const client = new CompactAnthropic({ apiKey: 'sk-...' }, {
syntax: 'tool_result', // 'wire' | 'tool_result' (default 'wire')
placement: 'first_user', // 'first_user' | 'system' (default 'first_user')
rewriteHistory: true, // rewrite prior tool_use blocks to compact (default true)
minifyToolDefinitions: false, // OPT-IN: strip descriptions from tool schemas
});How it works
Before API call:
tools[] → UNCHANGED (prompt cache preserved)
system → UNCHANGED
first message → format instruction prepended (safe for all cache breakpoints)
history → prior tool_use blocks rewritten to compact text
After API call:
response text scanned for compact spans
key=value args parsed back to structured JSON
synthetic tool_use content blocks emitted
dual-format: native tool_use + compact both handledPrompt caching
The tools array is never modified. The format instruction goes in the first user message, which is after every possible cache breakpoint (tools, system, messages). Zero cache invalidation.
Syntax
wire (default)
<call>getWeather location=Austin units=metric</call>tool_result
<tool_result name="getWeather">location=Austin units=metric</tool_result>Wire format rules
key=value → bare values
key="quoted value" → values with spaces
key=["a","b"] → arrays (JSON inline)
profile.name=Alice → nested objects (dot-path flattening)Benchmark
bun run bench # Offline token comparison (no API key)
ANTHROPIC_API_KEY=sk-... bun run bench:live # Real API benchmark
ANTHROPIC_API_KEY=sk-... bun run bench:live --model claude-haiku-4-5 # Specific model
bun run bench:live --compare --save # Compare saved runsLive benchmark output example
═══════════════════════════════════════════════════════════════
│ Compact Tool Calling — Live Benchmark │
│ Model: claude-haiku-4-5 │
│ 11 prompts × 3 modes = 33 API calls │
│ Pricing: $1.00/M in · $5.00/M out │
═══════════════════════════════════════════════════════════════
[ 0] What is the weather in Austin?
Native: 54 tok ✓ Wire: 55 tok ✓ ToolResult: 54 tok ✓
[ 1] Search for wireless earbuds.
Native: 57 tok ✓ Wire: 57 tok ✓ ToolResult: 57 tok ✓
[ 5] Get the weather in Austin and Dallas, then calculate…
Native: 107 tok ✗ Wire: 107 tok ✗ ToolResult: 141 tok ✗
═══════════════════════════════════════════════════════════════
│ RESULTS — claude-haiku-4-5 │
═══════════════════════════════════════════════════════════════
┌─────────────────────────┬─────────────┬─────────────┬─────────────┐
│ Metric │ Native │ Wire │ ToolResult │
├─────────────────────────┼─────────────┼─────────────┼─────────────┤
│ Output tokens │ 1,322 │ 1,703 │ 1,703 │
│ Δ vs Native │ — │ +28.8% │ +28.8% │
│ Input tokens │ 9,126 │ 11,678 │ 11,678 │
│ Δ vs Native │ — │ +28.0% │ +28.0% │
│ Accuracy │ 5/11 │ 5/11 │ 5/11 │
│ Δ vs Native │ — │ same │ same │
├─────────────────────────┼─────────────┼─────────────┼─────────────┤
│ Cost (this run) │ $0.0157 │ $0.0202 │ $0.0202 │
│ Δ vs Native │ — │ +0.44¢ │ +0.44¢ │
│ Cost @ 1K calls/day │ $15.74 │ $20.19 │ $20.00 │
│ Cost @ 10K calls/day │ $157.36 │ $201.93 │ $200.03 │
├─────────────────────────┼─────────────┼─────────────┼─────────────┤
│ Recommendation │ (baseline) │ ❌ Worse │ ❌ Worse │
└─────────────────────────┴─────────────┴─────────────┴─────────────┘
Results saved: /path/to/results/claude-haiku-4-5-123456789.jsonTests
bun test # 50 tests, no API key neededLicense
MIT — see LICENSE.
Copyright (c) 2026 Sawyer Cutler
