BlogCosts

Allocating model spend to the teams and work that caused it

To explain an LLM bill, attribute each request as it passes through a gateway: a key per team or service, tags for the feature and task, and a request ID you can join to the business outcome. Price those requests the way your contract bills them, allocate the costs no single request caused by a rule everyone has seen, and count retries and abandoned runs as cost rather than noise. Then reconcile the total with the provider's own report every month. The result is spend per team and task, and cost per accepted outcome.

Updated

Tag requests where they enter, not after the bill arrives

A provider invoice shows models and tokens, not teams. A gateway can add the missing context. LiteLLM's spend log, for example, records for each request the hashed key, the internal user and team that own the key, any request tags, the model and the endpoint used. Issue a key per team or service and require tags for feature and task. The documentation marks spend tracking and reports by tag as an enterprise feature, so check your licence before relying on them.

Two details decide whether the tags hold. LiteLLM warns that a user field supplied in the request body is self-declared and can move spend away from the key owner, so attribute by key, not by that field. Separate provider workspaces or keys per team also give you a second, independent breakdown: Anthropic's Usage and Cost API groups usage by workspace and API key.

Price requests the way you are invoiced

Gateways estimate cost from a price table. LiteLLM uses its model cost map, flags requests that price to zero because a rate is missing, and documents a procedure for cost discrepancies: align the time ranges, compare token categories including cache, then decide whether the gap comes from ingestion, the formula or the price map. Load your negotiated rates, cache read and write prices and any committed-use terms into that table, or every team's number will be wrong in the same direction.

Allocate what no single request caused

Some cost has no request ID: GPUs you run yourself, including their idle hours, the gateway and observability stack, evaluation runs, re-indexing for retrieval and the platform team's time. Router and classifier calls are a middle case. LiteLLM's auto routing logs its classifier calls with the originating request's identity, so they can follow the request that triggered them. For the rest, choose one rule and publish it:

  • By token share, simple and close to how hosted models bill
  • By GPU seconds, fairer for self-hosted models where long prompts occupy memory
  • As a fixed platform share, for costs that do not vary with use

Changing the rule mid-year makes every trend chart lie, so pick one deliberately and keep it.

Count retries, fallbacks and abandoned runs

A request the user sees once can be billed several times. LiteLLM's documentation notes that its spend-log request counts record each upstream attempt separately, and each row records whether a fallback served it. Agent runs that loop and then fail consume tokens with nothing to show. Report this as its own line per team. It can be the cheapest saving available, because nobody wanted that spend.

From cost per request to cost per accepted outcome

Cost per request rewards cheap answers nobody uses. Join request IDs to an outcome the business already records, such as an extraction accepted without correction or a support draft sent with minor edits. A hypothetical month, with €2,000 of shared platform cost split by token share, 40 percent and 60 percent:

  • Invoice extraction: €4,200 direct plus €800 shared, 111,000 of 120,000 invoices accepted without correction, about €0.045 per accepted invoice
  • Support drafts: €6,800 direct, of which €900 was retries and abandoned runs, plus €1,200 shared, 18,000 of 30,000 drafts sent, about €0.44 per sent draft

The second line is the one to investigate. Fewer than two drafts in three are sent, and about an eighth of direct spend produced nothing. Whether €0.44 is good value depends on the agent time each sent draft saves, which only the support team can estimate.

Reconcile with finance every month

  1. 1

    Start from the invoice

    Take each provider's invoice total and its usage report for the same period.

  2. 2

    Compare with the gateway

    Sum gateway spend for the period and explain the difference line by line.

  3. 3

    Find traffic that bypassed the gateway

    Compare provider usage per API key or workspace with gateway spend for the same keys and period. Usage the gateway never logged points to direct calls, even when they carry a valid key. Anthropic also reports console playground usage with no API key and default-workspace usage with no workspace ID, so those appear as separate unattributed lines.

  4. 4

    Publish showback

    Share spend per team, the waste line and cost per accepted outcome, as the FinOps Foundation's guidance on AI suggests, before any internal charging.

Questions

Should we charge teams for their LLM use or only show them?

Show first. Until the gateway total reconciles with the invoices for a few months in a row, charging creates disputes about the numbers instead of decisions about the work.

Does this cover coding agent subscriptions too?

Partly. Seats and subscriptions are billed per person, not per request, so they need their own line next to metered usage. Cloudsail's LLM cost optimisation service covers that breakdown for coding agents specifically.

Do we need a gateway to do this?

Not for a coarse split. Separate provider workspaces or keys per team already give spend by team. Task-level tags, cross-provider totals and joins to business outcomes are much easier with one gateway in the path.

Talk to an engineer

Bring one piece of work you would like to improve. The call takes 30 minutes and needs no access to your systems or your data.

Booking runs on Google Calendar.

Prefer to write first? Leave your email and a few lines, and we reply with times.

The button prepares an email in your own email program, for you to send. Privacy policy (draft)