Get 2,500 events tracked for freeSign up now

All posts
Talha Tayyab5 min readAttribution, Cost per run

A cost figure you computed is not a receipt

A dollar figure for an agent run is derived from token counts and a price table you maintain. What to record so a client or an auditor can check it.

The dollar figure next to an agent run is not something anyone observed. It is a derivation: usage counts the provider returned, multiplied by rates from a table somebody maintains, summed by a rollup you wrote. Someone outside the system — a client being billed for agent usage, an auditor, a finance team — cannot check any of the three, because the report does not say which parts came from the provider and which parts you supplied. Keeping those two halves distinguishable on the stored row is what makes the figure checkable later.

Computed, not observed

A discussion opened on the Langfuse board on 2026-08-28, titled "Verifiable, tamper-evident spend receipts alongside cost tracing", states what a trace gives you today:

Langfuse traces show what an agent did and what it cost, computed from token counts / provider pricing.

It then asks a narrower question: whether that cost can "be proven against the provider's own record", in a form a third party — the post names an auditor, a finance team, and a client being billed for agent usage — can act on.

The word doing the work is computed. This is not a gap specific to one tool; it is how every cost number in this space is produced, Capsera's included. A trace, a gateway spend log and an in-process SDK all arrive at dollars the same way, by pricing usage counts against a table. The difference between a figure that survives being questioned and one that does not is whether the row still records where each input came from.

What the provider told you, and what you supplied

Two sets of fields end up in one number, and they have completely different standing.

The provider reported the model string, the usage counts by class — input, output, cache read, cache write — and, where the client exposes it, a request identifier and a timestamp. Anyone with access to the same account can, in principle, look those up. You supplied everything else: the rate applied to each class, which version of the price table it came from, the agent, run and customer identity, and the rollup that added the rows together. None of that exists anywhere but in your process.

A cost report that presents both as one column gives them the same authority. They do not have the same authority, and the person asking to see the working is asking about the second set.

A missing input prices as zero

A LiteLLM fix from 2026-08-28, surfacing usage in the Bedrock Nova Sonic realtime API, reports both halves failing at once:

response.done always reported zero usage, so spend logged $0 or nothing

Nova Sonic and Nova 2 Sonic had no cost map entries

The provider-side usage never arrived, and the supplied-side price row did not exist. Neither condition raised anything. What reached the log was a line reading zero dollars, which is indistinguishable downstream from a call that was genuinely free. Every rollup built on top of it then reports a total that is correct arithmetic over incomplete rows, which is the failure mode behind tracking tokens not being the same as tracking cost. An unknown has to be its own state, and countable per run, or it is silently priced at nothing.

The price table belongs to somebody else

The rate half of the derivation is usually an artefact maintained outside your repository. A Helicone pull request from 2026-08-31 adds cost entries for a new provider and describes itself as a "data-only change (provider cost registry)". Your dollar figures change when a pull request to someone else's repository merges, which is fine — as long as the row says which version priced it.

The alternative is worse and more common. A Show HN posted on 2026-09-01 for a live model price API describes the status quo directly:

So far, what we've used are hardcoded files or keeping the data in our DB.

Hardcoded assumptions about rates decay in a specific direction: they are written when a family of models behaves one way and are not revisited when a new member does not. A LiteLLM release-day discussion on 2026-09-01, announcing day-0 support for Claude Fable 5.1, states that the new model's cache reads are priced at "0.025x the base input price, where every other Claude model sits at 0.1x". Code carrying the older ratio as a constant prices those cache reads at four times the rate that discussion quotes, on every call, starting the day the model ships — and nothing about the output looks wrong. That is the argument for storing the applied rate rather than recomputing it, which a model having no single price per token makes from the pricing side.

The invoice is the only record you both hold

There is exactly one artefact about your spend that a third party can obtain independently, and it is the provider's own statement for the account. It arrives at account and billing-period grain. It contains no run identifier, no agent, and no customer, so it cannot confirm any single line in your report.

That makes the check one-directional and still worth doing: sum your own rows over the provider's exact billing window and compare the total, then publish the difference. The mechanics of comparing like for like — the same window in the provider's timezone, exact per-model rates, cache reads and writes kept as separate lines — are covered in the questions hub. What matters for evidence is the residual, not the match. A figure handed over without one is asking to be trusted; a figure handed over with one is asking to be checked, and states its own error bar while doing it.

What to keep on the row

  1. The usage counts as the provider returned them, per token class, unmodified and not summed into a single input total.
  2. The rate applied to each class, with its source and the date it was taken. Recomputing a historical row against today's table changes history.
  3. A distinct state for "no usage was reported", counted per run. Zero dollars is a claim; absent is a different claim.
  4. The agent, run and customer identity written at call time. Reconstructing which agent a request belonged to from timestamps and model names afterwards is the join that is not recoverable.
  5. One reconciliation per billing window, residual published. Absorbing the difference into a rounding line removes the only external check available.

How this works in Capsera

capsera.init() patches the provider clients at process start, so the usage counts land in your own record from every call in the process, including calls made by a framework rather than by your code. @capsera.agent(name="planner") on a function you already have supplies the identity half at the time of the call, through contextvars, so nested agents inherit it and no per-request tag or per-agent API key is involved. Budgets are scoped per agent, per team or globally and checked in-process before the provider call, so a blocking budget raises BudgetExceededError and no tokens are spent. Capsera stores hashes and token counts, never prompt or response content, which means what you can hand a client or an auditor is counts and identifiers rather than a transcript.

The limitation is worth stating plainly, because the discussion above is asking for something none of these products ship: nothing here produces a provider-signed attestation of what a run cost. What is achievable today is provenance — keeping the reported and the supplied fields separable, stamping the rate, counting the unknowns, and reconciling the total. If the reason you need the working is to inspect prompts and traces themselves, Langfuse is open source, free, and built for that, and is where the receipts question is currently being asked. If the dollars you are defending come out of a gateway's spend logs, LiteLLM is MIT-licensed, free, covers 140+ providers, and enforces hard budgets per key, team, organisation and model.

Give every agent an identity, a budget, and hard limits.

One line of code. Anthropic, OpenAI, and Google Gemini.

See pricing