budget
js/ai/budget.ts
fino:ai/budget — enforceable token, cost, and wall-clock limits.
A Budget is an explicit capability. Create one per run, share one across a
durable session, or inject the same instance into every agent for a tenant.
Reservations are synchronous and atomic within a realm, so concurrent model
calls cannot all spend the same remaining capacity.
import { agent } from 'fino:ai/agent';
import { Budget } from 'fino:ai/budget';
const tenantBudget = new Budget({
tokens: 100000,
usd: 5,
wallClockMs: 60000,
onExhausted: 'suspend',
});
const bot = agent({ model, budget: tenantBudget, defaults: { maxTokens: 1000 } });Interfaces
interface BudgetLimits {
Limits enforced by a Budget.
Properties
tokens?: number
Maximum combined input and output tokens.
usd?: number
Maximum recorded provider cost in US dollars.
wallClockMs?: number
Maximum elapsed milliseconds from budget creation.
interface BudgetOptions extends BudgetLimits {
Construction options for a budget.
Properties
onExhausted?: 'error' | 'suspend'
Exhaustion behavior. error throws BudgetExceededError; suspend
throws SuspendSignal with a serializable budget snapshot.
clock?: () => number
Deterministic clock hook for tests and virtual schedulers.
interface BudgetGrant extends BudgetLimits {
Audited increase to an existing budget.
Properties
grantedAt: number
Timestamp at which the grant was applied.
approvedBy?: string
Operator or system identity that approved the increase.
reason?: string
Human-readable approval rationale.
interface BudgetSnapshot {
Serializable budget state suitable for durable session metadata.
Properties
limits: BudgetLimits
Current ceilings, including approved increases.
onExhausted: 'error' | 'suspend'
Exhaustion behavior retained across restore.
startedAt: number
Budget creation timestamp used for wall-clock enforcement.
usedTokens: number
Committed input plus output tokens.
usedUsd: number
Committed provider cost in US dollars.
reservedTokens: number
Capacity currently reserved by in-flight calls.
reservedUsd: number
Cost currently reserved by in-flight calls.
grants: BudgetGrant[]
Append-only approval history.
Classes
class BudgetExceededError extends Error {
Error thrown when a budget configured with onExhausted: 'error' is spent.
Readonly Properties
readonly limit: 'tokens' | 'usd' | 'wallClockMs'
Limit that rejected the operation.
readonly snapshot: BudgetSnapshot
Durable state at the point of rejection.
Constructors
constructor(limit: 'tokens' | 'usd' | 'wallClockMs', snapshot: BudgetSnapshot)
Create an exhaustion error. Applications normally receive this from a budget check.
class BudgetLease {
Capacity held for one in-flight model call.
Call commit() exactly once on a successful provider response or
release() when the provider fails before reporting usage. Both operations
are idempotent.
Methods
commit(usage: Usage, usd = 0): void
Replace the reservation with actual provider usage and cost.
release(): void
Return reserved capacity after a provider failure or cancellation.
class Budget {
Stateful enforcement surface for AI spend.
Constructors
constructor(options: BudgetOptions)
Create a new unspent budget.
Static Methods
static fromSnapshot(snapshot: BudgetSnapshot, options: { clock?: () => number } = {}): Budget
Restore a budget after restart.
In-flight reservations are cleared because no provider call survives the process. Committed usage, elapsed-time origin, limits, and grants remain.
Methods
check(): void
Check committed usage and elapsed time without reserving capacity.
reserve(predicted: { tokens?: number; usd?: number } = {}): BudgetLease
Atomically reserve predicted capacity before a model call.
grant(
increase: BudgetLimits,
audit: { approvedBy?: string; reason?: string } = {},
): BudgetSnapshot
Increase ceilings after human or policy approval.
The grant is append-only audit data and does not change committed usage.
snapshot(): BudgetSnapshot
Return a detached serializable state snapshot.