Finding which sub-agent burned the tokens in one run
Cost-per-step dashboards average many runs. Reconstructing the cost of one expensive run needs a run identifier and an inherited agent identity on every call.
Attributing one run's cost to the sub-agent that caused it needs two identifiers on every call: which run the call belongs to, and which agent made it. Both have to be captured inside the process making the call, because a shared API key carries neither. With both present, a single run decomposes into a per-agent breakdown. Without them, the only available view is an average over many runs, which answers a different question.
The tool people keep building for themselves
Last week someone posted a CLI to Hacker News that does exactly one thing: show which sub-agent burned the tokens in a single run. Their explanation of why they wrote it rather than using something existing:
LangSmith and Langfuse allow ranking on cost per step, but as dashboard widgets aggregating data over many runs over a period of time.
They add that Helicone can do it if you label the call yourself and write the query.
That is a fair description of the shape of those products, and it is worth
being fair back. Langfuse computes cost from ingested usage, supports tiered
pricing and custom model definitions, and nests cost per function through its
@observe decorator — documented
here — and it is free and open source. Cost
analytics is a job it does well. The gap the poster ran into is not accuracy.
It is the unit and the time window.
An average over runs and a single run are different artefacts
Ranking step types by mean cost across a week tells you which kind of step is expensive in general. That is a planning view, and it is the right one for deciding what to optimise next quarter.
It cannot reconstruct the one run someone is complaining about. A run is a tree: a coordinator delegates, delegates delegate, and the total lives in the multiplication rather than in any node. In Capsera's July 2026 scan of 133 public Python agent repositories, the median repository defined 2 agents and the 90th percentile 8 — so the tree is the normal case, not an advanced one (method and figures). Averaging over a week of those trees discards the structure that explains any individual one.
The two views also fail differently. An average gets less useful as variance rises, and cost per run in agent systems is high-variance by construction: the same request may take three steps or thirty depending on what the agent finds. Single-run decomposition is unaffected by variance, because it is not summarising anything.
The usage page you do not own
A related thread on Hacker News reported that Cursor removed cost information from its usage page and CSV export. Whatever the reasoning, the mechanism is worth noticing: when a vendor's usage page is your only ledger, its contents are a product decision, and so is your ability to answer a question about last Tuesday.
The same thread makes the case for measuring your own traffic anyway:
There are huge token efficiency/bloat differences between agents while working on the same tasks, using the same model, in the same environment
A published figure for how much a given harness or agent costs is not transferable, which is the argument for a per-call record of your own rather than a benchmark to read.
What every call has to carry
Three things, and none of them are exotic:
- One run identifier, set once at the entry point and propagated through everything the task triggers, including calls made by sub-agents that did not exist when the run started.
- An agent identity captured at the call site and inherited downward, so a sub-agent composed at runtime reports as itself under its parent. Approaches that need a tag passed per request, or a credential provisioned per agent, cannot express a tree that is built while it runs — see cost attribution for why that constraint decides where instrumentation has to live.
- Exact per-model prices, with cache reads and writes on separate lines. Cache reads cost about a tenth of base input and writes about 1.25×, so a blended rate quietly misprices any run whose cache behaviour changed. That also happens to be the most common source of a mismatch against the provider's invoice.
With those three present, "which sub-agent burned the tokens" stops being a research project and becomes a group-by.
How this works in Capsera
capsera.init() patches the installed provider clients — Anthropic messages,
OpenAI chat completions, OpenAI embeddings and Google Gemini, sync and async —
so instrumentation does not depend on how your graph is wired. set_session()
sets a run identifier at the thread level, which is usually a line in API
middleware rather than a change to agent code. The @agent() decorator names an
agent, and nested decorators inherit through a thread-local context stack, so
the chain arrives on the event without per-call plumbing.
What lands in the database is token counts, model names, timings and hashes. Capsera never stores prompt or response content, which means a run decomposes by cost without a copy of what it said existing anywhere.
Attribution is the prerequisite rather than the whole fix. The enforcement side is separate: budgets scoped to an agent, a team, or the organisation, checked before the provider call, with alert, throttle, or block as the action. But the order matters, and it only runs one way — if you cannot open one expensive run and see which agent inside it spent the money, you are debugging with an average.
Give every agent an identity, a budget, and hard limits.
One line of code. Anthropic, OpenAI, and Google Gemini.
See pricing