Ground Truth

Your Budget Cap Resets on Resume, Which Is Exactly When the Cost Arrives

Mostafa DhouibMostafa Dhouib·6 min read
The short answer

A spend limit on an automated run is a control only if it accumulates across the whole task. On at least one widely used agent runner the cap applies per invocation, so resuming or continuing a task starts the budget again. Cost controls therefore stop working at the precise moment a task goes back for more work, which is when the spend happens. The fix is to track cost outside the tool, against the task rather than the invocation.

Your Budget Cap Resets on Resume, Which Is Exactly When the Cost Arrives

The short answer. Agent runners offer a maximum spend per run, and it is the control most teams reach for first. On at least one widely used runner the limit is scoped to the invocation rather than to the task, so resuming or continuing a run starts the budget over from zero. A task that goes back for changes five times does not have one budget, it has five, and the control silently stops applying at the exact point where cost accumulates. The fix is not a smaller cap. It is to accumulate cost yourself, against the task identity, outside the tool whose cap you cannot trust to span it.

Cost controls on autonomous work are a reasonable first thing to want, and there is usually a flag for it. Set a maximum spend, the run stops when it hits the limit, the exposure is bounded.

The reasoning is sound and it depends on one assumption nobody checks: that the budget spans the thing you think of as the unit of work.

Invocation is not task

When a person asks an agent to do something, the unit in their head is the task. Build the feature. Fix the failing test. Migrate the module.

The runner's unit is the invocation. One start, one process, one accounting.

For a task completed in a single run, these coincide and the cap behaves as expected. For any task that goes back for changes, they diverge, and they diverge in the direction that removes the control.

Resuming or continuing a session is a new invocation. The budget flag applies to it afresh. The spend already incurred on the earlier invocations is not carried forward, because from the runner's point of view those were separate runs.

So a task that is resumed four times with a ten-dollar cap has a forty-dollar ceiling, and nothing anywhere reports forty.

ten dollars
The cap you set
forty dollars
The ceiling you actually have
every individual invocation stayed within its limitno threshold was breached, so nothing alertedthe cheap first time tasks are the ones fully covered
Cost is concentrated in the runs the cap stops covering. A task resumed repeatedly is one the agent is struggling with, so those runs are long, carry large contexts and are expensive. If you had designed the control to fail, this is how.
FigureThe unit in the operator's head is the task. The unit the runner accounts for is the invocation, which is one start, one process, one accounting. For a task that finishes in a single run the two coincide, and for every task that goes back for changes they diverge in the direction that removes the control.

Why this is the worst possible scoping

The distribution of cost across invocations is not uniform. It is concentrated in exactly the runs the cap stops covering.

A task that completes on the first attempt is usually a task that was well specified and straightforward. Those are cheap, and the cap covers them, where it was never needed.

A task that is resumed repeatedly is one the agent is struggling with. Ambiguous requirements, a failing approach, a loop of attempted fixes. Those runs are long, they accumulate large contexts, and they are expensive. The cap resets before each one.

The control is therefore applied with full force to the cheap case and removed entirely from the expensive case. If you had designed it to fail, this is how.

It also hides from monitoring. Each individual invocation stayed within its limit, so nothing alerted, no threshold was breached, and every run looks compliant. The overspend exists only at the task level, which is a level nothing is measuring.

What to do

Accumulate cost against the task, outside the runner. Give every task an identity that survives resumes. Record the cost of each invocation against it. Check the accumulated total before starting another invocation, and refuse when it exceeds the task budget. This is a small amount of code and it is the only version that matches how people think about the work.

Cap the number of resumes as well as the spend. Repeated resumption is itself a signal that something is wrong with the task rather than with the budget. A task on its sixth attempt rarely succeeds on its seventh, and the right action is usually escalation to a person rather than more autonomous attempts.

Alert on the second resume, not the tenth. The useful intervention point is early, when the task can be clarified or reassigned cheaply. By the tenth, the money is spent.

Verify the behaviour yourself. Run a task, hit the cap, resume, and watch what the counter does. The answer is version-specific and documentation is not always explicit about scoping. Ten minutes gives you a fact rather than an assumption.

The same shape, elsewhere

This is one instance of a pattern worth recognising, because it recurs across every control in this space.

A control is scoped to one unit and reasoned about in another. Cancellation is delivered only to work that reports in, so a wrapped process that never heartbeats cannot be cancelled however the interface looks. A retry limit applies per layer rather than per intent, so three layers of three retries is twenty-seven attempts with every individual limit respected. A timeout governs a connection rather than an operation, so an operation that reconnects never times out.

In each case the component is correct by its own definition, and the operator's mental model is at a different granularity. The question to ask of any control is not whether it exists but what it is scoped to, and whether that is the thing you care about bounding.

A spend cap scoped to the invocationreasoned about per taska task that goes back for changes five times does not have one budget, it has five
Cancellation delivered through the heartbeatreasoned about per runa wrapped process that never reports in cannot be cancelled, however the interface looks
A retry limit applied per layerreasoned about per intentthree layers of three retries is twenty-seven attempts with every individual limit respected
A timeout governing a connectionreasoned about per operationan operation that reconnects never times out
Verify the scoping rather than reading it. Run a task, hit the cap, resume, and watch what the counter does. Ten minutes gives you a fact rather than an assumption.
FigureEvery component here is correct by its own definition, and in every case the operator reasons about it at a different granularity than the one it is scoped to. The question to ask of a control is never whether it exists. It is what the control is scoped to, and whether that is the thing you care about bounding.

The honest limit

The behaviour described here is specific to a runner and a version, and flags change. Treat it as a thing to verify rather than a fact to carry, and the general point survives either way: a budget scoped to an invocation does not bound a task, whichever tool is doing the scoping.

Accumulating cost yourself also does not make the work cheaper or better. It bounds exposure and surfaces the tasks that are going badly, which is most of what a cost control is actually for.

FAQ

Does a maximum spend flag on an agent run bound the total cost of a task? Only if the task completes in one invocation. On at least one widely used runner the cap is scoped per invocation, so resuming or continuing starts the budget again and a task resumed four times has four budgets rather than one.

Why is per-invocation budget scoping particularly bad? Because cost is concentrated in the invocations the cap stops covering. Tasks that complete first time are cheap and fully capped. Tasks that are resumed repeatedly are the expensive ones, and the budget resets before each of those runs. The control applies hardest where it is least needed.

Why doesn't monitoring catch the overspend? Because every individual invocation stayed within its limit, so no threshold was breached and nothing alerted. The overspend exists only when costs are summed at the task level, and that is a level nothing is measuring by default.

How should I bound the cost of an agent task properly? Give the task an identity that survives resumes, record each invocation's cost against it, and refuse to start another invocation once the accumulated total exceeds the task budget. Cap the number of resumes as well, since repeated resumption usually signals a problem with the task rather than with the budget.

When should a repeatedly resumed task be escalated? Early, around the second resume, while clarifying or reassigning is still cheap. A task on its sixth attempt rarely succeeds on its seventh, and by then the money has been spent on attempts that were not going to work.

What other controls have this scoping problem? Cancellation delivered only to work that heartbeats, so a wrapped process that never reports in cannot be cancelled. Retry limits applied per layer rather than per intent, turning three layers of three into twenty-seven attempts. Timeouts governing a connection rather than an operation. In each case the component is correct and the operator's mental model is at a different granularity.

Carrying a program like this one?

Tell us the system, the stakes, and the date that matters. You get a straight technical reply from the person who would lead the work, within 24 hours.

Bring us the program