What changed: Updated 18 August 2026: added why attribution must be captured at call time rather than reconstructed, and how budget alerting differs from a budget that actually stops work.
Disclosure: BlueBear sells a gateway that records the per-call attribution described here, so we have a commercial interest. The measurement model itself is independent of tooling, and the article says plainly which parts need no product at all.
The question that arrives the week after it works
The pilot is finished, the agent is genuinely useful, and you have opened it to a department or to customers. Then finance asks a reasonable question: which team should this be billed to? Or a customer asks what their usage costs. Or you simply want to know whether the thing is worth continuing.
The provider invoice cannot answer any of those. It is one total, aggregated to an API key, arriving a month later. If several teams share that key -- and at the start they always do -- the invoice is a single undifferentiated number describing work done by many people for many reasons.
Why later analysis will not rescue you
This is the part worth internalising before anything else: attribution is decided at the moment of the call, not at reporting time. If a request does not carry who it was for, nothing downstream can reconstruct it. You can infer from timestamps, and that inference is exactly as defensible as it sounds.
The failure is quiet and specific. Client libraries read an API key and an endpoint from the environment, because those are the two things they need to work. Nothing about the calling team, workflow or end user travels with the request unless the caller deliberately attaches it, and there is usually no environment variable for that. So a system can be fully instrumented, storing token counts and costs faithfully, and still produce a table where the owner column is empty on every row. Everything was recorded except the one field that makes it divisible.
The practical consequence is a deadline you do not get told about: the months already billed stay unallocatable forever. Adding attribution in March does not explain January.
The five things that actually make up the cost
Who it was for
The base layer. Every call needs an identifier for the tenant, workspace, or user it served, recorded alongside the model, the token counts and the resulting cost. Once that exists, allocation and chargeback are a query rather than a project. The OpenTelemetry semantic conventions for generative AI are a reasonable shape to follow, mainly so the fields mean the same thing across services.
The attempts that did not count
A failed call is billed exactly like a successful one. An agent that needs three attempts to produce something acceptable costs roughly three times its headline price per finished piece of work. If your reporting counts spend per day and completions per day separately, this never becomes visible -- it just looks like the model is expensive.
Long context compounds it. When each step re-sends the accumulated conversation or document set, input tokens grow with every turn even where the new instruction is a sentence. The bill grows with the length of the interaction rather than the size of the request, which is counterintuitive until you see it in the token counts.
The human time
If a person checks the output before it is used, that review is part of the unit cost. It is usually the largest component and the one nobody books. An agent that costs eleven cents a call and eight minutes of a specialist's attention is not an eleven-cent agent. Excluding it produces a number that looks excellent and cannot be compared against what the work cost before.
You do not need a timesheet system for this. An approve or reject action with a timestamp is enough to get a defensible average.
Savings you should count separately
Prompt caching materially reduces the price of repeated input, which means a workload can become cheaper with no change to the model or the prompt. Record that saving as its own figure rather than letting it disappear into a lower total. Otherwise you cannot distinguish an efficiency improvement from a fall in usage, and those two facts call for opposite responses.
Capacity you committed to
If you have reserved or committed capacity, actual consumption has to be tracked against it. Unused commitment is real spend attributable to nobody, and it is the component most likely to be quietly wrong for a whole quarter.
Cost per approved outcome
Roll those together and you get the only number a budget holder can act on: the total cost of producing one result somebody accepted. All attempts, plus review time, divided by outputs that were actually used.
It is useful because it is comparable. It sits next to what the task cost before, it can be tracked as the agent improves, and it survives contact with a finance conversation in a way that a token count does not. It also reprices decisions correctly: an agent on a cheaper model with a poor first-pass rate frequently costs more per approved outcome than one on an expensive model that gets it right first time. Spend-per-call reporting says the opposite.
Four checks
- Pick last month's provider invoice and split it by team. If you cannot, you have an attribution gap, and every month it continues is permanently unallocatable.
- Count attempts, not just completions. If your records cannot tell you how many calls produced a discarded result, your cost per outcome is understated by the retry rate.
- Ask what a reviewed output costs including the review. If human time is not in the figure, the figure is not comparable to the thing it replaced.
- Check the owner column is populated, not merely present. A schema with a tenant field that is null on every row is the most common version of this problem, and it looks like success from the outside.
What this costs to put right
Attaching an identifier to each call is small work -- a header or a field, set in one place if your calls go through a single client. Recording attempts and approvals is a little more, because something has to know an outcome was accepted. Review time is mostly a decision to capture a timestamp you are already generating.
None of it requires buying anything. What it does require is doing it before you need the answer, because the reporting layer cannot invent a fact the call never carried.
What to do about the months you cannot allocate
Once attribution is on, you still have a period behind you that cannot be divided. Pretending otherwise is how a chargeback conversation goes badly.
Say plainly that the period is unallocatable, give the date attribution started, and apportion it by something defensible and clearly labelled as an estimate — headcount, seat count, or share of the first fully-attributed month. What matters is that the basis is stated rather than the number being precise. A finance team can work with a documented estimate; what they cannot work with is a precise-looking figure whose derivation nobody can explain.
Then stop reporting on that period. Its only remaining use is as the baseline that shows attribution starting.
The number to report once you can
Resist reporting total spend by team. It answers a question nobody asked and invites the wrong response, which is asking the highest-spending team to spend less regardless of what they are getting.
Report cost per approved outcome, per team, next to the volume of outcomes. Together those two say whether a team is expensive because it is doing more work or because its work costs more per unit — and only the second is a problem worth acting on.
The teams that look worst on raw spend are frequently the ones delivering most, and a report that cannot distinguish those two cases will reliably push effort away from wherever the agents are working best.
BlueBear AI FinOps Allocation Ledger
The FinOps Foundation reports that AI spend management is now widespread and a leading priority. For agents, a provider invoice is still only one ledger input. BlueBear’s useful allocation grain is the governed workflow and its accepted outcome.
| Cost pool | Allocation key | BlueBear evidence | Owner input |
|---|---|---|---|
| Model | Request or session usage | Model route, tokens, estimated rate, retries, and fallback. | Approved rate table and accounting period. |
| Tool/API | Tool invocation | MCP connection, action, count, receipt, and originating session. | Vendor rate and free-tier treatment. |
| Runtime | Documented workload allocation | Workspace, deployment, execution time, and capacity metadata where available. | Allocation method for shared capacity. |
| Human review | Active handling time | Approval and exception events, owner, status, and elapsed time. | Active-time rule and loaded labor rate. |
| Business result | Accepted outcome | Terminal workflow state and downstream outcome identifier. | Acceptance definition, value, and reconciliation source. |
Report attempts, accepted outcomes, acceptance rate, cost per attempt, and cost per accepted outcome together. A lower model bill is not an optimization if rejection, review, latency, or exception costs rise enough to damage the business result.
Use the BlueBear cost-per-outcome calculator to challenge an allocation before publishing it.
Attribution is an instrumentation decision, not a reporting one
The most consequential fact about AI cost allocation is that almost none of it is recoverable afterwards. A provider invoice knows an API key. It does not know which customer, which feature, or which workflow version caused the spend, and no analysis will recover information that was never captured. Every day without attribution is a day of permanently un-analysable spend.
Three implementations, in ascending order of robustness. A key per customer is genuinely fine at small scale and requires no code, but breaks when a customer spans products or a rotation loses the history. Metadata on every request works well and fails silently — a background job or a new endpoint written by someone who never read the convention produces untagged spend that looks like nothing at all. The robust version derives the identifier from the authenticated caller rather than trusting the application to supply it, which is how BlueBear's gateway resolves the tenant: a caller cannot forget to attribute, because it never supplies the attribution.
A budget that warns and a budget that stops are different controls
Alert thresholds tell you afterwards. A ceiling changes what happens. Both are useful and they should not be confused on a dashboard, because only one of them bounds your exposure.
In our billing services the alert types are explicit — budget.remaining_percent, budget.remaining_credits, budget.expiring_soon and budget.exhausted — with severity escalating as the threshold tightens. Two design points are worth borrowing regardless of platform. Exhaustion short-circuits: when the balance is gone, a single exhausted alert is emitted and the low-balance and expiry alerts are suppressed, because at that point they are noise competing with the one message that matters. And exhaustion is a hard stop enforced at more than one gate — a pre-flight check before a session starts and a credit gate before a metered call — rather than one more warning in a queue.
The reason to enforce at several gates rather than one is that they fail differently. A ceiling checked only at session start does nothing about a long-running session; a ceiling checked only per call lets a session begin that can never complete.
Two allocation traps worth naming
- Zero-priced models in the catalog. A model whose price is unset does not cost nothing; it costs an unknown amount that lands in your blended average as a zero. Flag them rather than silently including them.
- Estimates presented as observations. Keep the derivation with the number. Ours records whether a cost projection came from an explicit token demand or a message-size heuristic, and any calibration carries the sample count it was derived from. A projection built on four samples and one built on four thousand are not the same evidence, and a single figure hides which you have.
Where to go deeper
- Find your most expensive LLM calls — the six cuts, and which field each one requires.
- Why AI agent costs spike — the diagnostic path when an allocated line moves.
- Establish a cost baseline — the window and rate-source discipline allocation depends on.
- Reducing n8n agent costs — what attribution looks like when the workflow engine cannot supply it.
Questions people actually search for
- how do i allocate ai agent costs to departments or customers
By recording the owner on the call itself, not by analysing the invoice afterwards. Provider billing is aggregated to an API key, so a single key used by several teams produces one number that cannot be divided later. Send an identifier for the tenant, workspace or user with every request, store it next to the recorded token counts and cost, and allocation becomes a query. Add it after the fact and the months already billed stay unallocatable.
- what is cost per approved outcome for ai agents
It is the total cost of producing one result somebody accepted, including the attempts that were thrown away and the human time spent checking. If an agent needs three attempts and eight minutes of review to produce one usable report, the cost of that report is all three model calls plus the eight minutes -- not the price of the successful call. It is the only figure that compares sensibly against whatever the task used to cost.
- why is my ai spend higher than the number of successful tasks suggests
Usually retries and discarded work. A failed attempt is billed identically to a successful one, so an agent with a low first-pass rate can cost several times the headline price per finished task. Long context is the other common cause: re-sending an entire conversation or document set on every step means input tokens grow with each turn even when the request is short. Both are invisible if you only track spend per day rather than per outcome.
- should we track cache savings in ai cost reporting
Yes, as a separate figure rather than folded into the total. Prompt caching lowers the price of repeated input substantially, which means a workload can get cheaper without anyone changing a model or a prompt. If the saving is not recorded separately you cannot tell an efficiency gain from a drop in usage, and the two call for opposite responses.
