SDK Reference
Budget Tracker

Budget Tracker

BudgetTracker tracks token usage and cost during agent execution, and enforces spend limits so a runaway agent can't drain your API budget.

Papayya does not ship per-provider rate cards. LLM pricing changes too often and varies per customer contract, so the tracker uses a neutral default unless you supply your own TokenPricing. For accurate numbers, pass pricing that matches your provider contract.

import { BudgetTracker, DEFAULT_PRICING } from "papayya";
import type { TokenPricing } from "papayya";

Constructor

new BudgetTracker(
  limit_usd?: number,
  options?: {
    pricing?: TokenPricing;
    soft_limit_fraction?: number;
  },
)
ParameterTypeDescription
limit_usdnumber | undefinedMaximum spend in USD. If omitted, tracking is unlimited.
options.pricingTokenPricingUSD per million input/output tokens. Defaults to a neutral placeholder — override to match your contract.
options.soft_limit_fractionnumberFraction of limit_usd at which the soft limit warning fires (default: 0.8).

TokenPricing

interface TokenPricing {
  input_per_million: number;
  output_per_million: number;
}

Supply the numbers you pay — Papayya does not know your provider contract:

const tracker = new BudgetTracker(1.0, {
  pricing: { input_per_million: 3.0, output_per_million: 15.0 },
});

Methods

tracker.record(tokens)

Record token usage from a single LLM call.

tracker.record({ input: 1500, output: 350 });

tracker.exceeded()

Returns true if the total cost has exceeded the budget limit.

if (tracker.exceeded()) {
  console.log("Budget exceeded — stopping agent");
}

tracker.remaining()

Returns the remaining budget in USD, or undefined if no limit was set.

tracker.summary()

tracker.summary();
// { consumed_usd: 0.15, limit_usd: 0.50 }

How it works with agents

When you set budget_usd on an AgentConfig, the SDK creates a BudgetTracker internally using the default pricing. After each LLM call in AgentLoop, token usage from your ModelClient's response is recorded against the tracker. If the budget is exceeded, the run stops with a budget_exceeded status.

For accurate cost numbers, either:

  1. Construct your BudgetTracker with a custom TokenPricing and use the engine directly, or
  2. Call run.record_cost(usd) explicitly after each LLM call in a durable run, using a number you compute from your own pricing.

In cloud runs, budget enforcement happens server-side using integer math (cents) to avoid floating-point drift.

const agent = new Agent({
  name: "my-agent",
  model: myClient, // your ModelClient
  instructions: "...",
  max_steps: 50,
  budget_usd: 1.00, // Hard cap: $1.00 per run
  tools: [],
});