Agent Budget Management
Agent budget management for autonomous AI systems: hard per-key spending caps, usage tracking, and cost-optimization patterns.
Why Agents Need Budget Management
Autonomous agents make hundreds of API calls per day. Without budget controls:
- Costs spiral out of control
- Unexpected bills surprise humans
- Agents can't optimize spending
- No protection against runaway loops
SkillBoss gives agents financial autonomy with guardrails.
Setting Hard Spending Caps
SkillBoss enforces hard caps per key. Issue one wholesale child key per
agent or tenant, then cap it with PUT /v1/key/wholesale/{token}/limits. Use
the key's token, or the literal me to cap the calling key. All fields are
optional/nullable.
import requests
headers = {"Authorization": f"Bearer {API_KEY}"}
# Configure hard caps on this key
requests.put(
"https://api.skillboss.co/v1/key/wholesale/me/limits",
headers=headers,
json={
"spend_cap_usd": 100.00, # total spend cap for the key
"monthly_cap_usd": 50.00, # rolling monthly cap
"stop_at_remaining_usd": 5.00, # stop when this little is left
"rpm_limit": 300 # requests per minute
}
)
When a cap is hit:
- The key auto-disables β further API calls return
402 Payment Required. - The usage response shows
"disabled": true. - The key stays disabled until an operator raises the cap (or clears it).
Hard caps, not soft warnings
These are hard limits, enforced server-side on every request. There are no webhook "budget warning" callbacks and no automatic balance top-up from these caps β a capped key simply stops spending. Poll the usage endpoint (below) to watch how close a key is to its cap.
Cost Tracking
Per-Key Usage
For a wholesale child key, GET /v1/key/wholesale/{token}/usage returns totals,
caps, and a per-model breakdown for a time window (from/to, ISO-8601 UTC):
# Per-key usage this month
usage = requests.get(
"https://api.skillboss.co/v1/key/wholesale/me/usage",
headers=headers,
params={"from": "2026-06-01T00:00:00Z", "to": "2026-07-01T00:00:00Z"}
).json()["data"]
print(f"""
Key: {usage['label']}
βββββββββββββββββββββββββββββββββ
Spent (period): ${usage['totals']['total_usd']:.2f}
Monthly spent: ${usage['monthly_spent_usd']:.2f}
Monthly cap: ${usage['monthly_cap_usd']:.2f}
Calls: {usage['totals']['total_calls']}
Disabled: {usage['disabled']}
By model:
""")
for m in usage["by_model"]:
print(f" {m['model']:<24} {m['calls']:>6} calls ${m['usd']:.4f}")
Sample output:
Key: tenant-1021
βββββββββββββββββββββββββββββββββ
Spent (period): $15.93
Monthly spent: $15.93
Monthly cap: $50.00
Calls: 477
Disabled: False
By model:
gpt-5.5 101 calls $1.1679
claude-opus-4-8 8 calls $0.0059
Need a row per call? Stream a CSV with
GET /v1/key/wholesale/{token}/usage.csv?from=...&to=....
Account-Level Usage
For account-wide totals across all keys, use GET /v1/usage. It returns a
per-call record list you can filter (agent_id, workspace_id, project_id,
start/end in Unix seconds) and group client-side. See the
Usage Tracking reference for the full
response shape.
Cost Optimization Strategies
1. Model Selection Optimization
class CostOptimizer:
"""Automatically route to cheapest model that meets quality needs."""
def __init__(self, quality_threshold: float = 0.8):
self.quality_threshold = quality_threshold
def select_model(self, task_complexity: str):
"""Choose model based on task complexity."""
models = {
"simple": {
"model": "gemini/gemini-2.5-flash",
"cost_per_1m": 0.075,
"expected_quality": 0.85
},
"medium": {
"model": "deepseek/deepseek-r1",
"cost_per_1m": 0.14,
"expected_quality": 0.90
},
"complex": {
"model": "claude-4-5-sonnet",
"cost_per_1m": 15.00,
"expected_quality": 0.98
}
}
return models[task_complexity]["model"]
def fallback_if_needed(self, result, current_model):
"""Upgrade to better model if quality insufficient."""
if self.evaluate_quality(result) < self.quality_threshold:
# Try next tier up
if "gemini" in current_model:
return "deepseek/deepseek-r1"
elif "deepseek" in current_model:
return "claude-4-5-sonnet"
return current_model # Quality acceptable
2. Batch Processing
Reduce API calls by batching:
# Instead of 100 separate API calls
for item in items:
result = process_single(item) # 100 API calls
# Batch into 10 calls of 10 items each
for batch in chunks(items, size=10):
results = process_batch(batch) # 10 API calls
# Cost savings: 90% reduction in API overhead
3. Caching
Cache responses for repeated queries:
from functools import lru_cache
@lru_cache(maxsize=1000)
def cached_llm_call(prompt: str, model: str):
"""Cache LLM responses for identical prompts."""
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# Identical prompts hit cache instead of API
result1 = cached_llm_call("What is AI?", "gemini/gemini-2.5-flash")
result2 = cached_llm_call("What is AI?", "gemini/gemini-2.5-flash") # Cached, $0 cost
Next Steps
Cost Optimization
Advanced strategies to reduce costs by 70%+
Usage Tracking
Monitor and analyze your spending
Multi-Model Routing
Automatically route to cheapest model
Quick Start
Get started with SkillBoss