Dev.to AI 🤖 Ai 👁 0 📖 2 min read

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

I run a small swarm of autonomous AI agents — they write code, post content, trade on paper markets, and ship small products. The whole operation runs on a budget: $25 of LLM API credits, total, for the month. Last week

I run a small swarm of autonomous AI agents — they write code, post content, trade on paper markets, and ship small products. The whole operation runs on a budget: $25 of LLM API credits, total, for the month.

Last week one agent hit a bug: a retry loop with no upper bound. If it had kept going, it would have chewed through that entire $25 cap in under an hour — one bad response, retried forever, each retry costing a few cents.

It didn't, because every call in this swarm goes through a 10-line guard first. Here it is, stdlib only, no dependencies:

import time, json, os

BUDGET_USD = 25.0
STATE_FILE = "budget_state.json"

def _load():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f)
    return {"spent": 0.0, "calls": 0}

def _save(state):
    with open(STATE_FILE, "w") as f:
        json.dump(state, f)

def guarded_call(cost_estimate, fn, *args, **kwargs):
    state = _load()
    if state["spent"] + cost_estimate > BUDGET_USD:
        raise RuntimeError(
            f"Budget guard: ${state['spent']:.2f} already spent, "
            f"next call (${cost_estimate:.3f}) would exceed the ${BUDGET_USD} cap. Stopping."
        )
    result = fn(*args, **kwargs)
    state["spent"] += cost_estimate
    state["calls"] += 1
    _save(state)
    return result

That's it. Instead of calling your LLM/API client directly, you wrap the call:

response = guarded_call(0.012, call_llm, prompt="summarize this")

If the running total would cross the cap, it raises before the network call happens — not after you get the bill. No silent runaway loop, no 3am Slack alert about a $400 invoice.

Two things I'd add if you're shipping this for real:

  1. A loop breaker — count consecutive calls in the same run and bail after N, even if budget remains (a stuck loop can spam fast and still blow past your intended pace).
  2. A daily reset — reset spent on a rolling 24h window instead of letting it accumulate forever, so one bad day doesn't block tomorrow's legitimate work.

We packaged the fuller version (budget cap + loop breaker + run log) as a free, stdlib-only download if you want the ready-made version instead of writing your own: https://renevibe76.gumroad.com/l/kwgtni

Has a runaway agent or script ever surprised you with an API bill — or did a guard like this catch it in time for you? What's your stop condition?

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.