Cost tracking
Attribute model spend to prompts, models, sessions, flows, and steps.
Cost tracking answers a different question than token budgeting. Token budgets protect prompt context windows. Cost tracking tells you what the model call actually cost, where that cost came from, and when a tenant, session, flow, or prompt crossed a spend threshold.
Use withCostTracking() when you want model spend to show up in devtools, the CLI, the TUI, and OpenTelemetry without writing provider-specific accounting code.
import { config } from '@crux/core'
import { modelPricing, withCostTracking } from '@crux/core/cost'
const costs = withCostTracking({
pricing: modelPricing({
'gpt-4o': { input: 2.5, output: 10 },
'claude-sonnet-4-20250514': { input: 3, output: 15 },
}),
budget: {
warn: 1,
limit: 5,
},
})
config({
plugins: [costs.asPlugin()],
})Actual cost vs estimates
Crux records provider-reported cost when the adapter exposes _meta.cost. That is the preferred path because it reflects provider-side billing, routing, and model aliases. OpenRouter responses are the main reference case.
When _meta.cost is missing, Crux estimates from token usage and the pricing table:
modelPricing({
'gpt-4o': {
input: 2.5, // USD per 1M input tokens
output: 10, // USD per 1M output tokens
},
})Estimates are useful for dashboards and guardrails, but they are still estimates. If your provider changes pricing, update the table.
Reports
The tracker keeps an in-memory report for the current runtime process:
const report = costs.getReport()
report.total.cost
report.byPrompt['support-reply']
report.byModel['gpt-4o']
report.byFlow['flow_123']
report.bySession['session_123']Use costs.reset() to clear the process report, or costs.reset(sessionId) to clear one session.
Budgets
warn emits a cost:warn event once. limit emits cost:limit and throws CostLimitError after the call has been attributed.
const costs = withCostTracking({
budget: {
warn: 1,
limit: 5,
onLimit(report) {
console.error('cost limit exceeded', report.total.cost)
},
},
})The failed call is still recorded. That makes debugging straightforward: devtools and OTel can show the exact call that crossed the limit.
Where it appears
The same cost events power all Crux observability surfaces:
crux costshows the latest report and model/prompt breakdown.crux dev --tuishows cost totals and budget events in the terminal dashboard.- Web devtools shows cost totals and budget status on the dashboard.
@crux/otelemitscrux.cost.report,crux.cost.warn, andcrux.cost.limitspans with cost attributes.
Scope
Cost tracking observes model execution. It does not decide which model to call, retry a cheaper model, or split tenant billing storage. Those belong in routing, application policy, or your billing system. The cost tracker gives those layers a reliable signal.