Nabil Asofi

Journal / systems

Keeping token spend predictable with caps and a downgrade ladder

Keeping token spend predictable means budgets per task, hard caps, caching, and a model-downgrade ladder, not hoping usage stays flat.

Token cost is the one line item in an agent system that scales with success. The more the thing works, the more it gets used, and the more it costs. Keeping token spend predictable is not about finding a cheaper model. It is about putting a ceiling on the system before the system finds the ceiling for you, usually during a traffic spike nobody planned for.

Why keeping token spend predictable is a design problem, not a billing problem

Most teams treat token cost as something to check at the end of the month, which is exactly backwards. By the time the invoice arrives, the spend already happened. A system where cost is unpredictable usually has no budget attached to individual tasks, no cap that actually stops execution, and no cheaper fallback when the expensive path is overkill. Fix those three and the invoice stops being a surprise. This has to be decided at build time, the same way you’d decide on structured output or error handling, not bolted on after a bad month.

Set a token budget per task, not per project

A token budget per task means every unit of work has a ceiling before it starts, and the system knows what to do when it hits that ceiling. “Our monthly API spend should be under $2,000” tells you nothing about which task blew the budget or why. “Classifying one support ticket should cost under 800 tokens” tells you immediately when something is wrong, because one ticket suddenly costing 4,000 tokens is a visible, debuggable event. Set the budget at the smallest unit of repeatable work in your pipeline. If you can’t name that unit, you don’t have a system yet, you have a script that calls a model.

Enforce a hard cap on api spend that fails closed

A soft warning does nothing, because nobody reads logs in real time. A hard cap on api spend has to actually stop the call, return a defined failure state, and let the rest of the system handle that failure the way it would handle any other error. This means your prompts and output contracts need to account for a “budget exceeded” branch, not just a success and a retry. If your prompt design already treats failure as a first-class case rather than an edge case, this is one more branch, not a redesign. That’s the whole argument for prompting for reliability instead of prompting for a demo: the demo never hits the cap, production always does.

Cache before you downgrade

Caching is cheaper than a cheaper model, because it costs nothing at all. Most agent workflows repeat the same calls far more than teams expect: the same classification prompt on near-duplicate inputs, the same lookup embedded three times in one pipeline run, the same system prompt re-sent on every turn when only the user message changed. An llm cost caching layer that keys on normalized input and short-circuits identical or near-identical requests often cuts spend more than any model swap will. Build the cache first. Downgrading a model you’re calling five times when you only needed to call it once just means paying less for the same waste.

Build a model downgrade ladder before you need one

A model downgrade ladder is a defined sequence of fallbacks, cheapest viable option first, that the system steps through automatically when cost or rate limits demand it, instead of a manual scramble when the bill arrives. The ladder works because most tasks don’t need the most expensive model; they need the cheapest one that clears a quality bar you’ve already tested. Define that bar in advance, test each rung against it offline, and the downgrade becomes a config change under load, not an emergency rewrite. Without a ladder, “switch to a cheaper model” is a decision someone makes at 2am, under pressure, with no prior testing, which is how quality regressions sneak into production unnoticed.

Where this breaks down

None of this helps if the task itself shouldn’t be running on a model at a non-deterministic cost in the first place. A fixed pipeline that calls a model once per request has bounded, predictable cost by construction; it’s the systems trying to behave like real agents, making multiple model calls per task with branching and retries, where spend becomes genuinely hard to forecast. Before building caps and ladders, it’s worth checking whether you’re actually running an agent or a workflow with a model bolted on, because the fix for unpredictable cost is sometimes removing a call, not managing it.

Budgets, caps, caching and a downgrade ladder don’t make token spend cheap. They make it something you decided on, rather than something that happened to you. That distinction is the entire point of keeping token spend predictable: not minimizing cost, but owning the number before it owns you.

Also on this subject