Unbounded consumption rose from tenth to sixth on the OWASP 2026 list, and it moved because people started shipping agents. Cost belongs in a safety course rather than a budget review, because an attacker who can make your system spend money denies service to everybody else without breaching a single control, and a runaway loop does the same by accident.
Why this is a safety concern
Denial of service used to mean traffic. Against an AI feature it means spend, since inference costs real money per request and providers enforce quotas your whole account shares. Exhaust the quota or trip the budget and the feature stops answering, while your data, your model and your infrastructure were never touched.
The accidental version is more common than the deliberate one. An agent retrying a tool call that will never succeed, two agents handing work back and forth, a loop whose termination condition a long document never satisfies.
Where the money actually goes
The unit of cost is the run rather than the call. A run pays for a system prompt and a tool schema on every step, plus a conversation that grows as each tool result is appended to it, so cost climbs with the square of the step count rather than in a line. Retries multiply it again, and retrieval adds to it quietly, since every retrieved passage is an input token somebody pays for.
The mechanisms
Per user and per key limits. Requests per minute and tokens per day, applied to the identity making the request rather than to the account. Without them one caller consumes the capacity everybody shares, and you learn about it from support tickets rather than from a monitor.
Token and step budgets for agent runs. A hard maximum on steps, on total tokens and on tool calls, enforced by the loop rather than requested in the prompt. When a budget is reached the run should stop and say so, which is better than a run that quietly continues.
Timeouts. On the individual call and on the whole run, since a request nobody is waiting for any more is pure cost.
Caps on retrieval. A limit on the number of passages and on their combined length. An uncapped retrieval step is the usual explanation for a bill that does not match the request count.
Circuit breakers. When the error rate against a dependency crosses a threshold, stop calling it for a while. Retrying into a failing tool is the fastest way to spend money achieving nothing.
Alerting on spend. Daily at worst, with the alert on the rate rather than the total, because discovering the number when the invoice arrives means the exposure lasted a month.
Where consumption meets confidentiality
Model extraction is the case where the two concerns become one control. An attacker with enough queries can use the responses to train a substitute model, recover the substance of a system prompt, or map a retrieval index by asking about it systematically. None of that requires a breach and all of it requires volume, which is what a per caller limit removes.
The signal worth watching is therefore not any single request. It is one identity producing unusual volume with unusually systematic inputs, which you can only see if you record who called and how often.
Setting the ceiling yourself
A system with no ceiling has its ceiling set by whoever is most willing to abuse it. Every limit above is a decision about what your worst case looks like, and the choice is between making it calmly in advance or having it made for you by a stranger who found the feature interesting.
The corollary is that limits have to be tested. A budget nobody has ever reached is an assumption rather than a control, so drive one over the line in a test environment and confirm it stops the run.
Practise this
You need the agent or feature you run, your provider's price list, and five minutes with Python or a calculator.
Work out the worst case cost of one run, using the loop's maximum step count rather than the steps a typical run takes.
steps = 12 # the loop maximum, not the average
prompt_tokens = 1500 # system prompt plus tool schemas, sent every step
growth = 800 # tokens each tool result adds to the context
output_tokens = 400 # per step
input_total = sum(prompt_tokens + growth * i for i in range(steps))
output_total = output_tokens * steps
# Replace with your provider's prices per million tokens.
cost = input_total / 1e6 * 3.00 + output_total / 1e6 * 15.00
print(f"worst case run: {input_total} in, {output_total} out, {cost:.2f}")
What to look for. Compare the number with what you assumed a run costs, then multiply it by how many runs one user could start in an hour under the limits you have today. If you cannot state that second number, your ceiling is currently whatever a determined person decides it should be.
It teaches that the figure worth knowing is the worst case rather than the average, because the average is what your users produce and the worst case is what an attacker or a stuck loop produces.