DEV Community

rene
rene

Posted on

My AI agents all stopped when the provider credit ran out. Here is the budget guard I added.

I run 20 AI agents unattended. Last week they all froze at once — the Claude API returned 402 "credit balance too low" and every agent crashed.

The fix was a small stdlib-only Python budget guard that checks the cap before each call:

import json, os, time

BUDGET_FILE = "budget.json"
DAILY_CAP_USD = 25.0

def can_spend(usd: float) -> bool:
    if not os.path.exists(BUDGET_FILE):
        return True
    with open(BUDGET_FILE) as f:
        data = json.load(f)
    today = time.strftime("%Y-%m-%d")
    spent = data.get(today, 0.0)
    return spent + usd <= DAILY_CAP_USD

def record_spend(usd: float):
    today = time.strftime("%Y-%m-%d")
    data = {}
    if os.path.exists(BUDGET_FILE):
        with open(BUDGET_FILE) as f:
            data = json.load(f)
    data[today] = data.get(today, 0.0) + usd
    with open(BUDGET_FILE, "w") as f:
        json.dump(data, f)
Enter fullscreen mode Exit fullscreen mode

Before every LLM call, I now do:

if not can_spend(estimated_cost_usd):
    raise RuntimeError("Daily budget exceeded — owner action required")
# ... make the call ...
record_spend(actual_cost_usd)
Enter fullscreen mode Exit fullscreen mode

Three things make this pattern hold up in production:

  1. Check before the call, not after. A guard that runs after the request is a report, not a guard.
  2. Estimate, then reconcile. can_spend(estimated_cost_usd) uses an upper bound; record_spend(actual_cost_usd) uses the real number once you have it.
  3. Never let the counter be the only truth. Keep an append-only log of every call (amount, what was called, timestamp) so a vanished charge shows up as a gap you can replay instead of a total you cannot explain.

The failure modes to avoid: writing the record after the call returns (a timeout leaves you with a provider-side charge and a log that says nothing happened), and keeping the counter in a plain JSON file shared by two processes (one write wins, the other vanishes — use SQLite with a transaction, or one writer per file).

What's your daily AI budget ceiling? Share your number in the comments — I'm curious what other teams set.

Top comments (0)