Most "AI systems" fail in production for a boring reason: they hand the model work that plain code should have done. The model is non-deterministic, so the whole system becomes non-deterministic — and non-deterministic systems are hard to trust with real money and real operations.
Our default is the opposite. Deterministic first, AI second. Code owns everything that can be specified. The model is reserved for the small set of decisions that actually require judgment.
The dividing line
When we design an agentic workflow, we sort every step into one of two buckets:
- Mechanical — can be expressed as rules, lookups, joins, or arithmetic. This is code.
- Ambiguous — requires reading unstructured context and forming a judgment. This is the model.
A reconciliation pipeline is a good example. Matching a payment to an invoice by ID is mechanical. Deciding whether a $312.40 short-pay is a contractual adjustment or an error is ambiguous.
The goal isn't to use AI everywhere. It's to use AI only where deterministic software would be worse.
What this looks like in code
The transaction logic runs as ordinary, testable functions. The model is called through a narrow interface, and only when a case falls through the deterministic path:
function reconcile(payment: Payment, invoices: Invoice[]) {
const exact = invoices.find((i) => i.id === payment.ref && i.total === payment.amount);
if (exact) return { status: "matched", invoice: exact }; // mechanical — no model
const candidates = shortlist(payment, invoices); // mechanical — cheap filter
if (candidates.length === 0) return { status: "unmatched" };
// ambiguous — hand just this decision to the model, with structure
return investigate(payment, candidates);
}
The model never sees the whole system. It sees one decision, with the relevant context, and returns a structured result the surrounding code can verify.
Why it holds up
| Property | Deterministic core | Model at the edges |
|---|---|---|
| Reproducible | Yes | No — so we constrain it |
| Testable | Unit tests | Golden cases + verification |
| Auditable | Fully | Decision + rationale logged |
| Cost | ~0 | Only on ambiguous cases |
Because the model runs on a fraction of the volume, the system is cheaper, faster, and far easier to reason about when something goes wrong. When a number looks off, you can trace it — the deterministic path is a straight line, and the model's touches are logged with their inputs and rationale.
The takeaway
Reliability isn't the thing you add after the demo. It's the architecture. Put the model where it earns its keep, and let boring, correct code do everything else.