World’s largest virtual agentic engineering & quality conference
Testing non-deterministic AI outputs without exact-match assertions: determinism knobs, four assertion types, pass-rate sample sizes, metamorphic relations.

Prince Dewani
Author
Srinivasan Sekar
Reviewer
Last Updated on: August 9, 2026
Testing non-deterministic AI outputs replaces equality assertions with JSON schema checks, semantic similarity thresholds, and pass rates measured across repeated runs. Thinking Machines Lab sampled 1,000 completions from Qwen3-235B at temperature 0 and still produced 80 unique answers.[1]
This guide covers why one prompt returns different answers, what temperature and seed actually control, the four assertion shapes that replace exact match, how many runs a pass rate needs, metamorphic relations, golden sets, cross-version regression, and agent validation before production release.
Key Takeaways
AI models give different answers to the same prompt because inference servers batch requests together, and the batch size changes the order in which floating-point values are summed inside the model. That reordering shifts token probabilities enough to flip a choice.
Thinking Machines Lab traced this behavior directly. Sampling 1,000 completions from Qwen3-235B at temperature 0 with a single fixed prompt produced 80 distinct completions, and the most common one appeared 78 times. The completions stayed identical until token 103, where 992 of them continued with "Queens, New York" and 8 continued with "New York City".[1]
Your prompt is identical on every run, but the other users' requests batched alongside it are not, so the source of variation sits outside your code and outside your control. Three separate sources stack:

Only the first source is yours to configure. A test suite written as though sampling is the whole problem will pass in development and fail under production load, because production is exactly where batch composition varies most.
No. Temperature 0 forces greedy decoding, so the model always takes the highest-probability token, but it leaves the batching and kernel behavior underneath untouched. Greedy decoding narrows variance without removing it, and a fixed seed adds nothing at temperature 0, because greedy decoding makes no sampling draw for the seed to control.
OpenAI states the position plainly in its API documentation: Chat Completions are "non-deterministic by default", and a seeded request returns output that is only "(mostly) deterministic".[2] The same documentation ties reproducibility to a system fingerprint that tracks model weights and infrastructure configuration, and it changes when the provider updates either.
The measured cost of assuming otherwise is large. Researchers at Penn State University and Comcast AI Technologies ran five models across eight benchmark tasks at temperature 0 with fixed seeds, and recorded accuracy variations up to 15% across runs, with a gap between best and worst possible performance reaching 70%.[3]
| Knob | What it controls | What it leaves untouched |
|---|---|---|
| Temperature 0 | Token selection becomes greedy, removing sampling randomness. | Batch-size effects on logits, provider updates, tool-call ordering. |
| Fixed seed | The sampling draw when temperature is above 0. | Everything at temperature 0, where no sampling draw happens. |
| Top-p and top-k | The size of the candidate token pool. | Which candidate wins once the pool is set. |
| Pinned model version | Silent weight changes between releases. | Serving infrastructure changes within the same version. |
Set temperature to 0 and pin the model version anyway. Both narrow the distribution you have to test against.
Exact-match assertions fail because one question has many correct answers. "Paris", "Paris is the capital of France", and "The capital of France is Paris" are all correct, and a string equality check accepts exactly one of them. Each valid phrasing the model can produce lowers the odds that one expected string matches, so the suite decays as prompts evolve.
This is the test oracle problem. A conventional assertion needs an oracle, meaning a reliable way to decide whether a specific output is correct. Generative systems break that assumption because the correct output cannot be enumerated in advance, so a red test tells you the string changed and nothing about whether the behavior broke.
A script written for this article sent one prompt to gemini-2.5-pro 20 times at temperature 0 and compared each response against the first. The exact-match assertion passed 5 of the 20 runs, and the five distinct strings differed only in wording. Every response was a correct definition, so this run tested exact match on correct output only. The result covers one prompt, one model, and one provider.

