A drop-in wrapper that intercepts every LLM call, applies a multi-strategy token reduction pipeline, and produces detailed usage reports. Supports the Anthropic SDK and AWS Bedrock.
Every call to an LLM API is billed by tokens (roughly, word pieces) in and out. Most of that cost is waste: verbose instructions, repeated conversation history resent on every turn, and models rambling past the point where they've already answered the question.
ShrinkWrap sits between your code and the LLM API as a drop-in wrapper. You call
client.messages.create(...) exactly like you normally would; behind the scenes, ShrinkWrap:
- Trims obvious waste from what you're sending (verbose phrasing, old conversation turns that get summarized instead of resent in full) without changing what you're actually asking.
- Marks reusable parts of the prompt so the API caches them instead of re-billing you for the same text on every call.
- Caps how much room the model has to ramble in its reply, scaled to how hard the task actually is.
- Logs exactly how many tokens and dollars each call used, so the savings are measurable, not assumed.
None of this changes what the model is asked or what it knows. It only removes waste in how the request is packaged and how much space the response is given to sprawl.
Results on a 10-prompt benchmark (mixed code generation, debugging, explanation, and code review tasks) against Claude Sonnet 4.6 via AWS Bedrock:
| Metric | Baseline (no wrapper) | Wrapped (ShrinkWrap) | Reduction |
|---|---|---|---|
| Input tokens | 1,221 | 1,051 | 13.9% lower |
| Output tokens | 8,807 | 6,314 | 28.3% lower |
| Total tokens | 10,028 | 7,365 | 26.5% lower |
| Total cost (USD) | $0.1358 | $0.0979 | 27.9% lower |
See architecture.md for the full strategy-by-strategy breakdown and design rationale.
Anthropic:
export ANTHROPIC_API_KEY=sk-ant-...
bash run.shAWS Bedrock:
export AWS_BEARER_TOKEN_BEDROCK=<your-key>
python benchmark_runner.py --bedrock --model claude-sonnet-4 --benchmark benchmark_sample.jsonTo also measure against an unoptimized baseline:
bash run.sh --baseline- Python 3.9+
pip install -r requirements.txt(anthropic+boto3)- An Anthropic API key or a Bedrock bearer token
Anthropic:
export ANTHROPIC_API_KEY=sk-ant-...AWS Bedrock:
export AWS_BEARER_TOKEN_BEDROCK=<your-bearer-token>pip install -r requirements.txtThis installs anthropic (Anthropic SDK) and boto3 (Bedrock support).
# Basic run: wrapped mode, outputs to results.json
bash run.sh
# With baseline comparison
bash run.sh --baseline
# Different model
bash run.sh --model claude-sonnet-4.6
# Benchmark JSON
bash run.sh --benchmark benchmark_sample.json --output results.json
# Verbose per-call debug output
bash run.sh --verbose# Set API key
$env:ANTHROPIC_API_KEY = "sk-ant-..."
# Or for Bedrock
$env:AWS_BEARER_TOKEN_BEDROCK = "<your-bearer-token>"
# Install dependencies
pip install -r requirements.txt
# Basic run
python benchmark_runner.py --benchmark benchmark_sample.json --output results.json
# Bedrock
python benchmark_runner.py --bedrock --model claude-sonnet-4 --benchmark benchmark_sample.json --output results.json
# With baseline + verbose
python benchmark_runner.py --benchmark benchmark_sample.json --output results.json --baseline --verbose# Anthropic
python benchmark_runner.py \
--benchmark benchmark_sample.json \
--model claude-sonnet-4.6 \
--output results.json --baseline --verbose
# Bedrock
python benchmark_runner.py \
--bedrock --model claude-sonnet-4 \
--benchmark benchmark_sample.json \
--output results.json --verboseYou can test with your own prompts: just create a JSON file matching this format:
[
{
"id": "my_01",
"task": "code_generation",
"category": "general",
"difficulty": "medium",
"prompt": "Your prompt here"
}
]task: one ofexplanation,code_generation,debugging,code_review(drives adaptivemax_tokens)difficulty:easy,medium, orhard(lower difficulty = lower token budget)id: unique string per prompt (used in reports)category: freeform label (used in logs, not in logic)
Then run:
python benchmark_runner.py --benchmark my_benchmark.json --output results.json --baselineConsole output: two tables are printed after the run.
- A summary report with total tokens, cost, and most expensive calls
- A per-call table with input/output tokens, savings, and strategies applied
results.json: machine-readable output containing:
- Every prompt's response text
- Per-call token counts (input, output, cache reads/writes)
- Summary report with % token reduction and total cost
from shrinkwrap import ShrinkWrapClient
from shrinkwrap.pipeline import PipelineConfig
config = PipelineConfig(
enable_compression=True,
enable_trimming=True,
enable_caching=True,
)
client = ShrinkWrapClient(api_key="sk-ant-...", config=config)
response = client.messages.create(
model="claude-sonnet-4.6",
max_tokens=1024,
system="You are a helpful assistant.",
messages=[{"role": "user", "content": "Explain recursion."}],
label="my_call", # optional label for reports
)
print(response.content[0].text)
client.print_report()with ShrinkWrapClient(api_key="...") as client:
client.messages.create(...)shrinkwrap/
├── shrinkwrap/
│ ├── __init__.py # Public API: ShrinkWrapClient, UsageReporter, UsageLogger
│ ├── client.py # Drop-in wrapper (Anthropic SDK or Bedrock)
│ ├── bedrock_client.py # AWS Bedrock adapter
│ ├── pipeline.py # Reduction pipeline (compression, trimming, caching)
│ ├── logger.py # Per-call token usage accumulator (thread-safe)
│ ├── reporter.py # Console and JSON report generator
│ └── utils.py # Token counting, text compression, cost estimation
├── benchmark_runner.py # CLI benchmark harness (parallel, Anthropic + Bedrock)
├── benchmark_sample.json # Sample benchmark prompts
├── run.sh # Entry point script
├── requirements.txt
├── README.md
└── architecture.md
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
(required for Anthropic) | Anthropic API key (sk-ant-...) |
AWS_BEARER_TOKEN_BEDROCK |
(required for Bedrock) | Bearer token for Bedrock gateway |
WRAPPER_MODEL |
claude-sonnet-4.6 |
Default model (overridden by --model) |
WRAPPER_MAX_TOKENS |
1024 |
Max output tokens per call (overridden by --max-tokens) |
The wrapper does not truncate or rewrite prompt meaning. Reduction strategies are:
- Prompt caching: zero semantic change; uses Anthropic's native feature
- Text compression: normalizes whitespace, replaces verbose constructs with concise equivalents (e.g. "in order to" becomes "to"). Prompts containing code (fenced or unfenced) are automatically skipped to avoid counterproductive token inflation
- Context trimming: only summarizes long multi-turn history (>6000 tokens) using the configured model; all relevant context is preserved in the summary
- Output reduction: concise system prompt and adaptive
max_tokensper task/difficulty reduce output verbosity without sacrificing answer quality