Temperature 0 Is Not Determinism: Five LLM Output Determinism Misconceptions and a Re-runnable Test Tool

Debunking five LLM determinism myths with a re-runnable quantitative test tool and assertion strategy.
The article addresses the common scenario of local tests passing but CI failing periodically, noting that blaming "model instability" masks a fixable assertion defect. It breaks down five misconceptions: Temperature 0 only narrows the distribution; seeds need system_fingerprint and model version to form a reproducibility key; prompt strings differ from rendered tokens; string differences are often format drift; and output divergence isn't an incident unless decisions change. It then provides a Python re-run tool reporting distinct normalized outputs, schema pass rate, and fingerprint distribution, plus an assertion decision table and limitations.
Title
Temperature 0 Is Not Determinism: Five LLM Output Determinism Misconceptions and a Re-runnable Test Tool
Meta Description
Breaking down five LLM output misconceptions such as Temperature 0 determinism, providing a re-runnable Python test tool to quantify model output uncertainty, along with CI assertion strategies and practical advice on reproducibility keys.
Article Content
Tests pass locally, but fail once a week in CI. The prompt hasn't changed, so what actually changed? Most teams answer "the model is unstable," but that answer masks a fixable assertion defect. This article breaks down five common developer misconceptions about LLM determinism and provides a small, re-runnable test tool to help you quantify just how "uncertain" your own environment really is.