The failure is expensive in both directions. False failures train the team to rerun the suite until it passes, which destroys the signal. False passes are worse: an assertion that checks only for the substring "Paris" also passes on "Paris is not the capital of France".
Two rules follow. Assert on properties the answer must hold rather than on the text it happens to use, and keep every deterministic check that still applies. Response schema, status codes, latency bounds, required fields, and banned patterns are all still exactly assertable, and they should stay as strict as they were before the model arrived.
Four assertion types work on non-deterministic AI output: structural checks on shape, invariant properties that must always hold, semantic similarity against a reference, and rubric scoring by a judge model. Each costs more than the one before it. Structural checks run locally with no model call, while rubric scoring adds an extra inference to every assertion.
| Assertion type | What it verifies | Where it breaks |
|---|---|---|
| Structural | Valid JSON, required fields, enum membership, length and format bounds. | Passes on well-formed output that is factually wrong. |
| Invariant | Rules that hold for every input, such as a refund never exceeding the order total. | Only covers what you thought to forbid in advance. |
| Semantic similarity | Whether the meaning matches a reference answer, scored by embedding distance. | Scores negation and small factual edits as near-identical. |
| Rubric scoring | Subjective dimensions like faithfulness, tone, and completeness. | The judge is itself non-deterministic and carries its own biases. |
Route each claim to the cheapest type that can actually verify it. Sending a JSON schema check to a judge model spends tokens and adds variance on a problem that a Pydantic model answers instantly and identically every time. Reserve rubric scoring for claims that genuinely need semantic judgment, and read LLM as a judge for the bias controls that keep those scores stable.
In the Reddit thread "You can't test the model, so I gave up and tested everything around it" on r/LLMDevs, the author replaced a hand-tuned instruction file with deterministic gates: a hook that typechecks every file write, and an allowlist that stops the agent before it pushes. The author closes by asking how to test the non-deterministic part itself.
A pass rate needs enough runs that its confidence interval is narrower than the regression you want to catch. An 18-of-20 result looks like 90%, but its exact binomial interval at 95% confidence runs from 68.3% to 98.8%.[4] Precision improves with the square root of the run count, so doubling runs narrows that interval by far less than half.
That figure uses the exact binomial method, which the NIST Engineering Statistics Handbook specifies for proportions measured on small samples. A range that wide cannot separate a healthy suite from a badly degraded one, so a short gate reporting a high pass rate tells you almost nothing.

