Skip to content
LogoSamir Sawarkar

Jul 8, 2026 / 26 min read

The Probabilistic Core, Deterministic Shell: A Reliability Architecture for LLM Systems

Reliability in LLM systems is not the elimination of probabilistic behavior — it is the architectural containment of it.

reliabilityLLMsarchitectureengineering

The system worked exactly as designed

A loan-servicing pipeline gets a document-verification decision back from its LLM step:

{
  "decision": "approve",
  "confidence": 0.97,
  "reason": "All required documents are present."
}

The JSON parses. The schema validates — decision is a valid enum, confidence is a float between 0 and 1, reason is a non-empty string. Every automated check the team built passes. The application logs a clean, structured, high-confidence approval and moves the record to the next stage.

The required document does not exist. It was never uploaded. The model inferred its presence from a folder name that resembled the naming convention used in similar, approved cases, and it wrote a fluent, syntactically perfect justification for a fact that was never checked against anything.

Nothing in this pipeline was broken. The JSON parser did its job. The schema validator did its job. The model did what models do: produced the most probable continuation given the prompt. The failure did not happen inside the model. It happened at the boundary — the place where an uncertain, unverified claim was silently converted into a confident, actionable decision.

That conversion is the actual subject of this article. Not prompting. Not schemas. The boundary.

Most teams building on LLMs spend their reliability effort trying to make the model behave more deterministically: lower temperature, longer system prompts, few-shot examples, self-consistency voting, chain-of-thought scaffolding. Some of this helps at the margins. None of it changes what the model fundamentally is — a component that samples from a learned probability distribution over token sequences. Temperature zero does not remove that distribution; it just always samples its mode, which is a different thing from being correct.

The more productive question is not "how do we make the model stop being probabilistic." It's: where in the system is uncertainty allowed to exist, how is it represented once it does, and what stops it from crossing the next boundary unchecked?

That question has an architecture behind it. This article builds that architecture, names its parts, stress-tests it against a hostile reviewer, and is explicit about where it runs out of road.

Why temperature zero is not a reliability architecture

Temperature zero (or its equivalent, greedy decoding) removes sampling randomness at inference time. It does not remove model uncertainty — it removes the visibility of that uncertainty. A model at temperature zero that is genuinely unsure between two answers will still commit to one, deterministically, every time. You get repeatable wrongness instead of variable wrongness, which is easier to test against but not more correct. Determinism of output given identical input is a property of the sampling procedure, not a property of the model's relationship to truth.

It's also weaker than it sounds in practice, and the mechanism is more specific than "GPUs are noisy." Thinking Machines Lab's 2025 investigation into LLM inference nondeterminism found that individual kernels are typically run-to-run deterministic on their own, but production inference servers batch concurrent requests together, and most kernels lack batch invariance — the same request produces different floating-point results depending on what batch size it happened to be processed with, which varies with server load and is invisible to the caller (He et al., "Defeating Nondeterminism in LLM Inference," Thinking Machines Lab, 2025). Since server load isn't something a caller controls or observes, "temperature zero" APIs are frequently not bit-for-bit reproducible in production even in the narrow sense of the same prompt returning the same tokens twice in a row. Treating temperature as a reliability control conflates two unrelated things — the entropy of the sampling distribution, and the correctness of the distribution itself. A model can be maximally confident and maximally wrong at the same time; nothing about decoding temperature touches that.

This matters because it's the first place teams spend their reliability budget, and it buys almost nothing. The real work starts one layer out.

Structured output is necessary and radically insufficient

Constrained decoding — forcing generation to conform to a grammar, typically a JSON Schema — is real, well-studied engineering, not folklore. Frameworks like Guidance, Outlines, and XGrammar work by masking the model's token probabilities at each decoding step so that only grammatically valid continuations remain possible. JSONSchemaBench, a benchmark evaluating constrained-decoding engines against ten thousand real-world JSON schemas, found that modern engines now generate constrained output at speed comparable to or faster than unconstrained generation, reversing the earlier assumption that structural guarantees necessarily cost latency (JSONSchemaBench, arXiv:2501.10868, 2025).

