| name | agent-cost-budgeting |
| description | Use this skill when managing AI agent costs. Activate when the user needs to control token usage,
implement cost limits for agents, optimize LLM spending, track agent costs, or prevent runaway
API bills in agent systems.
|
Agent Cost Budgeting
Control and optimize token usage across AI agent systems.
When to Use
- Preventing runaway API costs
- Implementing per-task cost limits
- Optimizing multi-agent token usage
- Tracking and reporting AI spending
- Building cost-aware agent behaviors
Cost Model
interface CostModel {
provider: string;
model: string;
inputCostPer1K: number;
outputCostPer1K: number;
cacheCostPer1K?: number;
}
const COST_MODELS: Record<string, CostModel> = {
'claude-opus-4-6': {
provider: 'anthropic',
model: 'claude-opus-4-6',
inputCostPer1K: 0.015,
outputCostPer1K: 0.075
},
'claude-sonnet-4-6': {
provider: 'anthropic',
model: 'claude-sonnet-4-6',
inputCostPer1K: 0.003,
outputCostPer1K: 0.015
},
'claude-haiku-4-5': {
provider: 'anthropic',
model: 'claude-haiku-4-5',
inputCostPer1K: 0.00025,
outputCostPer1K: 0.00125
},
'gpt-4-turbo': {
provider: 'openai',
model: 'gpt-4-turbo',
inputCostPer1K: 0.01,
outputCostPer1K: 0.03
},
'gpt-4o': {
provider: 'openai',
model: 'gpt-4o',
inputCostPer1K: 0.005,
outputCostPer1K: 0.015
},
'gpt-4o-mini': {
provider: 'openai',
model: 'gpt-4o-mini',
inputCostPer1K: 0.00015,
outputCostPer1K: 0.0006
}
};
function calculateCost(
model: string,
inputTokens: number,
outputTokens: number
): number {
const costModel = COST_MODELS[model];
if (!costModel) throw new Error(`Unknown model: ${model}`);
return (
(inputTokens / 1000) * costModel.inputCostPer1K +
(outputTokens / 1000) * costModel.outputCostPer1K
);
}
Budget Management
interface Budget {
id: string;
name: string;
limitUSD: number;
spentUSD: number;
period: 'task' | 'hourly' | 'daily' | 'monthly';
resetAt?: Date;
alertThresholds: number[];
hardLimit: boolean;
}
class BudgetManager {
private budgets = new Map<string, Budget>();
async checkBudget(budgetId: string, estimatedCost: number): Promise<BudgetCheck> {
const budget = this.budgets.get(budgetId);
if (!budget) return { allowed: true };
const remaining = budget.limitUSD - budget.spentUSD;
const newTotal = budget.spentUSD + estimatedCost;
const utilizationAfter = newTotal / budget.limitUSD;
const crossedThresholds = budget.alertThresholds.filter(
t => budget.spentUSD / budget.limitUSD < t && utilizationAfter >= t
);
if (crossedThresholds.length > 0) {
await this.sendAlerts(budget, crossedThresholds);
}
if (estimatedCost > remaining) {
if (budget.hardLimit) {
return {
allowed: false,
reason: `Budget exceeded: ${remaining.toFixed(4)} USD remaining`,
remaining
};
} else {
return {
allowed: true,
warning: `Budget will be exceeded`,
remaining
};
}
}
return { allowed: true, remaining };
}
async recordSpend(budgetId: string, cost: number): Promise<void> {
const budget = this.budgets.get(budgetId);
if (!budget) return;
budget.spentUSD += cost;
if (budget.resetAt && new Date() >= budget.resetAt) {
budget.spentUSD = cost;
budget.resetAt = this.calculateNextReset(budget.period);
}
}
}
Token Estimation
function estimateTokens(text: string): number {
return Math.ceil(text.length / 4);
}
import { encoding_for_model } from 'tiktoken';
function countTokensAccurate(text: string, model: string): number {
const enc = encoding_for_model(model);
const tokens = enc.encode(text);
enc.free();
return tokens.length;
}
function estimateCallCost(
model: string,
systemPrompt: string,
userMessage: string,
expectedOutputTokens: number
): number {
const inputTokens = estimateTokens(systemPrompt + userMessage);
return calculateCost(model, inputTokens, expectedOutputTokens);
}
Cost-Aware Agent
class CostAwareAgent {
private budget: Budget;
private spent = 0;
constructor(budgetUSD: number) {
this.budget = {
id: 'agent-budget',
name: 'Agent Task Budget',
limitUSD: budgetUSD,
spentUSD: 0,
period: 'task',
alertThresholds: [0.5, 0.8],
hardLimit: true
};
}
async execute(task: string): Promise<Result> {
const estimate = this.estimateTaskCost(task);
if (estimate > this.remaining) {
return this.handleBudgetExceeded(task, estimate);
}
const model = this.selectModelForBudget(task);
const result = await this.llm.complete({
model,
messages: [{ role: 'user', content: task }],
onUsage: (usage) => this.recordUsage(usage, model)
});
return result;
}
private selectModelForBudget(task: string): string {
const complexity = this.assessComplexity(task);
const remaining = this.budget.limitUSD - this.spent;
if (remaining < 0.10) {
return 'gpt-4o-mini';
}
if (remaining < 0.50 || complexity === 'low') {
return 'claude-haiku-4-5';
}
if (remaining < 2.00 || complexity === 'medium') {
return 'claude-sonnet-4-6';
}
return 'claude-opus-4-6';
}
private handleBudgetExceeded(task: string, estimate: number): Result {
const cheaperModel = this.findCheapestViableModel(task);
if (cheaperModel) {
return this.execute(task);
}
return {
success: false,
error: 'Budget exceeded',
partialResult: null,
budgetInfo: {
remaining: this.remaining,
estimated: estimate
}
};
}
get remaining(): number {
return this.budget.limitUSD - this.spent;
}
}
Multi-Agent Cost Distribution
interface AgentCostAllocation {
agentId: string;
allocatedUSD: number;
spentUSD: number;
priority: 'low' | 'medium' | 'high';
}
class MultiAgentBudgetManager {
private totalBudget: number;
private allocations = new Map<string, AgentCostAllocation>();
allocateBudget(agents: { id: string; priority: string }[]): void {
const weights = { high: 3, medium: 2, low: 1 };
const totalWeight = agents.reduce(
(sum, a) => sum + weights[a.priority], 0
);
for (const agent of agents) {
const share = (weights[agent.priority] / totalWeight) * this.totalBudget;
this.allocations.set(agent.id, {
agentId: agent.id,
allocatedUSD: share,
spentUSD: 0,
priority: agent.priority as any
});
}
}
rebalance(): void {
const underSpenders = Array.from(this.allocations.values())
.filter(a => a.spentUSD < a.allocatedUSD * 0.5);
const overSpenders = Array.from(this.allocations.values())
.filter(a => a.spentUSD > a.allocatedUSD * 0.8);
for (const over of overSpenders) {
const needed = over.spentUSD - over.allocatedUSD * 0.8;
for (const under of underSpenders) {
const available = under.allocatedUSD * 0.5 - under.spentUSD;
const transfer = Math.min(needed, available);
if (transfer > 0) {
under.allocatedUSD -= transfer;
over.allocatedUSD += transfer;
}
}
}
}
}
Cost Optimization Strategies
1. Prompt Caching
async function callWithCaching(messages: Message[]): Promise<Response> {
const cachedMessages = messages.map((m, i) => {
if (i === 0 && m.role === 'system') {
return {
...m,
cache_control: { type: 'ephemeral' }
};
}
return m;
});
return anthropic.messages.create({
model: 'claude-sonnet-4-6',
messages: cachedMessages
});
}
2. Model Routing
function routeToOptimalModel(task: string, budget: number): string {
const complexity = assessComplexity(task);
const modelMatrix = {
simple: ['gpt-4o-mini', 'claude-haiku-4-5'],
medium: ['claude-sonnet-4-6', 'gpt-4o'],
complex: ['claude-opus-4-6', 'gpt-4-turbo']
};
const candidates = modelMatrix[complexity];
for (const model of candidates) {
const estimatedCost = estimateCallCost(model, task, 500);
if (estimatedCost <= budget) {
return model;
}
}
return candidates[candidates.length - 1];
}
3. Context Compression
async function compressContext(
context: string,
targetTokens: number
): Promise<string> {
const currentTokens = estimateTokens(context);
if (currentTokens <= targetTokens) {
return context;
}
const summary = await llm.complete({
model: 'gpt-4o-mini',
messages: [{
role: 'user',
content: `Summarize this context in under ${targetTokens} tokens, preserving key information:\n\n${context}`
}]
});
return summary;
}
Reporting
interface CostReport {
period: { start: Date; end: Date };
totalSpent: number;
byModel: Record<string, { calls: number; tokens: number; cost: number }>;
byAgent: Record<string, { calls: number; cost: number }>;
byTask: Record<string, { cost: number; success: boolean }>;
trends: {
dailyAverage: number;
projectedMonthly: number;
topCostDrivers: string[];
};
}
function generateCostReport(usageData: UsageRecord[]): CostReport {
}
Best Practices
- Set budgets early - Don't wait for the bill
- Monitor in real-time - Not after the fact
- Use tiered models - Right-size for the task
- Cache aggressively - Reuse where possible
- Compress context - Less tokens = less cost
- Alert early - 80% threshold, not 100%
- Track by task - Know what's expensive
- Review regularly - Optimize based on data