Long-horizon agent workloads are input-heavy, spiky, and full of repeated prefixes. That combination is exactly where most teams silently burn 60–80% more than they need to. This guide shows you how to build a cost-optimizing inference client in Python that combines three proven techniques — context caching, model cascading, and budget guards — into one production-ready module.
By the end you'll have a client that: reuses cached prefixes across agent turns, falls back from a premium model to a cheap one when the task allows, and hard-stops runaway agent loops before they torch your budget.
Why agent workloads waste money
Three failure modes dominate:
- Repeated prefixes. Every agent turn re-sends the system prompt, tool definitions, and conversation history. Without caching, you pay full input price for identical tokens hundreds of times.
- Over-provisioning intelligence. Teams route summarization, formatting, and extraction through their most expensive model because "it's already wired up."
- Runaway loops. A retry loop with a buggy tool call can multiply a $0.02 request into $20 before anyone notices.
Step 1: Prefix caching — stop paying for the same tokens twice
Most major APIs now support automatic or explicit prompt caching, where repeated identical prefixes cost a fraction of normal input price (typically 10–50% of the base rate). The critical rule: keep your static content at the front of the prompt.
def build_messages(system: str, tools_doc: str, history: list, user: str):
# Static prefix FIRST — this is what gets cached
return [
{"role": "system", "content": system},
{"role": "system", "content": tools_doc},
*history, # grows per turn, still prefix-stable
{"role": "user", "content": user},
]Anti-patterns that silently break caching:
- Injecting a timestamp or random ID into the system prompt (every request gets a new prefix).
- Reordering tools or few-shot examples between calls.
- Dynamic content in the middle of the prompt — put volatile data at the end.
Step 2: Model cascading — cheap first, escalate on failure
Don't send every request to your flagship model. Build a two-tier cascade: try a fast, cheap model first, and escalate only when quality signals fail.
CASCADE = [
{"model": "glm-5.3-flash", "max_tokens": 4096},
{"model": "deepseek-v4-pro", "max_tokens": 4096},
{"model": "claude-opus-5", "max_tokens": 4096},
]
def complete_with_cascade(client, messages, quality_check):
last_err = None
for tier in CASCADE:
try:
resp = client.chat.completions.create(
model=tier["model"],
messages=messages,
max_tokens=tier["max_tokens"],
)
text = resp.choices[0].message.content
if quality_check(text): # your domain-specific gate
return text, tier["model"]
last_err = RuntimeError(f"quality gate failed on {tier['model']}")
except Exception as e:
last_err = e
raise last_errGood quality_check gates: JSON parses for structured output tasks; regex/keyword presence for extraction; a small LLM-as-judge score for fuzzier tasks. In practice, 70–90% of production traffic (classification, formatting, simple extraction) passes the first cheap tier.
Step 3: Budget guards — circuit breakers for your wallet
Track spend in-process and in a shared store (Redis works well for multi-worker), and trip a circuit breaker at a hard ceiling:
import time
class BudgetGuard:
def __init__(self, redis, key: str, cap_usd: float, window_s: int = 3600):
self.redis, self.key = redis, key
self.cap, self.window = cap_usd, window_s
def _spend(self) -> float:
return float(self.redis.get(self.key) or 0)
def check(self):
if self._spend() >= self.cap:
raise BudgetExceeded(f"cap ${self.cap} hit")
def record(self, cost_usd: float):
self.redis.incrbyfloat(self.key, cost_usd)
self.redis.expire(self.key, self.window)
def priced_request(client, messages, model, in_price, out_price, guard: BudgetGuard):
guard.check()
resp = client.chat.completions.create(model=model, messages=messages)
usage = resp.usage
cost = (usage.prompt_tokens * in_price
+ usage.completion_tokens * out_price) / 1_000_000
guard.record(cost)
return respThis 30-line pattern would have saved every team that has ever posted "my agent spent $400 overnight" on a forum.
Step 4: Pick models with real price data
The cascade is only as good as your tier pricing. Verify current prices before wiring constants — here's the kind of spread you'll find on an open inference marketplace like Qubax (prices per 1M tokens, USD):
| Tier | Example model | Qubax price (in/out) | vs. flagship retail |
|---|---|---|---|
| Cheap | GLM 5.3 Flash | $0.0069 / $0.0277 | ~0.3% |
| Mid | DeepSeek V4 Pro | $0.0097 / $0.0389 | ~0.4% |
| Premium | Claude Opus 5 | $1.11 / $4.44 | ~22% |
That's real data from Qubax's live price index — where competing compute providers bid inference down, frequently far below official retail list prices. The gap between tiers is enormous, which is exactly why cascading pays: routing 80% of traffic to the first tier cuts blended cost by an order of magnitude while the premium tier catches the hard 20%.
Putting it together
The full request flow:
BudgetGuard.check()— refuse to start if the ceiling is hit.- Build messages with a cache-stable prefix.
- Run the cascade: cheap → mid → premium, gated by
quality_check. - Compute actual cost from
usageandguard.record(cost). - Alert when spend hits 50%, 80%, and 100% of cap.
Operations checklist
- [ ] Log model, tokens, and computed cost per request (you can't optimize what you don't measure).
- [ ] Alert at 50/80/100% of hourly and daily budgets.
- [ ] Re-verify tier pricing monthly — model prices move fast.
- [ ] A/B your quality gate thresholds; too strict and you escalate everything, too loose and quality leaks.
- [ ] Test the circuit breaker deliberately before you need it in an incident.
Cost optimization isn't a one-time project — it's a control loop. With caching, cascading, and budget guards wired together, your agent infrastructure scales with your product instead of against your budget. And when you route through an open marketplace like Qubax, the market does part of the optimization for you.
FAQ
How much can prompt caching actually save?
Most providers discount cached input tokens to 10–50% of the normal input price. For agent workloads where 90%+ of each request is a repeated prefix, this routinely cuts total token spend by half or more.
Which requests should go in the cheap tier of a cascade?
High-volume, low-ambiguity tasks: classification, extraction into a fixed schema, formatting, routing decisions, summarization. Keep ambiguous reasoning, complex code generation, and high-stakes content on the premium tier from the start.
How do I know what a request actually cost?
Every major API returns a usage object with prompt and completion token counts. Multiply by your model's per-token prices and log it per request — aggregate hourly and daily to power your budget alerts.
Where can I compare real model prices?
Qubax's model index shows live prices across the DeepSeek, GLM, Qwen, Claude, GPT, and Gemini families, with an open market of compute providers competing on price — often well below official retail.