But the same benchmark, and the broader constrained-decoding literature it summarizes, is precise about what this buys you: syntactic and structural compliance, nothing about semantic correctness. It guarantees the output parses and matches the shape you asked for. It says nothing about whether the values in that shape are true. One documented failure mode makes this vivid: JSONSchemaBench's analysis found that constraining an LLM to emit an "answer" field before a "reasoning" field measurably hurts task accuracy relative to the reverse ordering, because the schema forces the model to commit to a conclusion before it has generated the reasoning that should have produced it (JSONSchemaBench, arXiv:2501.10868, 2025). The JSON is perfectly valid and the answer can be wrong precisely because the schema was enforced in the wrong field order. The constraint didn't fail. It succeeded, and the success shipped a bad answer with high structural confidence.

There's a second, quieter cost. Forcing generation away from a model's preferred tokens to satisfy a grammar can measurably degrade output quality on some tasks — if the model's most probable continuations are all invalid under the grammar, it is pushed into lower-probability territory that may be grammatically legal but semantically worse. Structure is not free. It is a real constraint with a real accuracy cost in some regimes, and treating "the output validates" as a proxy for "the output is right" is exactly the mistake that produced the loan-approval failure above.

This is the first structural insight worth internalizing: schema validation is a necessary gate, not a reliability system. It belongs early in the pipeline. It should never be the last gate.

Four levels of LLM reliability

Most teams have one bar for "the model worked": did I get parseable output back. That bar conflates four genuinely separate questions, and separating them is one of the more useful things this article can hand you.

1. Syntactic reliability — can the output be parsed? Is it valid JSON? Does it match the grammar? This is what constrained decoding guarantees.

2. Structural reliability — does the output satisfy the schema and types? Is risk_score a float in [0, 1]? Is decision one of the declared enum values? Are required fields present? This is one level deeper than parsing — it's checking the shape, not just the syntax — and most "output validation" code stops here.

3. Semantic reliability — is the content actually correct and internally consistent? Does the cited document actually contain the claimed fact? Does the evidence field logically support the decision field? Is "Rahul" the Rahul the user meant? This is the level almost no pipeline checks, because it's the hard one — it usually requires grounding against an external source of truth, not just inspecting the object you were handed.

