Budget Caps
A budget is a spend cap you declare up-front on an agent. Every item a run processes accrues cost from its LLM steps; those per-item costs roll up to the run total. When a run's total crosses the cap, Papayya pauses the run and notifies you — it does not hard-kill in-flight work.
Pause-not-enforce is deliberate: a budget overrun stops the run from scheduling more work and flips it to the budget_exceeded lifecycle state, but the items already in flight are preserved so you can raise the cap and resume from where it stopped.
How it works
- You set
budget_usdon your agent (orbudget_centsvia the API). - After each LLM step lands, the control plane prices it — the token counts your provider reported, multiplied by your project rate card — and adds it to the run's accrued total. Steps are never rejected before they run: a completed step's work is always recorded first.
- When the accrued total crosses the budget the run transitions to
pausedand notifies you. It stops scheduling further items and steps; in-flight work is preserved, not discarded. - Resume by raising the cap and re-driving the run — the completed items and their cached steps are untouched (see Durability).
Because the check happens after a step lands, a single step can carry the total past the cap — the overshoot is bounded to one step's cost. That is the deliberate trade: pausing before a step would mean discarding work the customer already paid the provider for.
The number the fence compares is an estimate, not a bill. It is your own rate card multiplied by counts your provider reported, so a rate card that is wrong — or that has no entry for the model a step used — moves the fence. A step whose model is not on your rate card prices at $0 and never contributes to the cap. Set your rate card before you rely on a budget. Billing is metered separately and is unaffected by any of this.
Two errors surface budget conditions to your code:
WorkloadPaused— raised at the next step boundary when a run crosses its declaredbudget_usd. The completed step is checkpointed first; the run is paused (not failed) withreason="budget". Its item is parked in the queue, so nothing picks it back up until you resume — and resume continues the same run from that checkpoint rather than restarting it. (This is the same exception the degradation fences raise —reasonsays which fence tripped.)CreditExhausted— raised when the account's prepaid credit runs out, independent of any single agent's cap.
from papayya import WorkloadPaused, CreditExhaustedInteger math
Cloud runs store budgets and costs in cents (integers) to avoid floating-point drift. When you set budget_usd=1.00 in the SDK, it becomes budget_cents: 100 internally.
This matters for long-running agents that accumulate many small costs — floating-point addition can drift over hundreds of steps, but integer math stays exact.
Infinite loop detection
Beyond budgets, Papayya has a heuristic for detecting runaway items — an item that keeps calling the same tool with the same input repeatedly. When detected, the item is stopped and marked failed, and the run rolls it up in its worst_outcome_status.
Setting budgets
On the agent
from papayya import agent
@agent(name="my-agent", budget_usd=2.00)
def my_agent(input_data):
...@papayya.durable(name="my-agent", budget_usd=2.00) is an alias for the same decorator.
On a scheduled agent
Schedules don't carry their own budget — every scheduled run inherits the agent's budget_usd. Set the cap on the @agent decorator; the @schedule above it only controls when runs fire:
from papayya import agent, schedule
@schedule(cron="0 9 * * *") # 9am UTC daily — each fire is one run, capped at $5
@agent(name="my-agent", budget_usd=5.00)
def my_agent(payload):
...Via the API
POST /v1/agents/{agentId}/runs
{
"input": "...",
"budget_cents": 200
}Choosing a budget
A few rules of thumb, per run:
- Simple work (< 10 steps, Sonnet): $0.10–$0.50
- Research work (10–30 steps, Sonnet): $0.50–$2.00
- Complex workflows (30–100 steps, Opus): $5.00–$20.00
Start conservative and increase based on the actual per-item cost you observe in the dashboard.