Cost & Quality
Cost & Quality puts spend and quality on the same screen and answers one question for each of your two big LLM bills: could a cheaper model do this job without losing quality I can actually measure? It leads with the single recommended move and the one button that matters — Test before switching — and keeps the raw sweeps and scorer comparisons a click away as evidence.
The page has three tabs:
| Tab | Answers |
|---|---|
| Overview | What am I spending, what could I save this month, and what is the one move to make next? |
| Agent Model | Can a cheaper model run the agent and still pass my golden suite? |
| Judge Model | Can a cheaper model judge the agent and still agree with my gold labels? |
At a glance
| Where it lives | Cost & Quality in the left nav, under Evaluate → /cost-quality |
| Tabs | Overview · Agent Model · Judge Model (?tab=overview|agent|judge) |
| Key API routes | GET /cost-optimization/summary, GET /cost-optimization/judges, GET /cost-optimization/frontier, GET /cost-optimization/moves |
| Needs | Ingested traces (agent spend), at least one LLM judge that has run (judge spend), gold labels to compare judge models, a finished model sweep to compare agent models |
| Scope | The agent (project) you’re viewing. Anyone with read access can see it |
| Reads only | Nothing here spends money and nothing switches a model for you |
| Dollars | Every dollar amount on these tabs is shown as a whole number, rounded up — no cents |
Old links still work. /model-bench opens this page, /model-sweeps opens the Agent Model
tab, and /cost-optimization opens Overview. Individual sweeps (/model-sweeps/{id},
/model-sweeps/{id}/compare) and scorer comparisons (/scorer-comparison/{id}) are unchanged.
The version slice
A Neens project is one agent, so “which agent?” is never a question this page asks. The useful
sub-slice is which version of that agent produced the trace, read from the neens.version_label
attribute your traces carry:
span.set_attribute("neens.version_label", "v2.4.0")- Every label you have sent appears in the version selector, newest first. The label with the most recent trace is live, and it is the default selection on the tabs that have a version control — you land on the build you are actually running, not on an “all versions” blend.
- Traces with no label form their own unversioned row. They are never folded into the live version: “we don’t know which build this was” and “this was the current build” are different facts.
- Nothing breaks if you never send the attribute — you get one unversioned row and everything else works. Adding it later starts the split from that point forward; it does not rewrite history.
Where the version control appears differs by tab, because the useful slice is different:
| Tab | Time range | Version |
|---|---|---|
| Overview | Picker in the header | Header select, defaults to live |
| Agent Model | Picker in the header | In-body dropdown, defaults to live |
| Judge Model | None | Header select, defaults to live |
The Judge Model tab has no time-range picker, on purpose. A judge is scored against a fixed set of gold labels, not against a rolling stream of traffic — so “the last 7 days” is meaningless for judge agreement. The one traffic-based number on that tab (flag rate, below) is computed over the judge’s recent scored sessions and does not need you to choose a window.
Overview
Overview merges spend and recommendations into one visual screen: a hero move, three stat tiles, a spend trend, a spend breakdown, and the ranked list of moves.
The hero move
The top of the tab is the single most valuable move we can prove, presented as the page’s main call to action. If a cheaper model clears the bar, this is a Switch card whose button reads Test before switching (see Test before switching). The copy is explicit that pressing it does not change your agent — it opens a gated test first. If there is nothing to recommend, the hero says so honestly rather than inventing an action.
The three tiles
| Tile | What it is |
|---|---|
| Agent spend | What the agent’s own LLM calls cost over the window, with a daily sparkline |
| Judge spend | What your judges actually spent scoring, shown big — with a smaller “At full coverage ~$X” projection and a coverage % chip beside it |
| Savings available | The projected monthly saving from the moves we can prove, labelled as monthly/projected |
Two of these need reading carefully.
Judge spend leads with the real number — what your judges actually spent — because that is what lands on the bill. Underneath it, “At full coverage ~$X” answers a different question: what would it cost if this judge scored every trace instead of sampling a share of them? The coverage chip tells you how much of your traffic the judge is currently scoring, so you can read the two together: a low actual cost next to a high full-coverage projection just means the judge is sampling, not that it is cheap to run everywhere.
The at-full-coverage projection is shown as — whenever a judge with spend in the window has no price in your price table. A partial total presented as a whole one is worse than no total.
Savings available is the number the earlier version of this page got wrong, so it is worth being precise about what it now means.
Savings available is a monthly projection, independent of the time range you have selected. Changing the window from 7 days to 30 days changes how much you spent, but it does not change how much a proven switch would save you per month — that is a property of the price gap between the two models and your typical monthly volume, not of the window you happen to be looking at. The figure is derived from a per-unit saving projected onto a steady monthly volume, so it stays stable as you move the picker. Only switch moves that we can prove contribute to it; holds, untested versions, and moves with no quality signal add nothing.
Spend trend and breakdown
Spend trend stacks judge spend on agent spend, one bar per complete UTC day. Today’s bucket is marked partial rather than shown as a finished day that happens to look cheap.
Spend by version | model breaks the same total down as bars — the total dollars spent per agent version, or per model. It is deliberately kept at the dollars-you-paid level; there is no per-trace or per-1,000 framing here, because for a “where did the money go” view the absolute total is the honest unit.
Recommended moves
Below the charts is the ranked list of every move we found — at most one per version and one per judge — sorted by projected monthly saving:
| Status | Means |
|---|---|
| Switch | A cheaper model clears the bar with no measurable quality loss. This card has a Test before switching action |
| Hold | You are already on the best proven option. No action, and no card pretending there is one |
| Untested | There is no finished, comparable sweep for this version yet. The action is to run one |
| No quality signal | There is nothing to measure quality against — usually no gold labels. The action is to add some |
Agent Model
On this tab, quality means a stable pass rate on your golden suite. Neens replays the same frozen dataset against each candidate model k times and judges every run with your judges. “Stable” is the key word: a model that passes on two of three replays is not counted as passing. This pass^k reading is what stops a lucky single run from recommending a model that is actually flaky — you are switching on behaviour that repeats, not on one good roll.
Pick a version from the in-body dropdown (it defaults to your live one) and the tab shows the newest finished, comparable sweep for it.
- Candidate bars — one row per model, named exactly as it appears in your traces with the provider underneath. The quality axis is the stable pass rate on your golden suite, and a pass-rate bar is drawn across the chart at the threshold the candidate has to clear. Models that fall below the bar are drawn visually distinct so a failing candidate can never be mistaken for a passing one. The model you run today is chipped Current; the frontier’s pick is chipped Recommended.
- Verdict card — the plain-language read of the comparison: how much a switch saves per month, the change in pass rate (with an honest not distinguishable at n=… when the sample is too small to separate two models), and whether the recommended model clears the bar.
- Dataset version — a link straight to the dataset version the sweep replayed, so you can open the exact items behind the number instead of taking the pass rate on faith.
- Evidence — the underlying sweep, a Share report link a colleague can open without an account, and the option to launch a new sweep.
A worked example, from the shipped demo — a 30-item golden set replayed 3× with a 90% bar:
| Model | Stable pass rate | Monthly cost | Read |
|---|---|---|---|
claude-sonnet-4-6 | 3/3 green — clears | $45 | What you run today (Current) |
claude-haiku-4-5 | 3/3 green — clears | $15 | Recommended — a third of the cost, no measurable loss |
gpt-4o-mini | 3/3 green — clears | — | Clears, but unpriced, so it can’t be recommended |
claude-sonnet-4-5 | 2/3 green — fails | $45 | Two of three is not a pass |
gpt-oss:120b | 0/3 green — fails | $0 (self-hosted) | Cheapest possible, nowhere near the bar |
Two rules make the recommendation trustworthy rather than merely confident, and the demo ships an example of each:
- An unpriced model can never win. A model with no price shows — for cost, never
$0, and is never recommended — you cannot claim a saving you cannot compute. A model priced at a real $0 (self-hosted, where you pay for the GPU not for tokens) can win, but only if it also clears the bar. - A measurement carries its uncertainty. “Not measurably worse” means the candidate’s confidence interval overlaps the current model’s — not that its point estimate happened to land higher. Too small a sample to tell them apart reads as not distinguishable, not as a winner.
A sweep whose arms did not run on comparable inputs is void: Neens refuses to draw a comparison it cannot stand behind rather than showing a misleading chart. See Sweep decisions.
Judge Model
On this tab there are two quality numbers, and which one you can act on depends on whether you have gold labels. This is the single most important thing to understand about the Judge Model tab, so read it before the table.
| Number | What it measures | Needs gold? | What it drives |
|---|---|---|---|
| Fail rate (vs gold) | 1 − agreement: how often the judge’s verdict disagrees with the human verdict on the same session. Lower is better | Yes | The recommendation — a cheaper judge is only proposed when its fail-rate-vs-gold is not distinguishably worse |
| Flag rate (on traffic) | The share of the sessions this judge actually scored where it returned a failing verdict. Available for every judge | No | Nothing on its own — it describes the judge’s behaviour, not its accuracy |
The distinction matters because the two can look similar and mean opposite things. A judge with a high flag rate is failing a lot of your traffic — which is fine if your traffic really is failing, and a problem if the judge is trigger-happy. You cannot tell which from the flag rate alone. Only the fail rate vs gold — comparing the judge to a human on the same sessions — tells you whether the judge is right. That is why:
A cheaper judge cannot be recommended without gold labels. With no gold labels, there is no way to know whether the cheaper model agrees with a human — only how often it flags traffic, which says nothing about accuracy. So a judge with no gold shows — in the fail-rate column and its status reads Add gold labels to compare models. The recommendation is withheld, not guessed. Add labels in Review and the recommendation appears once verdicts exist.
The lens toggle
A toggle at the top-right of the table switches which number both quality columns show:
- Fail rate (default) —
1 − agreementwith gold. This is the lens that drives recommendations. Judges without gold read —. - Flag rate — the fail-verdict rate on traffic, available for every judge. In this lens the recommended-model column reads —, because a model you have not deployed has no live traffic to flag; the recommendation itself stays gold-based whichever lens you are viewing.
All judges at a glance
The table lists every judge with its current model beside the cheapest model that still holds the bar, so the comparison is one row:
| Judge | Current model | Fail rate | Cost | Cheapest that holds | Fail rate | Cost | Status |
|---|---|---|---|---|---|---|---|
| Groundedness Check | claude-sonnet-4-5 | 7% | $12 | claude-haiku-4-5 | 7% | $4 | Switch — same agreement, a third of the cost |
| Reasoning Consistency | claude-sonnet-4-5 | 9% | $11 | claude-haiku-4-5 | 27% | $4 | Hold — the cheap model is genuinely worse here |
| Harmful Content Screen | claude-haiku-4-5 | — | $4 | — | — | — | Add gold labels to compare models |
Read the first two rows together: the same cheap model is the right answer for one judge and the wrong answer for another. That is exactly why this is measured per judge rather than decided once for the whole workspace. The recommendation is always the cheapest scorer model whose fail-rate-vs-gold is not distinguishably worse and still clears the bar.
The docked comparison chart
The full per-model comparison for a single judge is docked at the bottom of the tab and only opens when you select a judge row. Selecting a row draws that judge’s candidate bars — one per scorer model — with the agreement threshold bar (default 0.80) drawn across them; models below the bar are visually distinct, and cost is shown as a whole-dollar label. A close control hides the dock again. A judge with no gold labels shows an add-gold-labels empty state in the dock instead of bars, because there is no agreement axis to plot.
To compare scorer models you have not run yet, the Run a scorer comparison button at the top of the tab opens the launch dialog directly — the same targets scored by several models side by side, which is how you get gold-grounded evidence for a judge before you switch it.
Test before switching
Every recommended switch on this page leads to the same button — Test before switching — and never to a button that flips the model for you. Neens does not edit your agent or redeploy your judge; it hands you a gated test and gets out of the way.
For an agent-model switch, that test is a pre-prod evaluation run against the candidate model:
Press Test before switching
The pre-prod eval dialog opens pre-filled from the evidence on screen: the same golden dataset version the sweep replayed, the same judges, the same pass-rate bar, and the candidate model as the version under test.
Check the prefill
Everything is editable. Widen the dataset, add a judge, raise the bar — the prefill is a starting point drawn from the comparison, not a locked form.
Save and let it run
Saving creates the pre-prod eval, which reruns your golden suite through your judges against the candidate model and checks the result against your pass-rate bar. If the candidate regresses — its stable pass rate drops below the bar — the gate goes red and the switch is blocked.
Ship behind a green gate
Only when the gate is green do you switch the model in your own deployment. You can wire the same gate into CI with eval gates so a regression can never merge.
Why the gate protects you. The sweep on the Agent Model tab is evidence — a comparison of past runs. The pre-prod gate is proof for this switch — a fresh, controlled rerun of your own golden suite against the exact candidate you are about to ship, with the same bar it will be held to. It is the difference between “this model looked good last week” and “this model clears my bar right now”, and it is the last thing standing between a promising cheaper model and a silent quality regression in production.
For a judge-model switch, the equivalent proof is a scorer comparison against your gold labels — the same “measure before you move” principle, because a judge you cannot check against a human is a judge you cannot trust to be cheaper and right.
How-tos
Cut judge cost without losing agreement
Open Judge Model and keep the Fail rate lens
The default lens compares each judge to your gold labels. This is the only lens that can tell you a cheaper judge is still correct, not just quieter.
Find a Switch row
A judge is a switch candidate when a cheaper scorer model holds the bar at a fail rate not distinguishably worse than the current model’s. If a judge you care about reads Add gold labels to compare models, label a handful of its sessions in Review first — without gold there is no recommendation to make.
Select the row and read the docked chart
Confirm the cheaper model sits above the 0.80 agreement bar with an interval that overlaps your current model’s. If it clears the bar and saves real dollars, this is a safe switch.
Prove it with a scorer comparison
Press Run a scorer comparison to score the same targets with both models side by side against gold before you redeploy the judge.
Prove a cheaper agent model on your golden set before switching
Open Agent Model and pick the version you run
The dropdown defaults to your live version. The tab shows the newest comparable sweep for it.
Read the pass-rate bar, not just the ranking
The Recommended model must sit above the pass-rate bar on the stable pass rate (pass^k) — a model that only passes some of its replays sits below the bar and is not a candidate, however cheap.
Open the dataset version
Follow the Dataset version link to see the exact golden items behind the number. If the suite is too small or too narrow for the decision, widen it before you trust the pass rate.
Press Test before switching
Run the pre-prod gate against the candidate. Ship only when it is green, and wire it into CI with an eval gate so the cheaper model can’t quietly regress later.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Every cost shows — | No prices for the models in your traces | Add them in Settings → model pricing. Neens never guesses a rate |
Savings available is $0 with moves on screen | Those moves are holds, untested, or lack a quality signal — only proven switch moves contribute | Read each card’s status; the tile deliberately sums proven switches only |
| Savings available looks unchanged when I change the time range | It is a monthly projection, independent of the window by design | This is correct — the window changes spend, not the per-month saving of a switch |
| A judge’s fail rate reads — and its status says Add gold labels | No gold labels for that judge’s scored sessions | Label sessions in Review; the fail rate and recommendation appear once verdicts exist |
| A judge shows a flag rate but no recommendation | Flag rate is behaviour on traffic, not accuracy vs gold — it can’t justify a switch | Add gold labels so the fail-rate lens can compare the cheaper model to a human |
| The Agent Model tab says untested | No finished, comparable sweep for that version | Run one from the tab, or see Model sweeps |
| A version you expect is missing | No trace in the window carried that neens.version_label | Widen the time range, or check the attribute is set on a span your agent emits |
| Judge spend looks impossibly low | The judge is sampling | Read the at-full-coverage projection and the coverage chip, not the actual — that is what they are for |
| Today’s bar looks small | Today is a partial day | It is marked partial; compare complete days |
Related
- Cost & model pricing — where every rate on this page comes from, and what unpriced means
- Cost–quality frontier — the statistics behind “clears the bar” and “not measurably worse”
- Model sweeps / Sweep decisions — the agent-model evidence
- Judges — deployments, sampling modes and scorer models
- Annotations & review — the gold labels that give the judge tab its recommendation
- Pre-prod evaluations / Eval gates — how a switch is tested before it ships