4. Operational reliability — is the system safe to act on this result? Even if the model is right, should this action execute automatically, right now, without further checks? A correct answer can still be operationally unsafe to act on autonomously — the classic case being an irreversible or high-blast-radius action (sending money, deleting records, sending an email on someone's behalf) where the cost of being wrong outweighs the convenience of automation, independent of how confident or correct the model actually was.

Valid JSON is not reliable AI. An LLM can return output that is syntactically perfect, structurally compliant, and completely wrong. Every dollar spent making level 1 and level 2 airtight without touching level 3 and level 4 is a dollar spent making the failure mode harder to see, not less frequent.

Which errors does your pipeline catch?

Toggle reliability levels to see what escapes. Each level subsumes the ones below it.

Presets:
Malformed outputneeds L1

Rejected at parse — retry with structured decoding

Wrong type / missing fieldneeds L2

confidence="high" (string) accepted as if numeric

Value outside allowed setneeds L2

decision="maybe" treated as implicit approval

Hallucinated evidenceneeds L3

"All documents present" — the document was never uploaded

Unresolved ambiguityneeds L3

Model picks one of 3 Rahuls silently — wrong person invited

Internal contradictionneeds L3

Evidence says "denied" but decision says "approve"

Policy violationneeds L4

Persuasive explanation bypasses $500 auto-refund cap

Duplicate executionneeds L4

Retry after timeout creates two calendar events

Catch rate
1/8
7 error classes escape to production

The central architecture: probabilistic core, deterministic shell

Before naming this pattern, it's worth being honest about how much of it is new. It largely isn't, and that's a feature, not a weakness.

Design by Contract, formalized by Bertrand Meyer in the 1980s, already gives us the vocabulary: preconditions define what a caller must guarantee before invoking a component; postconditions define what the component guarantees in return, provided the precondition held; invariants define what must remain true throughout. Applied to an LLM call, this is close to the whole architecture in miniature — the LLM is a component you invoke, its input contract is a precondition, its output contract is a postcondition, and the pipeline's job is to enforce both mechanically rather than trust the component to enforce them on itself.

Fault-isolation patterns from distributed systems — circuit breakers and bulkheads, popularized by Michael Nygard's Release It! and now standard in resilience libraries — supply the second half: the goal of a circuit breaker is never to make the downstream service stop failing. It's to stop a failure in one component from cascading into the caller and the rest of the system, insulating the caller from a degraded dependency rather than repairing it. That is precisely the right relationship to have with an LLM: you do not need the model to stop being unreliable. You need a boundary that stops its unreliability from propagating.

So the synthesis here is not a new primitive. It's naming a specific application of two mature ideas — contracts and fault isolation — to a component whose primary failure mode is semantic, not just availability or latency, which is the part existing resilience engineering doesn't natively cover. That's the honest scope of the claim: Probabilistic Core, Deterministic Shell is a name for where these known disciplines meet a new kind of unreliable component, not a new discipline.

A precision that matters here, because it's easy to get wrong: the shell is not a claim that every component inside it is deterministic software. It isn't. Semantic verification, several sections ahead, routinely uses a second LLM as a judge, a source-grounding model, or a confidence-calibration step — all probabilistic. Calling the whole thing a "deterministic shell" while it contains probabilistic verifiers is a real inconsistency if the word "deterministic" is describing the components.

It isn't. It's describing four other things: control flow, contracts, authority, and failure handling.

  • Control flow is deterministic — the sequence of which checks run, in what order, and what happens on each outcome is fixed code, not something the LLM decides.
  • Contracts are deterministic — the schema, the range checks, the enum constraints are enforced mechanically, whether or not the thing being checked was produced probabilistically.
  • Authority is deterministic — whether a given result is permitted to trigger an action is a fixed rule (a permission check, a blast-radius threshold), never a judgment the model itself makes about its own output.
  • Failure handling is deterministic — what happens when a check fails (retry, repair, escalate, refuse) is fixed logic, not improvised by another model call with no contract of its own.

A probabilistic judge can sit inside this shell as one signal feeding a deterministic decision about what state to assign next. What makes the architecture a shell rather than just "more LLM calls" is that the judge's verdict is never itself the last word — it's an input to fixed control flow that decides what to do with that verdict, including distrusting it. The core can nest: a probabilistic verifier can itself be wrapped in the same pattern, one level in. What cannot happen anywhere in the design is a probabilistic output being trusted to gate an action without a deterministic control point deciding whether to trust it.

The shape:

MESSY WORLD
    ↓
INPUT CONTRACT
    ↓
DETERMINISTIC NORMALIZATION
    ↓
CONTEXT CONSTRUCTION
    ↓
[ PROBABILISTIC LLM TRANSFORMATION ]
    ↓
STRUCTURED OUTPUT CONTRACT
    ↓
SYNTACTIC VALIDATION
    ↓
STRUCTURAL VALIDATION
    ↓
SEMANTIC VALIDATION
    ↓
INVARIANT CHECKING
    ↓
VERIFICATION
    ↓
RETRY / REPAIR / ESCALATION
    ↓
SAFE EXECUTION
    ↓
POST-EXECUTION VERIFICATION

Compare that to what most systems actually build:

MESSY INPUT
    ↓
LLM
    ↓
REAL-WORLD ACTION

The naive version has exactly one boundary — the edges of the prompt and the parsing of the response — and the entire distance between "messy world" and "real-world action" is crossed inside a single probabilistic hop. Every uncertainty in the input and every error in the model's reasoning has an unobstructed path to production state.

The deterministic shell doesn't try to shrink the probabilistic region to zero. It fences it. Everything upstream of the LLM call — normalization, context assembly — is deterministic code you can unit-test. Everything downstream — validation, verification, execution — is deterministic code you can unit-test. The LLM sits in the middle doing the one thing it's actually good at: interpreting messy, ambiguous, underspecified language and proposing a structured hypothesis. It is not asked to also be the type checker, the authorization system, or the transaction log, and it is never allowed to be the last check before an action executes.

The meeting example: from raw prompt to bounded execution

A user says: "Book me a meeting tomorrow evening with Rahul."

The naive path. Prompt goes to the LLM. The model has no reliable access to the current date, the user's timezone, or which of the three Rahuls in the user's contacts is meant. It picks the most probable interpretation, calls a calendar tool, and the event is created. If the retry logic fires because the tool call timed out, the event may be created twice. If the model guessed wrong about which Rahul, the wrong person now has a meeting invite with the user's manager's calendar attached.

Every one of those failures was avoidable, and none of them required the model to be "smarter." They required the system around it to stop pretending these were solved problems.

Walk through what's actually uncertain in that one sentence:

  • Which Rahul — the model cannot resolve this from the sentence alone; it needs the user's actual contact list.
  • What date is "tomorrow" — this is arithmetic on a clock the model doesn't have unless it's given the current timestamp.
  • What time is "evening" — this is a convention, not a fact, and conventions vary by person and culture.
  • How long is the meeting — unstated, and a default is an assumption, not information.
  • Is Rahul available — this is a fact about the world the model cannot know without querying a calendar.
  • Does the user have permission to create this event on the relevant calendar — an authorization fact, not a language-understanding fact.
  • Did the calendar API actually create the event — an outcome fact, observable only after the action, not before.
  • Was it created twice — a consequence of retry logic interacting badly with a non-idempotent action.

None of these are things the model should be expected to "just get right" through better prompting. They are things the system should resolve deterministically, or explicitly flag as unresolved, before the model's interpretation is allowed to become an action.

The reliable path:

USER INPUT
    ↓
DETERMINISTIC ENVIRONMENT ATTACHMENT
  — current timestamp, resolved timezone
  — authenticated user identity
  — user's actual contact list (not the model's guess at it)
    ↓