Why the Misconceptions Persist
Model outputs look stable in demos: you send a prompt and get the same JSON structure twice. But two samples are no evidence at all.
Determinism is a property you measure through many runs, not a "vibe" you feel in a playground tab. It's precisely this sampling bias that lets the claim "temperature 0 means deterministic" get passed down through teams generation after generation.
Misconception One: Temperature 0 Means Determinism
It doesn't. OpenAI's reproducibility guide describes low temperature as "largely deterministic," not guaranteed. The documentation also warns that the same request may return different outputs.
The reason lies in batching, GPU kernel differences, and routing between backend configurations—your request lands wherever there's capacity.
The corrected mental model: temperature 0 only narrows the distribution; it doesn't pin down a single sample.
Misconception Two: A Seed Makes Experiments Reproducible
Seeds help, but only on a best-effort basis. The same guide recommends logging seed together with system_fingerprint.
If the fingerprint changes, the backend has switched, and your so-called "same" run is actually a different experiment.
The corrected model: seed + fingerprint + model version together form your reproducibility key. Miss any one piece, and a replay is just a guess.
Misconception Three: The Same Prompt Means the Same Tokens
Your prompt string is not the prompt the model sees. Chat templates inject system text, and some SDKs add defaults.
Tokenizers also differ across models: a string that's 40 tokens on one model might be 43 on another.
The corrected model: compare the rendered prompt, not the source string. Log a hash of the rendered payload.
Misconception Four: Different Strings Mean Different Logic
Often the logic is completely identical and only the formatting has drifted:
- JSON object key order differs
1and1.0represent the same number- Extra whitespace or trailing newlines
- Valid JSON wrapped in Markdown code fences
Compare normalized outputs, or better yet, compare parsed field values.
The corrected model: assert on the schema and field values, not on raw strings.
Misconception Five: Output Divergence Means the Model Is Broken
Sometimes it is, but usually not. Ask one question first: does the divergence change a downstream decision?
If both outputs parse and pass the validator, the pipeline is fine. If one of them fails validation, you've found a real defect.
The corrected model: divergence is data; only a changed decision is an incident.
The Re-run Test Tool: Small, Boring, Repeatable
The tool below sends the same prompt N times and reports how many distinct normalized outputs you get. It works with any OpenAI-compatible endpoint—set three environment variables and run it.
import hashlib, json, os, re
from collections import Counter
from openai import OpenAI
client = OpenAI(
base_url=os.environ['LLM_BASE_URL'],
api_key=os.environ['LLM_API_KEY'],
)
MODEL = os.environ['LLM_MODEL']
PROMPT = 'Return one JSON object with exactly two keys: name, age.'
N = int(os.environ.get('N', '20'))
def normalize(text: str) -> str:
text = re.sub(r'^```(?:json)?|```$', '', text.strip(), flags=re.M)
return re.sub(r'\s+', ' ', text).strip()
def digest(text: str) -> str:
return hashlib.sha256(normalize(text).encode()).hexdigest()[:12]
def schema_ok(text: str) -> bool:
try:
obj = json.loads(normalize(text))
except json.JSONDecodeError:
return False
return isinstance(obj, dict) and set(obj) == {'name', 'age'}
def run_once(seed=None):
kwargs = {
'model': MODEL,
'temperature': 0,
'messages': [{'role': 'user', 'content': PROMPT}],
}
if seed is not None:
kwargs['seed'] = seed
resp = client.chat.completions.create(**kwargs)
text = resp.choices[0].message.content or ''
return text, getattr(resp, 'system_fingerprint', None)
def main():
hashes, valid, fps = Counter(), 0, Counter()
for _ in range(N):
text, fp = run_once(seed=7)
hashes[digest(text)] += 1
valid += schema_ok(text)
fps[fp] += 1
print(json.dumps({
'runs': N,
'distinct_normalized_outputs': len(hashes),
'schema_valid_share': round(valid / N, 3),
'system_fingerprints': dict(fps),
}, indent=2))
if __name__ == '__main__':
main()
The tool deliberately doesn't print example numbers—if you haven't run it, those numbers are fiction. It's worth running probes like this against free model access, because repetition is the whole point. The article mentions that MonkeyCode offers free model access and a free server option; treat that as an availability claim and validate it with your own workload. Disclosure: this article is part of a MonkeyCode product promotion.
How to Interpret the Output
Field by field:
distinct_normalized_outputsgreater than 1 means string-level uncertainty exists.schema_valid_shareless than 1 means you have a production defect, not "occasional instability."- Multiple
system_fingerprintvalues mean the backend changed mid-run. - A single fingerprint but multiple distinct outputs points to uncertainty during inference.
- A single fingerprint and a single output still proves nothing at N=20.
Assertion Strategy Decision Table
| Your goal | What you should assert | What you should never assert |
|---|---|---|
| CI stability | Schema plus field constraints | Exact raw strings |
| Regression testing | Fixed samples with fingerprint logging | Live model calls |
| Prompt tuning | Pass rate over 20+ runs | A single sample |
| Debugging failures | Rendered prompt hash plus fingerprint | The prompt as you remember it |
Limitations and Who Should Skip This
This tool measures your endpoint, not determinism in general. N=20 is a smoke test, not a rate estimate. Provider caching can hide variance and inflate stability numbers.
If you need bit-exact replay for auditing, billing, or regulated output, skip this approach. In those scenarios, log every response and compare against fixed samples—never compare against a live model.
If your prompt has no validator, skip it too—collecting twenty unparsed strings teaches you nothing.
One Habit Worth Keeping
Log three things on every call: the rendered prompt hash, the model version, and the fingerprint. When a test fails next month, you can answer "what changed" in minutes.
Run this tool on whatever free access you already have, then tell me your distinct output count—not your intuition.
Further reading: OpenAI Cookbook, "Reproducible outputs with the seed parameter." Confirm the latest wording in your provider's documentation before citing it.
One-line Summary
Breaking down five misconceptions about LLM determinism, with a re-runnable quantitative test tool and assertion strategy.
Paragraph Summary
The article addresses the typical scenario of "tests passing locally but failing periodically in CI," pointing out that most teams blaming "model instability" is a excuse that masks a fixable assertion defect. The author breaks down five common misconceptions one by one: Temperature 0 only narrows the distribution rather than guaranteeing determinism; seeds must combine with system_fingerprint and model version to form a reproducibility key; the prompt string is not the rendered tokens the model actually sees; string differences are often format drift rather than logic changes; and output divergence itself is not an incident—only a changed decision is. The article then provides a Python re-run tool compatible with OpenAI endpoints that samples N times and reports the number of distinct normalized outputs, schema pass rate, and fingerprint distribution, along with an assertion strategy decision table and a note on limitations.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.