Pydantic at the door, ontology at the ledger

Frank Coyle’s 21-minute AI Engineer talk, Why agentic systems need ontologies, makes an argument we keep arriving at from a different direction: an agent loop has no built-in notion of correctness, so something outside the model has to hold one. His answer is a formal domain model — an ontology — sitting between the tool result and the write. Ours, in an earlier post, was “every stage an agent touches is followed by a check the agent cannot argue with.” Same instinct, different machinery. Here is his version, what it genuinely buys you, and the three places we would not follow it.

The argument

The setup is that a language model is a probabilistic text generator that cannot tell a true statement from a convincing one. Coyle’s framing is that hallucination is a feature, not a bug — it is the same generative mechanism that makes the model useful, so you do not fix it, you fence it. The model is locked in a box: it can emit a perfectly well-formed instruction to pay an address without any way to know whether that address should be paid.

The second half of the setup is the loop. Model proposes a tool call, application code executes it, the result goes back into context, repeat. That iteration is what makes an agent Turing-complete — and therefore capable of running forever, drifting semantically across turns, and burning tokens doing it. The talk’s point is not that Turing-completeness is bad, it is that you have added unbounded computation on top of a component that cannot evaluate its own output.

So: validate. And validate in two places, which is where the talk’s one memorable line comes from — Pydantic at the door, ontology at the ledger. A type validator confirms the shape of the result. An ontology confirms that what the result asserts is legal in your domain, before anything commits.

What the type checker misses

The four failures the talk uses are all things that pass a schema and still cost real money:

Failure Why the type check passes What catches it
Second refund on an already-refunded order order_id is a valid int Functional property — one refund per order
Payout routed to a support agent, not the customer payee_id is a valid string Class disjointness — a customer is not staff
Status set to “probably shipped” it is a string An enumerated class
Two records for one entity treated as two people both are well-formed A reasoner resolving identity

Row three is the weakest of the four, and worth flagging because it is the one people quote. Literal["refunded", "pending", "failed"] closes it at the door for free — no reasoner required. The rows that earn a symbolic layer are the ones asserting something about the world, not about the message:

class RefundResult(BaseModel):
    order_id: int
    amount_cents: int
    payee_id: str
    status: Literal["refunded", "pending", "failed"]

Every field above can be valid while the refund is still wrong. The shape is not the question.

The tooling is the W3C stack, and it is old and stable: RDFS and OWL for inference and constraints, SHACL — a Recommendation since 2017 — for closed-world validation. A minimal shape for the payout case:

@prefix sh:  <http://www.w3.org/ns/shacl#> .
@prefix ex:  <https://x2code.dev/ns/support#> .

ex:RefundShape a sh:NodeShape ;
    sh:targetClass ex:Refund ;
    sh:property [
        sh:path     ex:payee ;
        sh:class    ex:Customer ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path     ex:againstOrder ;
        sh:maxCount 1 ;
    ] .

With ex:Customer owl:disjointWith ex:SupportAgent in the model, a payout aimed at staff fails validation rather than clearing. The talk’s advice on building these is sensible: do not invent a taxonomy, extend one — schema.org, Dublin Core, FOAF, DBpedia — and combine a top-down skeleton from domain experts with bottom-up structure derived from what the system actually sees.

There is independent evidence the approach helps. A 2026 preprint, Ontology-Constrained Neural Reasoning in Enterprise Agentic Systems, reports 1,800 controlled runs across five regulated domains and three models, with ontology-grounded agents beating ungrounded ones on metric accuracy and role consistency at p < .001. The largest gains were in the Vietnamese-localised domains — roughly double the English-domain effect — which is the result we find most interesting: the guardrail matters most exactly where pretraining coverage is thinnest.

Three places we would not follow it

The authoring burden moved, it did not vanish. Coyle is straight about why expert systems and the Semantic Web stalled — nobody wanted to write and maintain the knowledge. The claim now is that models can extract and maintain ontologies from runtime behaviour. Maybe, but an extracted ontology still needs review, and the moment it drifts from your actual schema you have two sources of truth and no way to know which is stale. That is a maintenance cost, not a free layer.

Most of these are database constraints. A unique index on (order_id) in the refunds table stops the duplicate refund, in one line, at the only place that matters. A foreign key to customers stops the misdirected payout. The reasoner earns its place when the rule spans systems the database cannot see — a refund policy that depends on an entitlement in a different service — not when it restates something your schema could already enforce. Start with the cheap guard.

“Hallucination is a feature” is a description, not a licence. It is accurate about the mechanism and it is a bad posture to design from, because it implies the fence is the whole answer. The cheapest reduction in agent errors we have found is still upstream: fewer tools, narrower ones, and no tool that can move money in a single call. Validation is the last line, not the first.

And on Turing-completeness — the control for a loop that will not terminate is a step budget and a cost ceiling, enforced by the runner. No ontology stops an agent from thinking in circles.

Takeaway

Take the line. Pydantic at the door, ontology at the ledger is the right decomposition: shape and legality are different questions and want different checks. Then note that “ontology” is a spectrum, and for most teams the ledger check is a unique index and a foreign key rather than a reasoner. Reach for OWL when the rule genuinely spans systems, and when you do, extend a public vocabulary instead of inventing one.

The part worth internalising is the placement — after the tool executes, before the state changes. That is the seam, whatever you put in it.

“Building the future, one commit at a time.”