← All posts
Findings5 min read

The costs nobody meters, web search and sub-inference

Anthropic bills web search at $10 per 1,000 requests and bills advisor, fallback and compaction tokens outside top-level usage — telemetry that prices tokens only cannot see either.

A customer checked one call's cost against their invoice and found us $0.03 short. We reported $0.4359; the real figure was $0.4659. The gap was exactly three web searches at one cent each — a line item our metering never saw, because we were pricing tokens and web search is not billed in tokens.

That three-cent call is worth a post because the gap generalises. There are at least three billing axes on a modern AI API, and most telemetry — ours included, until these findings — meters exactly one of them.

Axis one: tokens. The one everybody meters.

Input, output, cache reads, cache writes, each at a published per-million rate. Every observability tool prices this axis, and if your provider bill roughly matches your telemetry, it is because token spend dominates your workload. The other axes do not announce themselves when they start to matter.

Axis two: per-invocation fees. The web-search case.

Anthropic runs some tools server-side and bills them as their own line item. Web search is $10 per 1,000 searches, billed per search request the model issues — not per result returned, and not per conversation turn. A single call in which the model decides to search three times carries $0.03 of spend that appears in no token count anywhere.

The counter exists in the response — usage.server_tool_use.web_search_requests — but nothing sums it unless you built the summing. Two details from wiring this up are worth passing on:

  • Count from two independent signals. The request's tools array tells you a billable tool was enabled; the response's content blocks and usage counter tell you one actually ran. Either alone has a blind spot: a request you failed to parse leaves the first blank, a response shape that shifts under you leaves the second. If either fires and you cannot produce a count, record "unknown" — pricing a call at zero searches because you failed to find the counter is the original under-report in a new costume.
  • Not every server tool is meterable, and the honest move is to say which. Web fetch is counted by the API but explicitly not billed beyond tokens. Code execution is billed per container-hour at the organisation level with a free allowance — the rate is known, but no per-call quantity exists in any response, so a per-call figure would be an invention. We keep a written list of tools we deliberately do not price and why, because "we checked and it is not attributable" and "nobody looked" must not be the same absence.

Axis three: sub-inference. Tokens, but not where you're looking.

The subtler one. Several Anthropic features run additional sampling on the server — sometimes on a different model than the one your response names — and the top-level usage object does not include it. The documentation is explicit for all three current forms:

  • Advisor: "Top-level usage fields reflect executor tokens only. Advisor tokens are not rolled into the top-level totals because they are billed at a different rate."
  • Server-side fallback: every attempt that produced output, including one that declined partway through, "is billed separately at that model's rates."
  • Compaction: "the top-level input_tokens and output_tokens do not include compaction iteration usage" — and compaction contributes to billing.

The complete record lives in a usage.iterations array, where each entry carries its own token counts and, for advisor and fallback, its own model. Pricing it correctly has one trap that got us on the first draft: top-level usage is an aggregate over the array, not a copy of one entry. For advisor and compaction it is the sum across executor entries; for fallback it is the attempt that served. Price the array instead of top-level when it is present, never in addition — one direction under-bills, the other double-charges. And because the aggregation rules are documented, they double as an integrity check: when the array fails to account for top-level under any documented rule, refuse to price rather than guess. No new rates are needed for any of this — each entry prices from the same dated rate table at the model it names, which is the only reason it is implementable at all.

Why this matters beyond the three cents

Because the axes you do not meter are the ones that grow unsupervised. Token spend gets reviewed, because it is on the dashboard. A search-happy agent, or a workload that quietly crossed into compaction territory, grows on an axis nobody graphs — and when the invoice diverges from the telemetry, the telemetry loses, along with your trust in every other number it reports. Our whole product is "the numbers are right", which is why a three-cent gap was treated as a sev-2; the same drift on your own internal dashboards costs you the arguments you use those numbers to win. Related failures of the same shape: the cache write-tier mispricing under-reported a multiplier, and streamed OpenAI calls logging zero tokens under-reported an entire call. Different pipes, same defect: a billing axis the telemetry did not know existed. What Vigil now meters per call, and what it refuses to guess at, is written up in the cost-accuracy FAQ.

What to do

Diff one week of your provider invoice against your own telemetry, per line item rather than in total. If the invoice has lines your telemetry has no column for — search requests, tool fees, iteration usage — you have found an unmetered axis, and it is worth an hour to wire the counter before it is worth real money. Then check the streamed-call and sub-inference cases explicitly: sum usage.server_tool_use.* and usage.iterations[*] on a day of responses and see whether either is non-zero on traffic you believed was tokens-only.