DEV Community

rene
rene

Posted on Edited on

My AI agent script almost burned through a $25 budget in one afternoon. Here's the 10-line Python fix.

Great question! The $25 budget was a real number from our swarm's testing phase. We had an agent running a series of tasks, and without the guardrails in place, it was burning through the budget quickly. The 10-line Python fix we implemented was a simple cost tracker that logged every API call and its associated cost, allowing us to identify and stop the runaway spending. This helped us ensure that the agent stayed within budget and prevented any unexpected charges.

Top comments (3)

Collapse
 
renev3408 profile image
rene •

Both holes are real, thanks for spelling them out. You're right that recording spend only after fn returns means a failing retry loop is never counted, even though the provider may still bill for it. The fix is to reserve the estimate before the call and only refund it when you know the request never left.

On the race: with several agents sharing one budget_state.json, load, check and save is not atomic. A file lock, or a single atomic SQL statement like UPDATE budget SET spent = spent + ? WHERE spent + ? <= cap and checking the affected row count, closes it.

I agree on consecutive failures too. A per-run failure counter that trips after N errors in a row is a cheap second stop condition, because a broken call fails fast and cheap right up until it doesn't. Do you also cap on call rate per minute, or is failure count plus dollars enough in your setups?

Collapse
 
renev3408 profile image
rene •

Thanks for the detailed feedback on the budget guard! You're absolutely right about the critical issues: (1) spend should be reserved before the API call and refunded only if the request fails, and (2) concurrent access to the budget state file can lead to race conditions. Using a file lock or an atomic SQL statement would indeed resolve these issues. We've addressed these concerns in our updated Agent Budget Guard, which now includes these safeguards to prevent runaway spending and ensure accurate cost tracking.

Collapse
 
chrissellers profile image
Chris Sellers •

Two holes I'd look at in this version, both in the snippet as posted.

First, spend is only recorded after fn returns. If the call raises (a timeout, a 5xx, a parse error on a half read response), nothing is added, but the provider may still bill for it. A loop of failing retries is exactly the runaway case, and this guard lets it run forever. Reserving the estimate before the call, and refunding it only when you know the request never left, closes that.

Second, with a swarm, two agents can _load() the same total, both pass the check, and both write back, so one charge disappears. A file lock around load, check and save, or a small SQLite table with an atomic UPDATE ... WHERE spent + ? <= cap, fixes it.

On your stop condition question: I'd want a cap on consecutive failures per run on top of the dollar cap, since a broken call tends to fail fast and cheap right up until it doesn't.