Skip to content

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

Terminal window
pip install briefcase-ai

briefcase.cost is in the base package. No extra to install.

Estimate a cost

Both languages price one invocation from the same table: a model name, an input token count, and an output token count in; separate input and output costs plus a total out.

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.0035
print(estimate.input_cost) # 0.001
print(estimate.output_cost) # 0.0025
print(estimate.currency) # "USD"

Price any platform: rate cards

New in 3.2.1

By 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 it
standard = 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.75
print(batch.total_cost) # 1.875 — batch tier on AWS Bedrock, ~0.5x
# List representative cards
print(calc.get_available_rate_cards())
# ['standard', 'batch', 'cached', 'priority', 'flex', 'first_party:fast',
# 'bedrock:standard', 'bedrock:batch', 'vertex:standard', 'azure:standard', ...]
PartValuesEffect
Platformfirst_party · bedrock · vertex · azureSelects the provider’s price sheet
Tierstandard · batch · cached · priority · flexbatch / flex ≈ 0.5×; priority is a premium
Modifiersregional · us · fastregional / 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.1

Prompt 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 rate
print(estimate.total_cost) # 0.075 — output + cache

Why 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 USD
print(comparison["percent_difference"]) # 14.29

compare_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 USD

Check 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.0
print(status.remaining_budget) # 15.0
print(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. Version 4.2 adds Amazon Nova Premier, Pro, Lite, and Micro plus Amazon Titan and Cohere embedding rates on Bedrock.

Platform-qualified Bedrock IDs normalize before lookup. In Python use briefcase._native.normalize_model_id; in Node.js use normalizeModelId from @briefcase-ai/native. Region and vendor prefixes, date stamps, and version suffixes collapse to the pricing-table key.

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 / methodReturnsPurpose
CostCalculator.estimate_cost(model, in, out, *, rate_card=None, cache_read_tokens=None, …)CostEstimatePer-call cost, optionally for a platform/tier and with cache tokens
CostCalculator.estimate_cost_from_text(model, text, est_out, *, rate_card=None)CostEstimateEstimate from text instead of token counts
CostCalculator.compare_models(a, b, in, out, *, rate_card=None)dictCost delta between two models (cheaper_model, savings, percent_difference)
CostCalculator.project_monthly_cost(model, daily_in, daily_out, days, *, rate_card=None)floatProjected monthly total from daily volume
CostCalculator.check_budget(spend, limit)BudgetStatusSpend vs. budget with alert level
CostCalculator.get_available_rate_cards()list[str]Representative rate-card identifiers
CostEstimateinput_cost, output_cost, cache_cost, total_cost, currency
BudgetStatusstatus, percent_used, remaining_budget, alert_message

The rate_card and cache-token parameters are keyword-only; existing positional calls behave exactly as before.

Limits

Prices are a table compiled into the release, not a live feed. When a provider changes a rate, the number you get stays wrong until you upgrade the SDK. Nothing here calls out to a pricing API.

Model names must match exactly. estimate_cost("Claude-Haiku-4-5", ...) raises ValueError: Unknown model. There is no case folding, alias table, or fallback to an average price, so a provider’s newest model id fails until the table catches up. An error beats a made-up number, but you have to handle it.

Input plus output above the model’s context window raises ValueError: Invalid token count. A 400,000-token estimate for claude-haiku-4-5 is an error, not a large number.

estimate_cost_from_text is a divisor, not a tokenizer. It takes the byte length, divides by 4 (3 for non-ASCII text) and adds 5%. Good for an order of magnitude; use the token counts your provider returns for anything you bill against.

Every amount is USD, and no negotiated discount or commitment rate is modeled. compare_models and project_monthly_cost inherit all of the above: a projection is list price times volume, not a forecast.

API reference

briefcase.cost has the full signatures, including the keyword-only rate_card and cache-token parameters.

Where this fits

Cost Tracking is part of the Operate act: once decisions are flowing, watch what they cost.