An AI agent is a loop: it calls a model, reads the result, decides what to do next, and calls again. Each turn costs tokens, money and time. The natural question — what is the most this loop can spend before it stops? — usually has no answer until after it has already spent it.
Runtime budget trackers report the bill once it arrives. We wanted the worst case before deployment: a ceiling you can prove, not a number you observe in hindsight.
What we looked at
We took 254 real agent workflows from 45 public, production-grade repositories built on the common frameworks — LangGraph, CrewAI, the OpenAI Agents SDK — and asked, for each one: where does its spending ceiling actually come from?
The default is the catch. LangGraph's modern ceiling (recursion_limit) is 1000 supersteps — it was 25 before version 1.0.6. A workflow that looks "protected" can take a thousand turns before the framework stops it. And only about one in eight of the model calls in this code carries an explicit token cap. A limit of 1000 steps is not protection; it is a ceiling high enough to bound almost nothing.
A bound you can prove
Underneath the measurement is a small piece of theory: a typed-resource calculus in which a well-typed workflow provably cannot exceed its declared budget — on every possible trace, not just the ones you tested. The central cost-soundness theorem is machine-checked in Lean 4, with no gaps and no unproven steps.
The static checker that puts this to work is Costwright. You point it at a repository and it reports, per workflow graph, the worst-case ceiling, where that ceiling comes from, and when it is effectively vacuous. It never runs your code — it reads it. It is conservative by construction: where a workflow uses a pattern the calculus cannot bound, it says so, rather than inventing a smaller number.
The point is not that agent frameworks are careless. It is that "it has a limit" and "it has a limit that means something" are different statements — and today almost no one can tell which one is true of their own system before it runs.