Your agent pays for more than tokens
Search APIs, scrapers and metered MCP servers charge per call, and the model picks how many. Why that line is missing from your cost per run.
An agent run spends money in two forms, and only one of them reports itself. Tokens come back on every response as a usage field you can read and price. The tools the run decided to use — a search API, a scraper, a sandbox, a metered MCP server — are a count of calls multiplied by a price on somebody else's pricing page, and that count is chosen by the model while the run is in flight. A cost per run figure derived from token counts alone is a figure for one of the two.
The unit price is reviewed once; the count is set every turn
A comment on a Hacker News thread on 2026-11-13 about per-call payments for a search API puts the asymmetry plainly (source):
At $0.005 a search the unit price looks trivial, but the agents I've run don't search once — they re-search the same question with slightly different phrasing when the first results don't quite fit, and each retry is a fresh paid call.
The price is a constant someone evaluated once, at integration time, against a mental model of how often the thing would be called. The count is a variable the model sets per turn. At the unit price quoted in that comment, two hundred searches is a dollar — small enough that the per-call framing is exactly what stops anyone asking how many, and the run that issues two hundred of them looks from the inside like a run that is trying hard.
The rephrasing matters more than it looks. An agent does not replay a request, it regenerates one, so the second search is not a duplicate of the first to anything in the stack that matches on equality — the argument in a blocked duplicate is still a billed turn, arriving here with a vendor's meter attached to it.
Each of those retries is also charged three times over. The model turn that decided to search is billed in tokens. The search is billed by its vendor at its own rate. The result then joins the transcript and is re-sent as input on every remaining turn of the run, which is tool-result bloat. Two of the three land in your token counts. The middle one does not appear there at all.
The monthly bill was doing attribution work nobody assigned it
The same comment names what changes when the call is paid for individually rather than drawn against a key:
Removing the API key also removes the one place I used to see that happening, the monthly bill.
An API key issued once and billed monthly is an accumulator. Nobody chose it as a measurement surface, but it groups every call made with that credential and presents a total on a schedule, which is why the monthly statement is where most teams have historically discovered a loop. Settle each call on its own instead and the payments stay individually visible while the total stops being produced anywhere. Nothing is concealed; there is simply no longer a page that adds it up.
This is one step past the problem in a provider bill has no agents on it. There the bill exists and cannot be grouped by agent, because the provider never kept that dimension. Here the artefact itself is what goes away. The remedy points the same direction in both cases: an aggregate that is not produced downstream has to be assembled upstream, at the only point where the identity of the thing spending still exists.
A paid call that achieved nothing looks like a paid call that worked
A comment on a Launch HN thread on 2026-11-11 for a tool that generates MCP servers from websites describes the failure mode (source):
A tool can return HTTP 200 while making no useful progress. The agent may then repeat the same call with identical arguments.
Transport success and operation success are different states, and only the first one is on the wire. From the vendor's side the request was served and is billable. From the run's side nothing advanced, so the model tries again, pays again, and adds another result to the transcript that every subsequent turn re-reads. The same commenter describes flagging repeated tool calls by fingerprint and is careful about the limit — "it doesn't block live retries or determine whether caching is safe" — which is the honest shape of the control: it can count the repetition after the fact and cannot refuse it.
There is also a familiar structural point here. How many chargeable tools a run can reach is a configuration line, not a code change: an aggregate MCP endpoint hands over whatever catalogue it was configured with. A tool catalog is billed on every turn covers what that catalogue costs as input tokens whether or not anything is called. This is the other half of the same bill — what the entries cost when the model does call them, at prices that have nothing to do with tokens.
What a run's cost record has to carry
- Billed external calls per completed run, separable by vendor, written against the same run identifier as the model spend. Without the shared key the two halves can never be added.
- The price basis for each vendor — per call, per result, per compute-second, per seat. These do not convert into each other and they certainly do not convert into tokens, so a single dollar column that mixes them hides which lever moves it.
- Attempts per call site, counted by intent. A rephrased retry is the same intent and a new charge. If your counter is keyed on argument equality it will report one.
- Paid calls that returned success and did not advance the task, as a state of their own. That count is the signal; the dollars are the consequence.
- The residual, named. The part of a run's cost your instrumentation does not produce should appear in the report as a line that says so, rather than as the difference between two numbers nobody compares.
How this works in Capsera, and what it does not do
capsera.init() patches the provider clients — Anthropic messages, OpenAI chat
completions, OpenAI embeddings and Google Gemini, sync and async — so every model
call in the process is captured wherever it was made.
@capsera.agent(name="researcher") says who the calls inside it belong to, and
because the agent stack is a contextvars ContextVar rather than thread-local
state, nested agents inherit that identity without anything being threaded
through. capsera.set_session(session_id) puts one identifier on the calls
inside a run, which is the join key the first item in that list needs.
The limit is the obvious one and worth stating in full: a search API is not a
provider client, so nothing in-process sees it and no Capsera figure includes it.
The SDK's record() exists for a model call the interceptor missed and takes
input tokens, output tokens, model and provider — a flat per-call vendor fee has
no shape to go in it. What you get from us is the model half, attributed per
agent, team, task type, session, customer and cost centre, plus budgets checked
before the provider call and on by default at agent, team or global scope. A
budget that blocks a model call does stop the turns that would have issued more
tool calls, which bounds the vendor fees indirectly and does not meter them.
There is no per-run cost ceiling in the product; per-agent budgets are what
ships. And because we store hashes and token counts and never prompt or response
content, we cannot tell you what a tool call asked for.
If the paid surface is an HTTP API whose path you control, meter it where the traffic goes: LiteLLM is MIT-licensed, free and self-hostable, and a gateway is the right place for a spend log keyed on a credential. If you need to read the actual tool inputs and outputs to work out which call returned nothing, Langfuse is open source, free, and stores exactly the content we deliberately do not.
The model half of an agent's cost reports itself on every response. The other half exists only if something in your system writes it down.
Give every agent an identity, a budget, and hard limits.
One line of code. Anthropic, OpenAI, and Google Gemini.
See pricing