Many of the most visible public evals are comparative. Benchmarks such as HELM make models easier to compare, while arenas such as LMArena turn preferences into rankings. Their graphs are useful precisely because they spread models across an axis. At Stance we need a different shape. We don't train models, we consume them, and our customers bring their own: the product deploys into your cloud and runs on whichever models your organisation has approved. So the question our evals answer is how little our product's behaviour changes when the model underneath it changes.
Almost everything about how you build evals shifts once you start from that question. A comparative benchmark benefits from separating models clearly, because the spread is the information it was built to reveal. We want to compress that spread at the product layer, because a customer who has only approved a lighter model should still get the full product. And a business reason sits on top of the engineering one: throwing every problem at the biggest models is a road to financial ruin. Some of our workloads run thousands of times a day, and no margin survives running those on a frontier model. Maturity here means identifying which parts of your workflows genuinely need intelligence and which parts need structure, and our evals are the instrument that tells us where that line sits.
The distinction is less visible in public leaderboards, but the broader evaluation frameworks do account for it. NIST's AI Risk Management Framework applies to the design, development, use, and evaluation of AI products, services, and systems across their lifecycle. Our work was to turn those broad outcomes into regression tests for applied AI: a business workflow with prompts, code, tools, data, and a model embedded inside it. We wrote that operational layer up formally in our AI safety framework, which maps every eval to a NIST AI RMF MEASURE outcome and to named hallucination and bias controls, assesses each workflow under the EU AI Act's risk-based rules, and uses ISO/IEC 42001 for the organisation-level management system around it. The rest of this post covers the engineering underneath that paperwork.
The function you are actually testing
What an eval actually exercises is a function: the system prompt, the model, and the parameters go in, an output comes out, and you check the output against what you expected. Framing it that way pushed us into two practices.
First, the eval has to call the real function. Our evals import the same prompt configuration the production system uses, so a passing eval means the shipped prompt passes, and never a copy of it that drifted three weeks ago. The only thing the eval harness swaps is the model variant under test.
Second, we reduce every source of variance the model and provider let us control. Where the API exposes them, we use the lowest-variability sampling settings and a fixed seed. Those controls are not available on every model, and even where they exist they do not promise bit-for-bit determinism, so we also pin model versions, prompt configuration, tool schemas, and structured-output contracts. Then every item runs three times with the scores averaged, so a flaky pass can't sneak through and a flaky failure can't send anyone on a false hunt. We keep the datasets small and deliberate: roughly 25 to 45 items per eval, stratified into simple, complex, and edge cases, and we tag each item with its provenance, either grounded in a real fixture or authored by hand. That tag carries more weight than it looks like it should. If the gold answers in an eval are merely authored, and a subject-matter expert hasn't validated them, we don't let that eval gate anything. Several of our evals sit switched off in the codebase for exactly this reason, each with a note explaining what validation it's waiting on.
Every eval carries its own pass threshold, between 0.65 and 0.9 depending on the task, and the thresholds work the way smoke tests work in a normal codebase. Some critical datasets encode baseline business criteria, and any model that misses them gets rejected outright, whatever its reputation. Past that bar we treat the scores as a gradient we watch over time; failing is a very strong word for most of what the numbers do day to day.
Here is the part that makes the whole system lean toward lighter models: we calibrate those thresholds against a deliberately lightweight model. When the bar sits where a light model can clear it on a well-designed task, every heavier model clears it with margin, and a threshold breach tells us something real changed. If we calibrated against our smartest model instead, we would have quietly rebuilt the leaderboard we set out to avoid.
A hard eval is a signal to break the task down
When an eval scores well on a heavy model and falls on its face on a lighter one, the leaderboard instinct says the lighter model lost. We read it differently: the task is too big, and the eval just measured that for us.
The example I know best, because I personally did the breaking down, is requirement extraction. We take a regulatory document and turn its text into atomic, testable compliance requirements. Done as one job, it demands a lot: resolve the acronyms and variables, work out what context the headings contribute to each statement, pull out the atomic clauses inside each statement, strip the decorative language, extract the attributes, and finally map what's left onto a control framework. A frontier model can often do all of that in one agentic pass, and our first eval assumed that shape. It worked on the smartest models and completely fell over on lighter ones.
So we went the other way. The workflow became a chain of small, constrained steps: one prompt that only classifies whether a piece of text is a statement or a heading, one that only fills in acronyms and missing context, one that only extracts complete sentences, one that only splits sentences into clauses, one that only extracts attributes, and so on down the chain to the final mapping. Each step asks for so little intelligence that a light model handles it reliably, and ordinary code takes over between the steps: when the classifier says a chunk is a heading, the rest of the chain simply doesn't run for it. The model only makes the small judgment calls, and the program carries the control flow between them.
Then we exploded the eval to match. Each stage got its own dataset and its own threshold, which is how requirement extraction ended up with three separate scorers (statement-type classification, requirement content similarity, context completion) instead of one blended number. Where the old eval could only tell us that a light model couldn't do the job, the exploded evals tell us which two-hundred-token slice of the job it can't do, and you can fix that slice by Friday.
I think of it the way birds feed their chicks: they chew the food first. You can hand a big workflow whole to a model smart enough to chew it itself, but for business-critical paths where you can't assume that intelligence, the chewing becomes your job. The eval suite shows you where you haven't chewed enough.
Light, medium, heavy
We organise the model side into classes. Our configuration defines light, medium, heavy, and coding classes, each workload declares which class it needs, and an administrator can change the approved model for each class without a deploy. Workloads that run constantly on cheap, structured work sit in the light class, and the rare, genuinely hard reasoning sits in heavy.
The fashionable name for the general idea is routing, and there are providers who will route between models dynamically for you. We don't use them. We build enterprise software, so we have to answer, deterministically and after the fact, exactly which model handled which workflow, and the class system gives us that audit trail where a dynamic router would hide it. Model swaps still take about thirty seconds, and a human decides them.
Onboarding a new model into this system has become mostly a non-decision. Point the eval suite at it, read the per-class scores against the thresholds, and the answer falls out: either it clears the bar for a class or it doesn't. The current floor for the light class is a nano-class model, and the floor keeps rising. Years ago I ran a heavily quantised Llama on my own laptop against parts of our production eval suite, with no proper tool calling, on toy hardware, and it still passed acceptably for a slice of the workflows. That model would fail today; we've kept raising the minimum bar as the market's floor rose, and the machinery exists so we always know exactly where that floor is.
Scoring without a judge
Everything that gates in this system gets scored objectively. Exact matches, set overlap, lexical F1, embedding similarity, structural checks like compiling the generated policy and seeing whether it runs, and weighted composites of those. You will not find an LLM judging another LLM's single-shot output anywhere in our gating scorers, and we refuse that deliberately. Research has documented position, verbosity, and self-enhancement biases in LLM judges and has also reported self-preference effects, although newer work shows that the measured size of self-preference can depend heavily on experimental controls. That uncertainty is exactly the problem for a CI gate: it becomes harder to distinguish a product regression from movement in the grader. And for zero-shot and few-shot prompt evals you almost never need one anyway; when you can't say objectively what a correct extraction looks like, you haven't finished defining the task.
LLM-as-judge does earn a place at the multi-turn, tool-calling end of our eval work, because there the question shifts from whether the output is correct to whether the agent did the work honestly. Evaluating an agent means checking which tools it called, with what arguments, in what order, and whether it reached its answer through them or around them. Hand-curating those datasets costs far more than writing input/output pairs, so we bootstrap them from our own audit trail: we record every AI call in our product, run the workflow on the most capable frontier model available, extract those traces, and repurpose them into harnesses that we then hold lighter models against.
We use the same philosophy in production, well beyond the eval suite. Lighter models get lazy on multi-step work, so our skill definitions can declare mandatory tool rules: this tool must run at least three times and at most ten before the agent may conclude, and when the model tries to skip ahead, a corrective message pushes it back to work instead of letting it fail silently. One of our discovery workflows refuses to accept a conclusion until the agent has exercised the search tool from several distinct angles. Constraints like that raise light-model success rates enough to move a workflow from the medium class down to light, and they help the eval side too, because an agent forced to show its work leaves a trail you can check.
We also keep one habit I'd recommend to anyone building this: leave some failures in. One of our knowledge-graph evals contains a case that scores a third of the available points, and we've kept it that way on purpose as an honest regression anchor, instead of tuning the prompt until the number goes green. The day that score moves, in either direction, we've learned something about the model or the prompt. A suite that shows green everywhere, all the time, has stopped telling us anything.
What this buys you
The best war story I have for this system is a boring one. We once needed to move a set of workflows off OpenAI models onto open-weight ones, Gemma and GPT-OSS class, on short notice. Because we had already organised the evals around intelligence classes instead of model names, the swap turned into mostly a non-event: run the suite, read the scores against the class thresholds, flip the configuration. A sudden provider change would otherwise have demanded months of decomposition work in a panic, and we had already done that work calmly, in advance, with instruments.
That, to me, is what eval maturity looks like from the consumer side: the choice of model matters a little less every quarter, until the product stops caring which model it's given. The leaderboards will keep crowning a new winner every few weeks, and our job is to make sure our customers never need to care who it is.