LLM INTERPRETATION
  (produces a candidate structured intent, not an action)
    ↓
TYPED INTERMEDIATE REPRESENTATION
  { contact_candidates: [...], date: ISO-8601 | null,
    time_window: ..., duration_minutes: int | null,
    confidence_per_field: ... }
    ↓
DETERMINISTIC VALIDATION
  — is date resolvable and in the future?
  — does contact_candidates have exactly one match?
    ↓
EXPLICIT AMBIGUITY STATE
  if multiple Rahuls or missing duration → AMBIGUOUS, not a guess
    ↓
CLARIFICATION (only if AMBIGUOUS)
    ↓
PERMISSION CHECK
  — deterministic authorization logic, not model judgment
    ↓
IDEMPOTENT EXECUTION
  — request carries a client-generated idempotency key;
    a retried call cannot create a second event
    ↓
POSTCONDITION VERIFICATION
  — read the calendar back; confirm the event exists,
    at the resolved time, with the resolved attendee

Notice what changed. The LLM still does the one thing only it can do — turning "tomorrow evening with Rahul" into a structured candidate interpretation. But it no longer decides which Rahul when there are three; the system surfaces that as an explicit AMBIGUOUS state and asks. It no longer computes "tomorrow"; the system hands it an actual timestamp and lets deterministic code do the date arithmetic. It no longer gets to skip the permission check by being persuasive. And its claim that the event was created is never trusted on its own word — the system verifies the postcondition by reading the calendar back.

The same pattern generalizes directly. In a financial-operations context, a model can propose that a transaction matches a refund policy, but the actual balance check, fraud threshold, and transfer execution should be deterministic code with the model's output as one signed input, not the executor. In customer-support refunds, the model can extract the claimed reason and amount from a support ticket, but whether that refund is authorized should be a rule evaluated against the order and payment records, not against the model's summary of them. In document extraction, the model can propose field values from a scanned form, but a value should only be accepted automatically if it's cross-checked against a second signal — OCR confidence, a checksum, a database lookup — not accepted because the model stated it fluently.

The uncertainty propagation problem

Here is the mechanism behind almost every LLM production incident that isn't a pure outage: uncertainty enters the system honestly, as ambiguity in the input, and leaves the system dishonestly, as unearned confidence in the output.

Unreliable:
  AMBIGUOUS INPUT → CONFIDENT INTERPRETATION → IRREVERSIBLE ACTION

Reliable:
  AMBIGUOUS INPUT → EXPLICIT STATE → CLARIFY / VERIFY / ESCALATE → BOUNDED ACTION

The failure isn't that the model was uncertain — it's that the uncertainty was never represented. It existed for a moment as low probability mass spread across several plausible continuations, and then it was collapsed, silently, into a single string that looks exactly as confident as a correct answer would have looked. Nothing downstream can distinguish "the model was sure" from "the model picked one of several equally likely options and formatted its pick nicely," because that distinction was thrown away at generation time.

This is the deepest architectural claim in this article, and it's worth stating precisely: every boundary around an LLM should convert hidden uncertainty into an explicit, inspectable, measurable system state — not collapse it into "the model returned an answer."

Uncertainty as a first-class system state

Binary success/failure is the wrong data model for this problem, for the same reason a build system that only reports "compiled" or "did not compile" is useless for tracking down a subtle type error. A useful pipeline needs a richer vocabulary:

  • VALID — passed syntactic, structural, and semantic checks; safe to proceed.
  • INVALID — failed a deterministic check; reject or repair.
  • AMBIGUOUS — multiple plausible interpretations exist and the system cannot deterministically pick one (the "which Rahul" case).
  • INSUFFICIENT_EVIDENCE — the claim may be true, but nothing in context supports or refutes it (the "required document" case from the opening example — this state, honestly represented, is exactly what should have appeared instead of approve, 0.97).
  • CONFLICT — two sources of evidence disagree and the system has no deterministic rule for resolving the disagreement.
  • NEEDS_RETRY — a transient failure (tool timeout, malformed output) where retrying is expected to help.
  • NEEDS_REPAIR — the output is close to valid and a targeted, narrow correction is likely to fix it.
  • NEEDS_HUMAN — the system has exhausted its deterministic and probabilistic options and the decision should not be made without a person.
  • SAFE_TO_EXECUTE — the result has cleared semantic verification and the operational reliability bar for this specific action's blast radius.

The point of this vocabulary isn't the specific names. It's that each state is something you can log, alert on, measure the rate of, and route differently. A system that only ever emits VALID or throws an exception has thrown away the information that would tell you why it's failing and how often each failure mode occurs. You cannot improve what you cannot see, and "the model returned an answer" sees nothing.

What belongs inside the probabilistic region, and what must remain deterministic

LLMs earn their place doing things that are genuinely hard to specify with rules: interpreting messy or informal language, extracting latent intent from underspecified requests, handling ambiguity that requires world knowledge to even notice, generating candidate hypotheses when the space of possibilities isn't enumerable in advance, synthesizing across unstructured sources, and planning under incomplete information.

Deterministic code should own: type and range validation, calculations, authorization and permissions, state transitions, database constraints, business rules that are actually rules (a refund policy with fixed thresholds is a rule, not a judgment call), idempotency, transaction boundaries, the act of execution itself, and invariant enforcement.

