An agent bill has a nasty property: it grows quadratically with conversation length (every turn re-sends the whole history), multiplies with every pattern you stack, and one runaway loop can burn a day’s budget in an hour. Cost control isn’t something finance adds later — it’s designed into the architecture.
The analogy
The meter and the circuit breaker. The meter tells you which appliance eats the electricity — no meter, no idea. The breaker cuts the power before the wiring catches fire — you don’t discover a short circuit through the bill. An agent needs both: visibility per step, and hard limits that trip automatically.
The principle
flowchart LR
R([request]) --> C{"stable prefix cached?"}
C -->|hit| CHEAP["~90% cheaper reading"]
C -->|miss| FULL["full-price processing"]
CHEAP --> LLM["model sized to the step"]
FULL --> LLM
LLM --> B{"budget & turn caps OK?"}
B -->|yes| OUT([continue])
B -->|exceeded| STOP([stop & report])
The four big levers, in order of impact:
- Prompt caching — put the stable content (system prompt, docs, tool schemas) first, the variable part last: the repeated prefix costs up to ~90% less.
- Right-size the model per step — routing and chaining let a cheap model do the easy 80% and reserve the strong one for the hard step.
- A lean context — prune history, summarize (see memory), disable unused tools: you pay the whole context on every turn.
- Hard limits — max turns, max tokens per answer (
max_tokens), max spend per task. An agent loop without a breaker is an open-ended invoice.
A concrete example
A document-processing pipeline, before and after:
before → one big model call per document, full context
10,000 docs/month ≈ $2,300
after → routing: small model classifies (90% stop there)
big model only for the 10% complex cases
static instructions cached
10,000 docs/month ≈ $410
Same output quality on the eval set — that’s the point of measuring both (see evaluate & observe).
The starter checklist
- Meter first: log tokens and cost per step, not just per month — you can’t cut what you can’t see.
- Order your prompt for the cache: stable first, variable last. It’s free money.
- Set the breakers on day one: max turns, max cost per task, timeout. Generous is fine; absent is not.
- Watch cost per outcome, not cost per call: a $0.40 task that replaces 20 human minutes is cheap; a $0.02 answer nobody can use is expensive.
The classic trap
Optimizing the price of the wrong thing. Teams shave input tokens while a retry loop silently triples volume, or switch to a cheaper model that fails 15% more — and the reruns eat the savings. Always read cost next to the eval scores: the cheapest system is the one that succeeds on the first try.