Cost & attribution
Your bill tripled last month. Find out which team, feature or customer did it, and how much to trust the answer.
On this page
Someone forwards you the provider invoice with one line of commentary: this is three times last month, what happened? You have an hour. The invoice groups by model, which tells you that most of it went to your most expensive model, which you already knew. It cannot tell you which team, which feature, or which customer sent those requests, because the provider never knew.
That gap is the whole subject of this section. A provider bills an API key. You need to bill a decision someone in your organisation made. Nothing in between records the connection unless something is sitting in the request path writing it down.
TokenTriage writes one costed row per request, and everything here is an aggregation of those rows. What makes the aggregation worth reading is the second half of the promise: every figure says how much to trust it. A total names the rows it could not price rather than counting them as free. A saving says whether it was measured or modelled. A recommendation that cannot support its own number prints the number it would have needed instead.
The hour you have
Here is the order that answers the question fastest, with the page that covers each step.
- Look at what already fired. If spend jumped, the detector has probably already flagged the hour and ranked what drove it. Anomaly detection.
- Split the total by something meaningful. Model, agent, step class or trace, from the terminal, in one command. Read your spend from the terminal.
- Split it by your nouns: team, tenant, feature, customer. This is the step that needs configuration you may not have turned on yet. How a dollar gets a name.
- Check the figure before you send it on. Which rows were excluded, whether the number is measured or modelled. How to read a cost figure.
- Tie it back to the invoice, and see what the two sides disagree about. Reconcile against a provider invoice.


↑ Excludes 6 unpriced rows from all totals — spend the price catalogue cannot cover is counted and disclosed, never quietly folded into the total as a zero. The total itself carries EST because some of its rows are estimated.
What is on by default, and what is not
This matters more than usual here, because two of the defaults decide whether the section’s best surfaces exist for you at all.
| Thing | Default | What you lose without it |
|---|---|---|
| The costed ledger row | on | nothing: every proxied request is costed and logged |
top and report |
on | nothing: they read the log directly, no setup |
| Anomaly detection | with the dashboard | nothing beyond turning the dashboard on |
ledger.dimensions.enabled |
off | team, tenant, feature and per-customer attribution |
analytics.enabled |
off | rollups, recommendations, forecasts, chargeback, exports |
dashboard.index.enabled |
off | the index that analytics is built on |
A fresh install costs everything and can group by less than you expect. It knows the model, the tier, the provider, the endpoint, and whatever trace identity your client sends. It does not know your tenants, because nothing on the wire told it. Turn on business dimensions is the ten-minute fix, and it is worth doing before you need it, because dimensions apply to rows written after you turn them on and are not applied retroactively.
The two ways a figure is produced
Every number in this section comes from one of two paths, and knowing which changes what you can ask.
The decision log, a JSONL file, is the record. top and report read it directly with no
database, no index and no configuration. That is the whole of the terminal experience, and it
survives losing everything else.
The derived index is a SQLite file rebuilt from that log. It carries an hourly pre-aggregation on eight attribution dimensions, which is what makes a month-scale question finish quickly, and it is what every dashboard cost surface, export and detector reads. Delete it at any time and rebuild it from the log.
Both answer the same question with the same number. That is the constraint the section is built on, and what the rollups make cheap explains where the pre-aggregation helps, where it silently steps aside, and the two dimensions it leaves out for good.
What this section covers
The pages fall into four groups.
Attribution, where a dollar’s name comes from. How a dollar gets a name explains the three authorities behind a row’s dimensions and why two of them are not interchangeable. Turn on business dimensions is the configuration. What the rollups make cheap covers the pre-aggregation and its limits.
Trust, how much a figure is worth. How to read a cost figure teaches the vocabulary as it appears on cost surfaces, and verdicts, methods and baselines is the lookup table behind it.
Action, what to do about it. Recommendations covers what the engine proposes and what it refuses to propose, the eight recommendation types lists them, and the realized measurement is the only thing on the site that produces a measured saving. Anomaly detection watches for spend that broke pattern.
Settlement, getting the number out of the building. Reconcile against a provider invoice, forecast spend, chargeback, showback and FOCUS exports, and what the measurement itself costs.
What this section does not cover, and where that material lives
Limits and refusals. Everything about capping spend belongs to governance: budgets, rate limits, and what happens when one is hit. The division is enforcement versus reporting. Governance decides whether a request goes through; this section reports what the ones that did went on. A budget that was passed is an enforcement property, and a spend report is ours.
Ledger field definitions. Every field on a costed row, with its type and when it is absent, is in decision ledger fields.
Where the prices come from. The pricing snapshot behind a figure, the catalog key the
price resolved under, and the estimated and unpriced flags are defined field by field in
the cost block of a ledger row.
Cache savings arithmetic. The provider’s prompt cache and TokenTriage’s response cache produce two savings figures that are kept apart, and the reasoning is in two kinds of cache savings.
The verdict vocabulary’s definitions. The honesty model owns them. This section teaches how they show up on cost surfaces and links there for the rules.
Where it can go wrong
The most expensive mistake in this section is not a wrong number. It is a right number read as though it covered everything.
A total is computed over the rows it could price. If your ledger contains a model your price table has no entry for, such as a fine-tuned model or a provider added last week, its rows are excluded and counted, and the count is printed beside the figure:
COST excludes 35 unpriced rows of 412 (no price resolved; the $0 is a missing price, not $0 of spend)
Read that line before you read the dollar above it. Thirty-five unpriced rows out of four
hundred is a total you can send on with a caveat. Thirty-five out of forty is not a total at
all. The same rule holds on every surface here: exports leave the cell empty, the API sends
null, and no path anywhere turns an unpriceable row into $0.00.