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 "@use-crux/core";
import { modelPricing, withCostTracking } from "@use-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.
@use-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.