Quick Start
1
Disabled by default
A
limit_usd of 0 (the default) disables budgeting — every turn is allowed, exactly like the legacy behaviour.2
Enable with a limit
Set a positive
limit_usd to cap cumulative spend per identity in a rolling window.3
Wire it alongside a durable sink
Pair the policy with
SqliteTokenUsageSink so cumulative spend survives restarts and is shared across processes.How It Works
The gateway reads cumulativespent_usd from a durable sink, then asks the policy whether the next turn is allowed — all before the LLM call runs.
Pass pending_usd to reserve budget for the estimated turn cost before the call, so a single expensive turn cannot overshoot the cap.
Choose Your Budget Knob
PraisonAI has three cost controls — pick the one that matches your scope.Imports
API Reference
WindowedSpendBudgetPolicy
Config-driven, stateless, dependency-free default. Cumulative spend is owned by the sink.
SpendBudgetPolicyProtocol
@runtime_checkable Protocol — any object with a matching check signature satisfies it, no base class needed.
RateLimitDecision
Reused frozen dataclass — identical to the rate-limit policy shape.
SpendBudgetPolicy
Backward-compat alias for SpendBudgetPolicyProtocol. New code should import SpendBudgetPolicyProtocol.
SDK Reference
Full auto-generated API surface for the gateway package.
Configuration Options
The policy supports three levels of control.Common Patterns
$2/day per identity
$0.50/hour burst cap
Custom tenant-tiered policy
Friendly retry-after reply
Best Practices
Always pair with SqliteTokenUsageSink
Always pair with SqliteTokenUsageSink
The policy is stateless — it never stores spend. Back it with a durable sink so budgets survive restarts. An in-memory sink loses budget on every restart.
Pass pending_usd when you can estimate turn cost
Pass pending_usd when you can estimate turn cost
Supplying
pending_usd reserves budget for the turn before the LLM call, so a single expensive turn cannot overshoot the cap before its cost is recorded.Feed oldest_spend_ts for accurate retry hints
Feed oldest_spend_ts for accurate retry hints
Pass
oldest_spend_ts from sink.oldest_spend_ts(...) so rejected users get the precise time until spend rolls out of the window — not a full-window worst case.Prefer per-identity caps; use scope for tenant ceilings
Prefer per-identity caps; use scope for tenant ceilings
Cap per canonical identity for fair per-user limits. Scope-scoped caps are for tenant-level ceilings across many users on one channel.
Related
SQLite Usage Sink
Durable, per-identity spend ledger that feeds this policy
Rate-Limit Policy
Gate on request count instead of cost
Gateway Admission Control
The admission seam this policy plugs into
Agent Max Budget
Cap spend for a single agent run

