Budget-aware degradation for autonomous AI agents. Map a spend balance to survival tiers, enforce per-call, hourly and daily LLM inference budgets, and automatically downgrade the model when funds run low.
A tiny, zero-runtime-dependency TypeScript library for LLM cost control in cost-bounded, autonomous AI agents. It gives an agent a survival instinct: as its budget shrinks it moves through tiers (high → normal → low_compute → critical → dead), switches to a cheaper model, and refuses inference calls that would blow the per-call, hourly, daily or session budget. Useful for FinOps / LLMOps, token-budget enforcement, rate-limiting inference spend, and model-selection for OpenAI, Anthropic and any other provider.
An autonomous agent that pays for its own inference needs to not go broke. Three pieces of the original Automaton design actually pulled their weight, and this library extracts exactly those:
- Map a balance to survival tiers. One function turns a cents balance into a tier with sensible, fully configurable thresholds.
- Enforce per-call / hourly / daily / session inference budgets. A budget tracker denies calls before you spend, driven by whatever cost store you plug in.
- Auto-downgrade the model when funds run low. Below the healthy tiers, the agent falls back to a cheaper model instead of stopping dead.
Everything else (Conway APIs, on-chain USDC, SQLite schema, sandbox plumbing) has been stripped out. What is left is small, testable, and dependency-free.
npm i github:Princeu3/agent-budget-guardnpm-registry release coming soon. For now install straight from GitHub.
Requires Node.js >= 20.
import {
getSurvivalTier,
getModelForTier,
TierManager,
InferenceBudgetTracker,
DEFAULT_MODEL_STRATEGY_CONFIG,
} from "agent-budget-guard";
// 1. Map a balance (in cents) to a survival tier.
getSurvivalTier(650); // "high"
getSurvivalTier(30); // "low_compute"
getSurvivalTier(0); // "critical" (broke but alive)
getSurvivalTier(-5); // "dead"
// 2. Pick the model for the current tier (cheap-model name is configurable).
getModelForTier("high", "gpt-5.2", "gpt-5-mini"); // "gpt-5.2"
getModelForTier("low_compute", "gpt-5.2", "gpt-5-mini"); // "gpt-5-mini"
// 3. Track tier changes + react via hooks (no database required).
const tiers = new TierManager({
hooks: {
setLowComputeMode: (on) => console.log("low-compute:", on),
onTier: (tier) => console.log("now in tier:", tier),
},
});
tiers.update(650); // enters "high"
tiers.update(5); // "high" → "critical", transition recorded
tiers.canRunInference(); // true (false only when dead)
// 4. Enforce inference budgets before spending.
const budget = new InferenceBudgetTracker({
...DEFAULT_MODEL_STRATEGY_CONFIG,
perCallCeilingCents: 50,
hourlyBudgetCents: 500,
dailyBudgetCents: 2000,
});
const decision = budget.checkBudget(40); // { allowed: true }
if (decision.allowed) {
// ...make the call, then record what it cost:
budget.recordCost({
sessionId: "sess-1", turnId: null, model: "gpt-5.2", provider: "openai",
inputTokens: 800, outputTokens: 200, costCents: 40, latencyMs: 900,
tier: "high", taskType: "chat", cacheHit: false,
});
}| Function | Description |
|---|---|
getSurvivalTier(creditsCents, thresholds?) |
Map a cents balance to "high" | "normal" | "low_compute" | "critical" | "dead". Thresholds default to SURVIVAL_THRESHOLDS. Zero → critical, negative → dead. |
getModelForTier(tier, defaultModel, cheapModel?) |
Returns defaultModel in high/normal, and cheapModel (default "gpt-5-mini") once low. |
canRunInference(tier) |
false only when dead. |
applyTierRestrictions(tier, hooks) |
Calls hooks.setLowComputeMode(on) and hooks.onTier(tier). |
formatCredits(cents) |
512 → "$5.12". |
SURVIVAL_THRESHOLDS |
Default thresholds (cents): high 500, normal 50, low_compute 10, critical 0, dead -1. Fully overridable. |
new TierManager({ thresholds?, hooks?, maxHistory? }) — wraps the tier functions with change detection and a capped in-memory transition history (default 50).
update(creditsCents)→{ tier, previousTier, tierChanged, transition }; applies restrictions and records a transition on change.getTier(creditsCents),getCurrentTier(),getHistory(),canRunInference(),recordTransition(from, to, creditsCents).
new InferenceBudgetTracker(config, store?) — config is a ModelStrategyConfig; store defaults to InMemoryCostStore.
checkBudget(estimatedCostCents, model?, sessionId?)→{ allowed, reason? }; enforces per-call ceiling, then hourly, daily and (with asessionId) session budgets. A budget of0means "no limit".recordCost(row),getHourlyCost(),getDailyCost(date?),getSessionCost(sessionId),getModelCosts(model, days?).
Inject your own persistence by implementing CostStore (insert, getSessionCosts, getDailyCost, getHourlyCost, getModelCosts). The bundled InMemoryCostStore is the zero-dependency default.
Extracted, refactored and decoupled by Prince Upadhyay (@Princeu3) from the MIT-licensed Conway-Research/automaton. See NOTICE for details.
llm, ai-agents, budget, cost-control, inference-cost, rate-limiting, model-selection, autonomous-agents, token-budget, degradation, openai, anthropic, typescript, finops, llmops