<!-- orbyt:chrome:begin -->
---
title: "Can Your Agent Outspend Its Limit?"
description: "A one-cent ceiling stopped our September 2026 controls after estimates reached $0.478471 and $0.4000276. Those were subscription usage estimates, not invoices. The records show a stop after crossing, while our protocol wrongly calls it a reservation. Here I propose a budget contract and the checks it would need to pass."
author: "Justin Bartak"
published: 2026-11-11
modified: 2026-11-11
canonical: https://www.orbytlabs.ai/blog/ai-agent-budget-limits
---
<!-- orbyt:chrome:end -->

# Can Your Agent Outspend Its Limit?

On September 17, 2026, Chicago time, a one-cent ceiling stopped two agent sessions. In UTC it was already September 18. By the stop, their estimated usage read $0.478471 and $0.4000276 ([single record](https://www.orbytlabs.ai/research/single-agent-vs-team/evidence-2026-10-08/docs/research/single-agent-vs-team/runs/controls/ceiling-single/RESULT.json), [team record](https://www.orbytlabs.ai/research/single-agent-vs-team/evidence-2026-10-08/docs/research/single-agent-vs-team/runs/controls/ceiling-team/RESULT.json)).

The stop was real. So was the overshoot.

Both runs ended with `error_max_budget_usd`. The dollar figures are list-price estimates on a subscription, not invoices. The model records name `claude-sonnet-5` and helper `claude-haiku-4-5-20251001`. The Claude CLI release was not recorded.

**A spending limit is defined by when it stops work, what it counts, and which paths obey it.** A dollar sign in a setting answers none of those questions.

## What happened to the one-cent limit?

Both runs were deliberate controls in my [single-agent versus team trial](https://www.orbytlabs.ai/research/single-agent-vs-team). The record names them `ceiling-single` and `ceiling-team`. The second is a named ceiling probe, not evidence about simultaneous team spending.

| Historical control, September 17, 2026 | Configured ceiling | Final list-price estimate | Stop status |
| --- | --- | --- | --- |
| Single | $0.01 | $0.478471 | `error_max_budget_usd` |
| Team | $0.01 | $0.4000276 | `error_max_budget_usd` |

Both records also say `passed: true`. That looks like a contradiction until you read what passed.

Both records contain all three markers: an error, a budget status, and estimated usage at or above the ceiling. The control code asks for less. It passes a parseable result when any one marker matches. In these runs, all three did.

The [checker](https://www.orbytlabs.ai/research/single-agent-vs-team/evidence-2026-10-08/scripts/research/single-agent-vs-team.mjs) never required the estimate to stay under the limit. Its pass alone would not even prove every stop marker appeared. The green status needs its own receipt.

Our own [protocol](https://www.orbytlabs.ai/research/single-agent-vs-team/evidence-2026-10-08/docs/research/single-agent-vs-team/PROTOCOL.md) gets this wrong. Its final paragraph says the controls prove a reservation. Its Deviation 2 says the opposite: the stop came after the crossing call. The raw records contradict the reservation claim too. The final paragraph is wrong.

That is a claim about our document, not about today's CLI. These controls cannot say what a current release does, and the missing release number limits reproduction. A current claim needs a new, authorized, versioned test.

## When does your limit take effect?

Four different mechanisms get called a limit. An alert tells someone a threshold was crossed. An accounting check notices usage after the work returns. A session stop keeps the session from continuing. Admission control decides whether work may begin, counting its maximum permitted charge first.

Each is useful. Each makes a different promise.

Those controls demonstrated a stop after crossing. That is the narrower claim the September records support. Calling it a reservation would imply the crossing work was bounded before it began. Nothing in the records shows that.

It is the question behind [the loop whose stop condition could never close](https://www.orbytlabs.ai/blog/i-wrote-a-loop-that-could-run-forever). Where does an instruction become a decision the process must obey? Find that point in the execution path. Then exercise it.

Start with work that fits. It must run. Then present work the rule should refuse, and read both the result and the usage record. A system that refuses everything has bounded consumption and no useful behavior. The [audit article](https://www.orbytlabs.ai/blog/ai-code-audit-harness) makes that demand of detectors. A budget control owes the same proof in both directions.

## What belongs in the budget?

Start with the unit. Provider charges, subscription capacity and my attention go in separate columns. A list-price estimate cannot tell me the marginal cash cost of work on a subscription. Cash plus raw human minutes is not a meaningful sum.

Convert time to money if you must, but disclose the rate and show the minutes. That is a valuation, not a charge on an invoice.

Then the scope. Name the account, project or task that owns the limit. Give the period a start and an end. Decide where unfinished work goes when the period closes, so a reset cannot erase outstanding exposure.

Then list every charged action: model calls, cached reads and writes, delegated calls, retries, paid tools and compute. Give a child its parent's budget identity. Send a retry back through admission. A cheaper model changes the estimate. It does not take the action out of the accounting.

The boundary changes the answer. [The energy cost of an AI answer](https://www.orbytlabs.ai/blog/how-much-does-one-ai-answer-cost) works the same problem in another unit. Here, a limit that covers model usage alone has to say that paid tools sit outside it.

Useful output needs its own denominator. The FinOps Foundation's [Unit Economics](https://www.finops.org/framework/capabilities/unit-economics/) separates resource efficiency from business units such as resolved cases. My [research comparison](https://www.orbytlabs.ai/blog/did-the-agents-make-the-business-better) makes the choice concrete: accepted findings and resolved questions answer different questions.

Define the accepted outcome before you measure its cost. Count failed attempts and retries in the numerator. If the budget produces no accepted outcome, report the spending and the zero separately. There is no finite cost per accepted outcome.

## Can two agents spend the same remaining balance?

Yes. This example is synthetic: chosen numbers, not another Orbyt measurement.

A shared limit is $1.00. Settled usage is $0.60. Nothing is reserved. Two workers each propose an action bounded at $0.30.

Both read $0.40 remaining. Both approve themselves. If both actions reach their bounds, total usage reaches $1.20. Each decision was locally affordable.

Both approvals used the same balance.

The fix I propose is one shared admission point, where checking availability and recording the reservation are a single atomic operation. After the first worker reserves $0.30, only $0.10 remains. The second $0.30 request is refused.

**PROPOSED admission rule, not implemented or tested by this trial:**

```text
settled_usage + outstanding_reservations + next_action_upper_bound <= limit
```

The arithmetic is the easy part. Every relevant charge needs a conservative upper bound. Admission must be atomic. Every billable path must participate, including delegation and retries. The ledger must survive process and storage failures.

A typical response cost is not an upper bound. Neither is the largest response seen so far. The bound follows from enforceable action limits and the applicable prices, including any tool work the action can start.

A worked example, with synthetic inputs and illustrative prices that are not any provider's price list. An action may make at most 5 model calls. Each call is capped at 8,000 input tokens and 2,000 output tokens. At $3 per million input tokens and $15 per million output tokens, one call costs at most $0.024 plus $0.030, which is $0.054, and five calls cost at most $0.27. The action may also start at most 3 paid searches at $0.01 each, another $0.03. Its bound is $0.30, the figure the concurrency example above uses. Now let the same action also start a subagent with no turn limit. That component has no enforceable bound, so the action has none either, and admission refuses it until the subagent carries a limit of its own.

If those conditions do not hold, state the weaker promise. Name the largest exposure you can justify. If you cannot bound it, say it is unknown. This design was not tested by the historical controls.

The strongest objection is practical. Conservative reservations can strand useful capacity, and many workloads can tolerate overshoot. That is a reasonable choice. Make it in writing: specify the acceptable exposure and measure what enforcement costs. A promise of a strict cap carries a stricter burden.

## What happens when the receipt never arrives?

The caller stopped waiting. That is all the timeout establishes. It does not show that remote work stopped, that cancellation reached it, or that no charge will arrive.

In the contract I propose, a timeout moves the action into an unresolved state, and the reservation stays out of the pool. Keep unknown exposure reserved until authoritative usage or cancellation evidence settles it.

Settlement must replace the reservation with the final charge in one ledger update. Otherwise another worker can spend the gap between the release and the record. A repeated receipt settles the same action once.

Crash recovery is part of the promise. After a restart, recover outstanding actions before admitting more work. A cancellation request needs a recorded outcome. A late charge belongs to its original action, even after a new budget period has started.

Keep the uncertainty visible. Give a missing receipt an owner and an escalation rule. If the contract stops new work while accounting is down, say so. If it permits more exposure, name that exposure and the authority that accepted it.

A manual override belongs in the record: who approved it, what changed, why, and until when.

## What to do Next

Write the contract before you choose a control. Copy this worksheet into the task's record and fill every answer. An empty cell is an unresolved promise.

| Budget-contract field | Fill before execution |
| --- | --- |
| Unit and limit | Currency or quota unit; cash, estimate or capacity; amount |
| Scope and owner | Account, project or task; accountable person |
| Period | Start, end, reset rule and treatment of outstanding work |
| Counted actions | Models, caches, children, retries, tools and compute; explicit exclusions |
| Price assumptions | Provider, CLI release, model IDs, price version and measurement date |
| Enforcement point | Alert, accounting check, session stop or admission; exact promise |
| Settled usage | Authoritative receipt, action ID and reconciliation method |
| Reservations | Shared ledger, action bounds, atomic admission and durable recovery |
| Missing usage | Timeout, cancellation, restart and late-charge handling |
| Escalation | Who receives unresolved exposure and what pauses until review |
| Manual override | Approver, reason, amount, expiry and audit record |
| Useful result | Acceptance rule; failures counted; human minutes kept separately |

Then write down the receipt each test should produce. Permit an affordable action. Refuse an unaffordable one. Race simultaneous admissions against the same balance. Exercise a delegated child and a retry. Crash and restart with work outstanding. Withhold a usage receipt. Deliver a late charge.

For every case, read the admitted work, the settled usage and the remaining reservation together. A green status alone cannot show whether the contract held. [Verification](https://www.orbytlabs.ai/blog/verification-is-the-new-literacy) starts by opening the thing the claim is about.

Run the smallest authorized test that could contradict the promise. Record the version and the result. Then describe the limit you actually observed.

Mine stopped after it crossed.

Related reading:

- [I Wrote a Loop That Could Run Forever.](https://www.orbytlabs.ai/blog/i-wrote-a-loop-that-could-run-forever) how a declared stop can fail to constrain execution.
- [How Much Does One AI Answer Cost?](https://www.orbytlabs.ai/blog/how-much-does-one-ai-answer-cost) why the accounting boundary belongs beside a cost figure.
- [Did the Agents Make the Business Better?](https://www.orbytlabs.ai/blog/did-the-agents-make-the-business-better) the completed research comparison that separates findings from resolved questions.

<!-- orbyt:chrome:begin -->
This is the markdown version of https://www.orbytlabs.ai/blog/ai-agent-budget-limits. The page there is the canonical copy.
<!-- orbyt:chrome:end -->
