What you'll learn: how to record latency, tokens, placeholder-price cost and failures for each evaluated run, why a failed run still costs tokens, and why a lower step limit can look cheaper while answers get worse.
At a glance
Figure 1. What is recorded for one evaluated run
How to read this: tokens are counted where every call passes, so the repair retry and tool-planning calls are included.
- Record latency, tokens in and out, cost, and how each run ended.
- Cost is tokens times a price; the capstone's prices are placeholders.
- A failed run still spent tokens. Count them.
- A run cut off without an error is degraded, not successful.
Scenario
Composite scenario, not a real company. Lumen Industrial Supply's finance lead asks two questions about the product-discovery assistant: what will it cost per month, and how long will a customer wait? The team has accuracy numbers and nothing else. Someone suggests "just lower the step limit to save money".
What you will be able to do
- Say which numbers of a run are measured and which estimated.
- Wrap a provider to count tokens for failed runs.
- Record a failed or cut-off run without stopping.
- Explain why a mean cost hides expensive requests.
Prerequisites
A baseline and two strategies, Calling a provider and AI Architect: Cost Economics for forecasting.
Core ideas
The usage meter
MeteredProvider wraps any provider so UsageMeter records every call, including the repair retry. snapshot turns the totals into the usage object returned with each response.
Verified: capstone/fde-product-discovery-copilot/app/observability/usage.py
def snapshot(self) -> Usage:
cost = (self.input_tokens * self._in_price + self.output_tokens * self._out_price) / 1_000_000
return Usage(
input_tokens=self.input_tokens,
output_tokens=self.output_tokens,
llm_calls=self.llm_calls,
workflow_steps=self.workflow_steps,
estimated_cost_eur=round(cost, 6),
)
Prices come from Settings: 1.0 and 5.0 EUR per million input and output tokens. These are placeholder prices; fill in your provider's published list before quoting a cost. Mock token counts are estimates (words times 1.3).
What the evaluation records, and what it does not
Figure 2. Cost and latency per strategy, 36 questions (from eval/results/latest.json and latest.md)
| Strategy | Tokens in / out | Placeholder cost (EUR) | Mean latency (ms) | p95 latency (ms) |
|---|---|---|---|---|
| baseline | 33384 / 3484 | 0.050804 | 14.14 | 25.1 |
| A | 30828 / 3283 | 0.047243 | 11.905 | 16.5 |
| B | 30680 / 3261 | 0.046985 | 16.254 | 22.6 |
How to read this: tokens and cost repeat exactly on every run; the two latency columns do not.
The filter removes partner-only chunks and B also drops superseded ones, so the model reads fewer tokens: B costs 7.5% less than the baseline (0.050804 to 0.046985).
Latency is different. A re-run on 2026-11-02 gave means of 21.467, 18.973 and 19.028 ms: the ranking changed. The mock answers in milliseconds, so none of this is model latency.
Failures: the harness stops, the meter forgets
grade catches no exceptions, so one raising question stops the evaluation, and the meter inside run_discovery loses that run's tokens.