Cost Tracking
base package For: engineering & operations
Estimate what a decision costs, price it for the platform and tier you actually run on, account for prompt caching, compare models, and check spend against a budget — all from the token counts your decisions already carry. The cost types ship in the base package (no extra).
Install
pip install briefcase-aibriefcase.cost is in the base package — no extra to install.
Estimate a cost
CostCalculator.estimate_cost() takes a model name and token counts and returns a
CostEstimate with separate input and output costs plus a total.
from briefcase.cost import CostCalculator
calc = CostCalculator()estimate = calc.estimate_cost("claude-haiku-4-5", input_tokens=1000, output_tokens=500)
print(estimate.total_cost) # 0.0035print(estimate.input_cost) # 0.001print(estimate.output_cost) # 0.0025print(estimate.currency) # "USD"Price any platform: rate cards
New in 3.2.1By default, estimates use first-party standard list price. A rate card prices
the same call for the platform, tier, and modifiers you actually run on. It is a
forgiving platform × tier × modifiers string — pass it as the keyword-only
rate_card.
calc = CostCalculator()
# Same workload, two ways to buy itstandard = calc.estimate_cost("claude-opus-4-8", 500_000, 50_000)batch = calc.estimate_cost("claude-opus-4-8", 500_000, 50_000, rate_card="bedrock:batch")
print(standard.total_cost) # 3.75print(batch.total_cost) # 1.875 — batch tier on AWS Bedrock, ~0.5x
# List representative cardsprint(calc.get_available_rate_cards())# ['standard', 'batch', 'cached', 'priority', 'flex', 'first_party:fast',# 'bedrock:standard', 'bedrock:batch', 'vertex:standard', 'azure:standard', ...]| Part | Values | Effect |
|---|---|---|
| Platform | first_party · bedrock · vertex · azure | Selects the provider’s price sheet |
| Tier | standard · batch · cached · priority · flex | batch / flex ≈ 0.5×; priority is a premium |
| Modifiers | regional · us · fast | regional / us add ~10%; fast is a premium base rate |
Cards are order-independent and separator-tolerant, so "bedrock:batch",
"batch + bedrock", and "vertex / standard, us" all parse. Omitting rate_card
(or passing "standard") keeps the previous first-party standard pricing.
Prompt-cache billing
New in 3.2.1Prompt caching changes the math: cache reads are billed at a fraction of the input
rate. Pass cache-token counts (all keyword-only) and read the cache_cost on the
estimate.
estimate = calc.estimate_cost( "claude-opus-4-8", input_tokens=0, output_tokens=1_000, cache_read_tokens=100_000, # also: cache_write_5m_tokens, cache_write_1h_tokens)
print(estimate.cache_cost) # 0.05 — 100K cache reads at 0.1x of the input rateprint(estimate.total_cost) # 0.075 — output + cacheWhy it matters: a cache-heavy agent’s bill is dominated by cache reads at 0.1× input. Counting those tokens at full input price overstates the cost.
Compare models
compare_models() estimates the same workload across two models so you can see the
difference before switching.
comparison = calc.compare_models( "claude-haiku-4-5", "gpt-5.4-mini", input_tokens=1000, output_tokens=500)
print(comparison["cheaper_model"]) # "gpt-5.4-mini"print(comparison["savings"]) # 0.0005 — absolute, in USDprint(comparison["percent_difference"]) # 14.29compare_models() also accepts a rate_card so you can compare like-for-like
across tiers or platforms.
Project monthly spend
project_monthly_cost() extrapolates a daily workload to a monthly estimate.
monthly = calc.project_monthly_cost( "claude-haiku-4-5", daily_input_tokens=100_000, daily_output_tokens=50_000, days_per_month=30,)print(monthly) # 10.5 — a float, the projected monthly total in USDCheck a budget
check_budget() compares current spend to a budget and returns a BudgetStatus
with an alert level you can act on.
status = calc.check_budget(current_spend=85.0, budget_limit=100.0)
print(status.status) # "warning"print(status.percent_used) # 85.0print(status.remaining_budget) # 15.0print(status.alert_message)Supported models
The default pricing table covers the current frontier — Anthropic Claude 4.x, OpenAI GPT-5.x, and Google Gemini 2.5–3.x — alongside every previously priced model. See the Changelog for the full list added in 3.2.1.
How cost tracking fits
flowchart LR
A["Decision record"] --> B["token counts"]
B --> C["CostCalculator"]
R["rate_card<br/>(platform × tier)"] --> C
C --> D["CostEstimate<br/>(+ cache_cost)"]
C --> E["BudgetStatus"]
Key classes
| Class / method | Returns | Purpose |
|---|---|---|
CostCalculator.estimate_cost(model, in, out, *, rate_card=None, cache_read_tokens=None, …) | CostEstimate | Per-call cost, optionally for a platform/tier and with cache tokens |
CostCalculator.estimate_cost_from_text(model, text, est_out, *, rate_card=None) | CostEstimate | Estimate from text instead of token counts |
CostCalculator.compare_models(a, b, in, out, *, rate_card=None) | dict | Cost delta between two models (cheaper_model, savings, percent_difference) |
CostCalculator.project_monthly_cost(model, daily_in, daily_out, days, *, rate_card=None) | float | Projected monthly total from daily volume |
CostCalculator.check_budget(spend, limit) | BudgetStatus | Spend vs. budget with alert level |
CostCalculator.get_available_rate_cards() | list[str] | Representative rate-card identifiers |
CostEstimate | — | input_cost, output_cost, cache_cost, total_cost, currency |
BudgetStatus | — | status, percent_used, remaining_budget, alert_message |
The rate_card and cache-token parameters are keyword-only; existing
positional calls behave exactly as before.
Where this fits
Cost Tracking is part of the Operate act: once decisions are flowing, watch what they cost.