What an AI coding agent's request ledger should actually record

Every call your agent makes is a row. Most people log too little of it.

If you run Claude Code, Codex, or Cursor for more than a day, you generate hundreds of LLM calls you never see individually. A request ledger should record, at minimum, seven things per call: model name and version, input and output token counts, the real dollar cost at the rate that model actually billed, wall-clock latency, which local process made the call, whether the call hit a cache, and a timestamp you can bucket by day or by run. Miss any of these and you can't answer the two questions that actually matter: where did the money go, and why did that one response take four seconds.

Why 'total spend' is not observability

A single number at the end of the month tells you that you spent money. It doesn't tell you whether a stray background process burned through your budget while you were in a meeting, whether one particular agent session looped on a bad tool call and re-sent the same 40k-token context nine times, or whether you're paying full price for requests that a cache should have caught. Those are the actual failure modes. You find them by looking at rows, not totals.

This is also why coding agents specifically need better logging than the average chatbot integration. A chat app makes one call, waits, shows you the answer. A coding agent makes a call, reads a file, makes another call with that file appended to context, runs a shell command, makes another call with the output appended, and so on, sometimes twenty or thirty times in a single task. The context grows with every turn. If you're not logging token counts per call, you won't notice that turn eighteen is carrying 90k tokens of accumulated file reads that turn three didn't need.

The fields that matter

  • Model and version string, not just a friendly label — pricing and behavior both shift between minor versions, and 'the fast model' isn't a queryable field six months later.
  • Input tokens and output tokens, counted separately — output tokens usually cost 3-5x input tokens on most providers, so a call summary that only shows total tokens hides where the spend actually concentrated.
  • Real cost in dollars at the rate that was actually billed, including any prompt-cache discount that applied — a token count is not a cost until you multiply it by the correct per-model rate, and hand-computing that after the fact from a provider's pricing page is where most homegrown logs quietly go stale.
  • Latency from request sent to response complete, ideally with time-to-first-token separated out if you're streaming — a slow model and a slow network look identical in a total-time-only log.
  • The local process or session that issued the call — on a dev machine running multiple agent CLIs, 'something spent $40 today' is useless without knowing whether it was Claude Code, Codex, or a Cursor background agent.
  • Cache outcome — hit, miss, or not attempted — and which cache layer, if you run more than one, so a spike in spend is traceable to a cache that stopped matching rather than a mystery.
  • A run or session identifier that ties a sequence of calls back to one user-initiated task, so you can look at the shape of a whole agent run instead of one call in isolation.

Two fields most tools skip, and why they're the ones that matter most

Process attribution and cache outcome are the two fields I see missing most often, and they're the two that actually change what you do next. Process attribution matters because a modern dev machine isn't running one AI tool, it's running three or four, often at the same time, often with one left open in a background tab. Without knowing which process made a call, a spend spike is a mystery you have to reconstruct from memory. With it, it's a five-second lookup.

Cache outcome matters because caching is where most of the real savings live, and it's also where the real risk lives. An exact-match cache is safe: same input, same output, no ambiguity. A semantic cache is not automatically safe — it matches on similarity, and a near-miss on a tool-calling conversation can return a plausible-looking response that was never actually generated for that context, which is a much worse failure than a slow response. If your ledger doesn't record which layer handled a call and how confident that match was, you can't tell the difference between money saved and a corrupted run.

What good logging looks like in practice

Practically, the ledger should be queryable by day, by run, by model, and by process, without needing to write a script every time. You want to be able to ask 'what did yesterday's refactor cost' and get an answer in one query, and 'what's driving my Opus spend this week' in another. If the log only exists as scrollback in a terminal or a provider's dashboard that aggregates by API key, you've lost the ability to ask either question.

A token count is not a cost. A cost is a token count multiplied by the rate that was actually billed, at the moment it was billed.

How Probe0 approaches this

I built Probe0 as a local proxy that every coding agent CLI on a Mac routes through — Claude Code, Codex, Cursor — after one certificate install, with no per-tool config. One of its modules, Recording, keeps the full request ledger described above: model, tokens, real cost, latency, and which local process made each call. Because it's a proxy sitting between your tools and the providers, it sees every call regardless of which agent issued it, which is the only way process attribution actually works — a tool can't reliably report on itself.

The other modules feed the same ledger with outcome data rather than hiding it: Exact Cache and Semantic Cache both log which layer served a hit, and the semantic layer refuses to match anything carrying tool calls, because a wrong hit on an agentic conversation corrupts the run rather than just wasting a summary. Spend Guard reads the same ledger to warn and then pause before a run blows past a cap. None of this needs a server — it's a local process reading local data, which also means the ledger never leaves your machine.

None of that requires Probe0 specifically. If you're building your own logging around a provider SDK or a different gateway, the checklist above is the one to hold yourself to: model, tokens split by direction, real cost at the billed rate, latency, process attribution, cache outcome, and a run identifier. Everything else is presentation.

Related