Small run counts also hide common defects. The same binomial model says a failure mode firing on 8% of requests survives a 5-run gate whenever all 5 runs pass, and 0.92 to the fifth power is 65.9%.[4] The defect clears the gate on roughly two attempts out of three, then reaches production as an intermittent complaint nobody can reproduce.
Work backwards from the regression size that matters to you. Applying the NIST sample-size formula for proportions at 95% confidence and 80% power, detecting a drop from a 95% baseline to 85% needs 53 samples.[5] Halve the difference you want to catch and the requirement roughly quadruples, which is the arithmetic that decides your suite size.
Breadth beats repetition for most suites. One hundred different scenarios run once exercises far more of the input space than one scenario run 100 times, and it costs the same in tokens. Repeat a single prompt only when the variance of that specific prompt is the thing under test.
In the Reddit thread "Verifying non-deterministic generative UI in CI" on r/LLMDevs, the author reported that generated interfaces change on every render, so pixel-diff tools fail. Their harness samples N generations, renders each in headless Chromium, and scores data fidelity, accessibility, and layout, then reports consistency as the standard deviation of those scores. The practical takeaway is that spread across runs is itself worth gating on.
Note: Run your AI test suites across 3,000+ browser and OS combinations on TestMu AI. Try free!
Metamorphic testing checks that a required relation holds between the outputs of two related inputs, so it needs no expected answer at all. It beats a golden set whenever the correct output cannot be written down in advance. The relation itself is the assertion, which is why it scales to inputs that have no reference answer.
A systematic survey by Zheng Zheng and colleagues describes the technique as oracle-alleviating, because it checks necessary relations among multiple related executions instead of relying on exact expected outputs.[6] Their worked example is sentiment analysis: replacing a word with a synonym, so "The movie is good" becomes "The movie is excellent", must not change the predicted label.
Metamorphic relations are the cheapest way to generate large numbers of valid test cases, because each one turns a single labeled input into an unlimited supply of derived checks. Four relations transfer directly to a retrieval or support application:
The relations complement a golden set rather than replacing it. A golden set proves the system gets specific known cases right, and metamorphic relations prove it stays self-consistent across inputs nobody labeled, which is where regressions usually hide. For broader coverage of scoring methods, LLM evaluation maps the metric families these relations feed into.
A golden set is a fixed collection of inputs paired with human-approved acceptance criteria rather than exact expected strings. Start with 25 to 50 labeled cases, then grow the set from real production failures. Criteria do not catch a regression nobody anticipated, so the set only covers failure modes someone has already written down.
The design decision that makes a golden set survive is storing criteria instead of answers. An expected-string record breaks on the first harmless rewording, while a criteria record keeps working across model versions because it encodes what correctness means for that input.
Keep the set small enough to run often. Scaling past 100 cases before the thresholds are calibrated produces a suite that is expensive to run and still unable to say whether a change made things better. Every production failure that reaches a user should end its life as a new record in this file.
Compare distributions instead of single runs. Record the pass rate and score spread for every scenario on each build, then fail the pipeline when the new mean drops below the stored baseline interval. A build whose wording changed on every scenario but whose pass rate held has not regressed.
A single red response is not a regression signal on a system that samples from a distribution. The measurable signal is a shift in the distribution, and it takes two forms: the mean pass rate drops, or the spread widens while the mean holds steady.
The second form is the one teams miss. An unchanged average with a doubled standard deviation means the system now fails harder on the runs where it fails.
# Gate a build on the distribution, not on one response.
import statistics
BASELINE_PASS_RATE = 0.94
BASELINE_STDDEV = 0.06
MIN_RUNS = 30
def gate(scores, threshold=0.75):
"""scores: one similarity or rubric score per scenario run."""
if len(scores) < MIN_RUNS:
raise SystemExit(f"Need {MIN_RUNS} runs, got {len(scores)}")
pass_rate = sum(s >= threshold for s in scores) / len(scores)
spread = statistics.pstdev(scores)
# Wilson-style margin: allow normal sampling noise, block real drops.
margin = 1.96 * (BASELINE_PASS_RATE * (1 - BASELINE_PASS_RATE) / len(scores)) ** 0.5
if pass_rate < BASELINE_PASS_RATE - margin:
raise SystemExit(f"Pass rate {pass_rate:.2%} below baseline")
if spread > BASELINE_STDDEV * 2:
raise SystemExit(f"Score spread {spread:.3f} doubled; output destabilized")
print(f"OK pass_rate={pass_rate:.2%} spread={spread:.3f}")Store results per scenario rather than as one aggregate. An aggregate score hides the case where two scenarios improve while one collapses, and per-scenario history makes a regression traceable to the prompt that caused it. Re-baseline deliberately after a model upgrade, and record the old numbers so the comparison stays honest.
Sampling several responses and taking the majority answer also raises accuracy on reasoning tasks. Wang and colleagues reported that self-consistency, which samples diverse reasoning paths and selects the most consistent answer, improved GSM8K accuracy by 17.9%.[7] The same aggregation that stabilizes a test also stabilizes production behavior.
For the wider tooling picture, LLM testing covers the frameworks these gates plug into, and LLM test automation shows the pipeline wiring with code.
Run the agent through many scenario variants, score each on fixed quality dimensions, and require a confidence level tied to scenario volume before approving the release. A verdict from 10 scenarios is not the same evidence as a verdict from 200.
Multi-turn agents make the sample-size problem worse. A five-turn conversation can score well on every individual response and still fail overall because the agent lost context between turns, so per-response scoring misses the defect entirely. Building that scenario volume by hand is where most teams stall, because writing 100 conversational variants and grading them consistently is slow manual work.
TestMu AI provides Agent Testing, which generates the scenarios and scores the transcripts against fixed dimensions:
Scenario generation produces 60 to 100 or more variants per workflow from uploaded documentation, and each runs as a full multi-turn conversation rather than a single exchange. You can follow the getting started with agent testing platform guide to connect an agent and read the go-live report.
Non-determinism shows up at every stage of a testing pipeline, not only at the model boundary. TestMu AI runs a set of purpose-built AI agents across those stages, including Agent Testing for conversational quality, an Auto Healing Agent for element drift, a Test Insights Agent for result analysis, and a Root Cause Analysis Agent for failure triage.
The metric definitions behind agent evaluation scores are set out in AI agent evaluation.
Start by writing down the acceptance criteria for 25 scenarios your application must handle, then pick the cheapest assertion type that can verify each one. Set temperature to 0, pin the model version, and treat the remaining variance as a property to measure rather than a bug to eliminate.
Testing non-deterministic AI outputs comes down to one shift: the assertion moves from the response to the distribution behind it. Pass rates, tolerance bands, and metamorphic relations all answer the question a release actually turns on, which is whether behavior changed since the last build.
Teams planning a broader skills path can follow the AI roadmap for software testers, which places these techniques alongside the rest of the AI testing stack.
Author
Prince Dewani is a Community Contributor at TestMu AI specializing in AI agents, software testing, QA, and SEO. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI, and presented academic research on AI agents at PBCON-01. At TestMu AI, he has also carried out extensive cross-browser research on the support of modern web technologies such as WebGPU, WebAssembly, WebXR, WebGL2 and other web technologies, validating their compatibility and feature parity across major browsers and rendering engines through rigorous hands-on testing. Prince has hands-on experience building AI agent workflows using Anthropic Claude, Google Antigravity, n8n, LangChain, and other agentic frameworks, and works regularly with MCP and A2A protocols. He shares his work with 5,500+ QA engineers, developers, DevOps experts, tech leaders, and AI agent practitioners on LinkedIn.
Reviewer
Srinivasan Sekar is Director of Engineering at TestMu AI (formerly LambdaTest), where he leads engineering and open-source initiatives behind the Selenium and Appium automation grid and owns TestMu AI's MCP Server. A committer to Appium and a contributor to Selenium, WebdriverIO, Taiko, and AppiumTestDistribution, he brings over 15 years of experience in quality engineering and open-source technologies. He is the author of the Apress book 'The MCP Standard: A Developer's Guide to Building Universal AI Tools with the Model Context Protocol,' a Certified Kubernetes and Cloud Native Associate, and an international conference speaker. Before TestMu AI he spent over eight years at Thoughtworks as a Principal Consultant and Quality Architect. Srinivasan holds a B.Tech in Information Technology from Anna University.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance