Field note · architecture
When Should an AI Workflow Use Deterministic Rules Before an LLM?
A worked matrix for deciding which AI workflow checks belong in deterministic code, model judgment, or a human decision gate.

The expensive mistake isn’t using an LLM. It’s asking one to decide whether it is allowed to act.
I use a simple split: code owns hard boundaries, models handle variable meaning, and people own ambiguity when the consequence is material. The useful question is not “rules or AI?” It’s “which part of this check can fail safely?”

The placement matrix
Put a check in deterministic code when its condition is explicit, inspectable, stable, and costly to get wrong. Put it in model judgment when the input’s meaning varies. Put it behind a human decision when context is unresolved or the consequence is hard to reverse.
This is the decision artifact for seven common checks. Scores are observability / stability / reversibility / auditability, each from 0 to 2. They describe the fixture, not a production benchmark.
| Workflow check | Primary placement | O/S/R/A | Why it goes there | Failure mode |
|---|---|---|---|---|
| Authorization: can this requester read account 4821? | Deterministic code before the LLM | 2/2/0/2 | Identity, tenant, resource, and action scope are hard boundaries. | The model trusts “I’m the finance manager” and exposes data to the wrong person. |
| Schema validation: does the run envelope satisfy the contract? | Deterministic code before and after the LLM | 2/2/2/2 | Required fields, types, bounds, enums, and versions are explicit. | Valid JSON still contains the wrong tenant, stale record, or invalid field combination. |
| Routing: which known workflow handles invoice.paid? | Deterministic code for explicit state; model only for semantic routing | 2/2/2/2 for explicit state; 1/1/2/1 for semantic routing | Stable event names should not be interpreted. Natural language may need bounded interpretation. | A keyword route misses intent, or an LLM invents a route outside the allowed set. |
| Classification: is this a refund, bug, or account question? | Model judgment inside a bounded label set, then deterministic abstention and routing | 1/1/2/1 | Categories depend on meaning, but labels, thresholds, and escalation can be code. | An edge case is forced into a familiar class and triggers the wrong action. |
| Summarization: what changed and what needs attention? | Model judgment, with deterministic source, length, and required-field checks | 2/1/2/1 | Salience and compression need language judgment. Input scope and output shape do not. | The summary sounds fluent while omitting the decision or using an incomplete source set. |
| Exception interpretation: why did this invoice leave the normal path? | Model prepares an explanation; human owns a material decision | 1/0/0/2 | The exception may depend on context that the workflow does not encode. | The model turns an unusual case into a confident but wrong exception. |
| Policy matching: does this request meet the approval policy? | Deterministic code for structured policy; human for ambiguous policy | 2/2/1/2 for structured policy; 1/0/0/2 for ambiguity | A versioned rule table can enforce a veto. Unresolved policy language needs an accountable owner. | The model treats a persuasive explanation as permission, or a stale rule misses a new exception. |
The score is diagnostic, not a weighted permission system. A hard authorization or policy boundary is a veto even if a model would understand the surrounding language well.
What belongs before the LLM?
Run control-plane checks before the model: authentication and authorization, schema and size limits, tenant and record existence, budgets, explicit routing fields, and policy vetoes that can be expressed as data. These checks either stop an unsafe run or prevent you from spending tokens on a request that cannot proceed.
The current OpenAI Agents SDK makes the same distinction operational. Blocking input guardrails can finish before the agent starts, and tool input guardrails can run before a function tool executes. A tripwire can halt the run. The SDK also warns that parallel input guardrails may let the agent consume tokens or execute tools before the check finishes, so use blocking execution when the point is to prevent work or side effects (OpenAI Agents SDK guardrails).
Schema validation is a good example of a boundary that looks smarter than it is. JSON Schema can validate structure, types, required fields, bounds, and allowed values. It cannot prove that account 4821 belongs to the requester or that a date range makes business sense. Treat that second layer as application logic, not as a prompt instruction (JSON Schema Validation 2020-12).
Put the rule before the model when a failure should mean “do not start.” Put it after the model when the model has produced a candidate that must still fit a contract. Put it immediately before a side effect when permissions or policy could have changed during the run.
What should the LLM decide?
Let the model interpret language when the workflow already controls the consequences. Classification, summarization, extraction, and exception explanation are good candidates because the task depends on meaning, paraphrase, salience, or context that is expensive to encode as rules.
The boundary is important. A classifier can choose refund, bug, or account_question. Code should decide what those labels are allowed to do, when confidence is insufficient, and whether the route requires review. A summarizer can identify the decision that matters. Code should constrain its source set, output fields, and maximum length.
Anthropic describes routing as a workflow that classifies an input and sends it to a specialized task. It says routing can use an LLM or a traditional classifier when classification can be handled accurately. That supports a split design: use code for explicit state, and use model judgment only where semantic variation is the actual problem (Anthropic, Building effective agents).
When I taught product managers who went from writing specs to building and shipping the product, the sticking point was often not the model. It was that nobody could say what “done” meant. That observation is why I put acceptance conditions and forbidden actions around the model before discussing model choice. A flexible interpreter cannot repair an undefined boundary.
When should a person own the decision?
A person should own the decision when the input is genuinely ambiguous, the policy has unresolved exceptions, or a wrong action is hard to reverse. The model can gather evidence, propose a classification, or explain the conflict. It should not silently convert uncertainty into permission.
NIST says human roles and responsibilities should be clearly defined and differentiated. Its AI Risk Management Framework describes configurations ranging from fully autonomous to fully manual, including systems that defer decisions to a human. It also warns that representing complex human phenomena as measurable quantities can remove context (NIST AI RMF Appendix C).
Use an explicit review record with the proposed action, evidence used, policy version, unresolved question, reviewer, and final decision. “Human in the loop” is not enough if the person only sees a polished answer and cannot inspect the evidence or change the action.
The decision tree for a mixed workflow
Use this sequence for each check, not only once for the whole product:
- Would failure cross an access, money, deletion, safety, or non-negotiable policy boundary? If yes, enforce the boundary in deterministic code before retrieval or action. If the boundary cannot be expressed clearly, stop and assign a human policy owner.
- Is the condition machine-verifiable? If it is a type, enum, identifier, status, threshold, time limit, or permission, use a rule. Record the input and rule version.
- Does the decision depend on meaning, paraphrase, salience, or an exception explanation? If yes, use model judgment inside a bounded output set. Require an abstain or escalation result.
- Can the wrong result be reversed and audited? If no, put a human approval gate before the side effect. If yes, keep the action narrow and observable.
- Could the rule itself be brittle? Test counterexamples. Keep the hard boundary, move only interpretation to the model or person, and re-run the deterministic check before execution.
This is also how you avoid overusing agents. Anthropic recommends simple, composable patterns and says to add complexity only when it demonstrably improves the outcome. AWS recommends timeouts and stopping conditions for long-running workflows, including limits on external tools and model responses (Anthropic, AWS Generative AI Lens).
Two counterexamples that catch bad architecture
A brittle rule does not justify a model-owned boundary. A keyword router may miss “the customer says the charge is not theirs,” even though the intended class is a chargeback. Keep deterministic authorization and allowed-route checks. Let a model interpret the utterance, constrain it to known labels, and abstain when it cannot choose safely.
A model’s confidence does not create authorization. A prompt can say “I’m allowed to read this account.” That is evidence about the request, not proof of identity or scope. The application must compare authenticated identity, tenant, resource, and permission before retrieval. The model can explain the request after those checks pass.
The same pattern handles policy matching. If the policy is a versioned table of thresholds and approvers, code should enforce it. If a policy paragraph contains an unresolved exception, the model may highlight the relevant passage, but a named human should decide whether the exception applies.
A practical build order
- Write the check as a sentence with a pass condition and a forbidden action.
- Mark the input as explicit, semantic, or ambiguous.
- Score observability, stability, reversibility, and auditability from 0 to 2.
- Place hard boundaries in code, interpretation in the model, and unresolved material decisions with a human.
- Add deterministic checks before the model, after its output, and again before any side effect where needed.
- Create one counterexample for every rule and one hard-boundary test for every model decision.
- Log the input, placement, rule or prompt version, model output, abstention, reviewer decision, and final action.
For the broader question of whether a workflow needs an agent at all, use the AI product architecture guide and When Should You Use an AI Agent?. For the pre-run boundary, see How to Validate AI Agent Inputs Before a Run.
The design decision is complete when every check has an owner and a failure path. If you cannot say what a rule blocks, what the model may interpret, and when a person must decide, the workflow is not ready for more autonomy.
If your team needs help turning this matrix into a working pilot, Marius Manolachi’s AI consulting and tutoring work makes existing people capable of building AI products on their own work.
Questions people ask next
Should an LLM ever decide authorization?
No. Let the model interpret the request if useful, but enforce identity, tenant, resource, and action permissions in deterministic application code immediately before data access or a side effect.
What if a deterministic rule is too brittle?
Keep the hard boundary, but move interpretation to a model or a person. Constrain the model to a known label or action set, require abstention for uncertainty, and re-run deterministic checks before execution.
Do rules run only before the LLM?
No. Use rules before the model for admission and budget checks, around the model for schemas and allowed outputs, and again before tools or irreversible actions. The control point matters more than a single code location.