Token consumption: an aggregate bill cannot be split back apart

Finance did not ask what the agents cost. They asked which business unit owes what, which is a different question and cannot be answered from a total after the fact.

Finance did not ask what the agents cost. They asked for a number per business unit, tied to the agent that unit actually uses — a narrower question than a total, and the client's framing rather than ours. Two production agents sat on shared cloud infrastructure, so answering it meant attributing spend per agent, not per project and not per environment.

A total answers a different question

The first thing ruled out was a single whole-engagement figure, and the client ruled it out, not us. Add both agents and the shared platform beneath them into one number and nothing takes it apart again: the record of whose work produced which share does not survive the addition. An aggregate is a perfectly good answer to "what did this cost us." It is not an answer to "what does this unit owe."

Labels are necessary and nowhere near sufficient

The obvious fix is to tag every resource with an agent-identifying label and call attribution solved. That was ruled out early, for a reason worth repeating: a label records which agent touched a resource and collects nothing. Every service keeps its own billing record, the marked usage sits where it falls, and no per-agent view exists anywhere. The label is half the mechanism. The missing half is gathering it up.

One label, every surface, one export

What worked was a single consistent label value per agent, applied at every billing surface that agent actually touches, with a billing export as the place the marked usage collects. Three surfaces had to carry it:

  • Model requests — the label travels with the inference call itself, so model usage appears under one agent rather than dissolving into an account-level total.
  • Warehouse queries — each BigQuery job the agent's tools fire is submitted labelled, so query compute is booked against whichever agent caused it, not against the service account or project it happened to execute in.
  • Runtime services — the Cloud Run services behind each agent wear the label at resource level, which picks up standing service cost as well as per-call cost.

Billing Export is what turns those marks into a bill. It lands the labelled usage in BigQuery, where a group-by on the label value produces the per-agent split. That grouping is the step a labels-only approach never reaches: the marks were always there, nothing was collecting them. Once the export was in place, labelled jobs were seen arriving in the dataset soon after they were created — evidence the path ran end to end rather than merely being configured.

Platform services that neither agent owns outright are allocated across agents by an agreed rule. Two agents do not own all the infrastructure between them, and the remainder has to land somewhere explicit rather than quietly falling out of the total.

What transfers, and what is ours rather than yours

The pattern travels. Pick one identifying label, put it on everything your agent stack bills you for, pipe your provider's billing feed somewhere you can query it, and group on the label to get a figure per consuming unit. Every major cloud exports billing this way and tags resources this way, so the shape holds well beyond one provider.

What does not travel is the surface list. The three above are the surfaces this particular stack has. A stack with no per-job warehouse compute, or one answering from a shared inference cluster instead of per-request calls, has a different set — and working out yours is the job, not copying ours. The allocation rule for shared infrastructure travels least of all: it is a policy negotiated with a finance team about who absorbs what, not a technical default. Take the shape as reusable and the specifics as an illustration of how a shape gets applied, rather than a configuration to lift.

The gap this still leaves

Per-request model labels are still missing. The labelling reaches resource level — this job belongs to that agent, this service belongs to this one — but individual inference requests are not yet tagged one at a time. The compute half of the chargeback therefore splits cleanly per agent today, and the model half does not yet split to the same depth. That makes the picture directionally right and incomplete, and naming which half is which beats handing over a total that implies otherwise. Copy the mechanism, stop once the infrastructure is labelled, and you arrive at precisely this gap: the model-request surface needs labelling work of its own, and nothing the infrastructure labels do will reach it.

There is also one quiet failure mode. Miss the label on a resource and its usage drops out of the grouping altogether — the spend is still in the billing data, parked in an unattributed bucket with no owner against it, and nothing announces the omission. It stays invisible until the totals refuse to reconcile and somebody goes looking by hand. A chargeback like this is only ever as complete as the labelling discipline underneath it.

All insights

Get in touch

Talk to us

Tell us what system the answer lives in and who needs it. We'll reply with a view on whether it's a two-week assessment, a five-week pilot, or something else.

Start a conversation →

or info@insightnext.tech

InsightNext on LinkedIn