This is not a clean binary. A meaningful set of tasks sit in between and need hybrid verification: "does this refund reason match the stated policy" is partly rule-based (is the item within the return window — deterministic) and partly semantic (does the customer's free-text explanation actually describe a covered scenario). The honest position is that hybrid tasks need their own verification strategy, not that they can be forced into either bucket by rephrasing the problem until it fits.

The hard problem: semantic verification

This is where the architecture stops being comfortable. Some semantic checks require another probabilistic judgment. Doesn't that just move the reliability problem one layer over, rather than solving it?

Mostly, yes — and that has to be said plainly. Several verification strategies exist, and none of them is a clean escape:

Deterministic checks — the strongest available option when it applies. Does the extracted date parse as a valid calendar date? Does the amount match the sum of the line items? These are real checks with real guarantees.

Source-grounded verification — checking a specific claim against a specific document reduces "is this true" to "is this supported by this text," which is narrower and more checkable.

Cross-field consistency — does the evidence field actually support the decision field, independent of whether either is externally true? This catches a specific and common failure mode (internally incoherent output) without requiring any external ground truth.

Independent model verification — running a second, differently-prompted model as a check. Zheng et al.'s MT-Bench and Chatbot Arena work documented measurable position bias (favoring whichever option appears first) and verbosity bias (favoring longer answers) (Zheng et al., 2023). Wataoka, Takahashi, and Ri identify self-preference bias specifically — a model rating outputs stylistically similar to its own more favorably — and show this correlates with familiarity (low perplexity to the judge), not correctness (Wataoka et al., arXiv:2410.21819, 2024).

Abstention and selective prediction — a system can decline to answer when calibrated confidence is below a threshold. Mohri and Hashimoto's conformal factuality work shows conformal risk control can provide finite-sample guarantees on the error rate among the answers the system chooses to give, at the cost of coverage (Mohri & Hashimoto, 2024).

Self-correction — asking a model to review its own output is a weak mechanism. Huang et al.'s controlled study found LLMs struggle to self-correct reasoning errors without external feedback, and performance can degrade after a self-correction pass (Huang et al., arXiv:2310.01798, 2023). Tsui identifies a specific "self-correction blind spot": models catch errors reliably when introduced by someone else but fail to catch the identical error in their own prior output (Tsui, arXiv:2507.02778, 2025).

Human escalation — the honest fallback when the above aren't sufficient for the stakes involved. Routing genuinely unresolvable ambiguity to a person is exactly what the NEEDS_HUMAN state is for.

You cannot wrap an open-ended reasoning task in enough if statements to make truth deterministic. What the shell can do is narrow the space of claims requiring open-ended verification to the smallest possible surface, handle everything reducible to a deterministic or source-grounded check outside that surface, and make sure the remaining genuinely hard cases are visibly flagged rather than silently passed through.

Failure containment rather than failure elimination

A circuit breaker does not make the downstream dependency more reliable. It stops that dependency's unreliability from becoming the caller's unreliability. A bulkhead does not stop one thread pool from failing. It stops that failure from exhausting resources needed by everything else. The unit of success in both patterns is not "nothing fails." It's "failure stayed where it started."

Applied here: the goal is not "the LLM never fails." The goal is "when the LLM fails, how far does the failure travel before something catches it?"

That single sentence hides two different measurements:

  • Containment depth — how many independent enforcement boundaries exist between the probabilistic core and an irreversible action. This is a property of the design, fixed before any error occurs. Higher is better.
  • Escape distance — how many of those boundaries a specific, actual failure crossed, undetected, before something caught it. This is a property of an incident, measured after the fact. Lower is better.

With that split, the loan example reads correctly: a pipeline with containment depth 4 (schema check, cross-field consistency, source-grounded verification, permission check) where the hallucinated document claim is caught at cross-field consistency has an escape distance of 1. A pipeline where the claim slips past all four has an escape distance of 4 — a total escape. A pipeline with containment depth 1 (schema check only) can never catch a semantic error, regardless of escape distance, because the boundary capable of catching it was never built.

Depth is what you design. Distance is what you measure when something goes wrong.

The reliability ladder

A rough progression, useful as a self-assessment tool:

  • Level 0 — Raw generation. No parsing, no checks. The output is used as-is.
  • Level 1 — Parseable output. You can reliably extract structure from the text.
  • Level 2 — Schema-constrained output. Constrained decoding or strict-mode APIs guarantee valid, typed JSON.
  • Level 3 — Deterministic validation. Range checks, enum checks, cross-field consistency — all reducible to fixed code.
  • Level 4 — Semantic verification. Source grounding, independent checks, calibrated confidence — the level most systems skip entirely.
  • Level 5 — Bounded execution. Actions are gated by explicit permission and safety checks, and irreversible actions get extra scrutiny proportional to their blast radius.
  • Level 6 — Recovery and escalation. NEEDS_RETRY, NEEDS_REPAIR, and NEEDS_HUMAN are real, monitored code paths, not unhandled exceptions.
  • Level 7 — Measured reliability. The rate of each explicit state is tracked over time, so degradation is visible before it becomes an incident.

Schema-constrained output (level 2) is by far the most common thing teams reach for. Semantic verification (level 4) is comparatively rare, and the gap between the two is usually a decision that was never made explicitly — teams default to level 2 because it's what the SDK gives you for free, not because level 4 was evaluated and judged unnecessary.

What this architecture cannot solve

This section is load-bearing, because a thesis that doesn't survive its own limits isn't a thesis, it's marketing.

Wrong specifications. If the schema or permission model encodes the wrong policy, a deterministic shell will enforce the wrong policy with perfect consistency. Determinism guarantees consistency, not correctness of the thing being enforced.

Incomplete world models. The system can only check claims against evidence it has access to. If the "required document" were fabricated by an upstream system, source-grounded verification would pass a false claim.

Unobservable truth. Some claims — "this customer's stated reason for a refund reflects their actual intent" — have no ground truth the system can query.

Correlated verifier failures. If the verifier is another LLM sharing training data with the generator, its checks are not independent evidence.

Adversarial inputs. A user who understands the validation logic can craft input designed to produce a false VALID state.

Distribution shift. Deterministic rules and calibration thresholds tuned against past data degrade silently when the input distribution moves.

Validator bugs. The deterministic shell is still software, written by people, and can itself contain bugs. It guarantees that when something is wrong, it's wrong in code you can read, test, and step through — which is a meaningfully weaker but genuinely useful property.

Excessive complexity. Past some point, a shell with enough validators, retries, and escalation paths becomes a large distributed system in its own right. Not every task justifies level 5 or 6.

Open-ended tasks with no verifiable answer. "Write a compelling opening paragraph" has no INVALID state to check against. The architecture has essentially nothing to offer tasks where there is no external standard of correctness.

The research question

Underneath the engineering advice is a genuine open research question: where should probabilistic behavior be permitted inside an AI system, and can deterministic boundaries measurably prevent uncertainty from propagating into system state and real-world actions?

Consider a pipeline as a sequence of boundaries B₁, B₂, ..., Bₙ between the probabilistic core and an irreversible action A. Let an error of class e enter the pipeline at the core. Define:

p(Bᵢ, e) = probability that boundary Bᵢ detects an error of class e,
           given that the error reached Bᵢ undetected

containment depth  = n  (design-time property)

escape distance(e) = boundaries a specific error crossed undetected
                     (incident-time property — 0 ≤ escape distance ≤ n)

escape probability(e) = ∏ᵢ (1 − p(Bᵢ, e))   [if the Bᵢ are independent]

The independence assumption is unsafe by default — correlated verifiers push the real escape probability higher than the naive product suggests. A more honest version would replace the product with a joint distribution over which boundaries share failure modes.

These quantities are offered as a vocabulary that turns research questions into things with units — not as claims that have been measured.

Conclusion

Don't ask how to make the model stop being probabilistic. Ask where uncertainty is allowed to exist, how it's represented once it does, and what stops it from crossing the next boundary unchecked.

The model can remain probabilistic. The system does not have to remain uncontrolled.


Further Reading

  • Horace He et al., "Defeating Nondeterminism in LLM Inference," Thinking Machines Lab, 2025
  • Bertrand Meyer, Object-Oriented Software Construction — Design by Contract
  • Michael T. Nygard, Release It! — circuit breakers and bulkheads
  • J. H. Saltzer, D. P. Reed, D. D. Clark, "End-to-End Arguments in System Design," ACM Transactions on Computer Systems, 1984
  • "JSONSchemaBench: A Rigorous Benchmark of Structured Outputs for Language Models" (arXiv:2501.10868)
  • Huang et al., "Large Language Models Cannot Self-Correct Reasoning Yet" (arXiv:2310.01798)
  • Tsui, "Self-Correction Bench" (arXiv:2507.02778)
  • Wataoka, Takahashi, Ri, "Self-Preference Bias in LLM-as-a-Judge" (arXiv:2410.21819)
  • Zheng et al., "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena"
  • Geifman & El-Yaniv, "Selective Classification for Deep Neural Networks"
  • Mohri & Hashimoto, "Language Models with Conformal Factuality Guarantees"