The Missing Step Before Any AI-Assisted Design: Domain Ontology

By | March 19, 2026

Most teams are good at building. APIs, services, workflows, integrations. They ship.

Now ask a simple question: what exactly is a “Customer” in your system?

You will probably get three answers from three teams, four variations across four services, and if you have introduced AI into the delivery pipeline, five AI-generated outputs that each made a slightly different inference about what the word means.

That is not an AI problem. It is a missing ontology. And in an AI-assisted world, the cost of not having one just went up significantly.


Why this matters more with AI

Before AI, weak domain definition created drift slowly. A service misunderstood a concept. An API leaked a local interpretation. Six months later, integration pain arrived.

Add agentic AI to that picture. The AI can accelerate design, code generation, test generation, documentation, and refactoring. But it does not invent clarity. It amplifies whatever clarity or ambiguity already exists in your domain.

So if your domain is vague, AI does not solve that. It industrialises it: ambiguous concepts get repeated faster, weak boundaries get embedded deeper, inconsistent naming becomes harder to unwind, bad assumptions spread across specs, code, tests, and documentation in a single session.

In greenfield, you can accidentally build confusion at speed. In brownfield, you can accidentally preserve and multiply legacy confusion under the banner of modernisation. Neither outcome is what AI was supposed to deliver.


What an ontology actually is

In software architecture, an ontology is the formal definition of what exists in the domain: what the core concepts are, what they mean, and how they relate. It is the semantic foundation of the solution.

It is not a database schema. It is not an API contract. It is not a class model or a topic schema. Those are downstream artefacts. The ontology sits above them and gives them meaning.

A simple way to hold this: the ontology defines the nouns and the truths. Specs define the behaviours. APIs, events, and interfaces expose those behaviours. Code implements them.

Most teams skip from requirement straight to API and code. That sequence feels efficient, especially in a delivery environment that rewards visible progress. But without the ontology underneath, the spec redefines terms each time, the API leaks local assumptions, the implementation hardcodes accidental semantics, and the AI fills the gaps with pattern-matched guesswork.

This is how you end up with “Customer” meaning a legal entity in one service, a tenant in another, a billing account somewhere else, a user’s organisation in the UI, and a CRM record in reporting. Everything looks coherent in isolation. Integration, migration, onboarding, and audit are where the cracks appear.


Greenfield: the false confidence problem

In greenfield work, the danger is false confidence. Nothing exists yet, so teams assume they can define meaning later.

They start generating designs, services, events, and workflows quickly — especially with AI support — and early terminology hardens fast. Once “Customer”, “Account”, “Organisation”, “Tenant”, “User”, and “Party” are used loosely across prompts, specs, and code, you have created semantic debt before a single user has touched the system.

The terms become load-bearing before anyone agreed what they meant. Changing them later is not a search-and-replace. It is an architectural rework.


Brownfield: the inherited ambiguity problem

In brownfield work, the danger is inherited ambiguity. Legacy estates typically contain mixed meanings, historical compromises, duplicated concepts, and naming that made sense at the time but no longer reflects the business.

When modernising with AI, teams often feed existing artefacts into the tool and ask it to transform, refactor, or document. The AI will mirror the mess back in cleaner syntax. That is not transformation. It is ambiguity preservation with better formatting.

Brownfield work requires an explicit decision before the AI touches anything: which concepts are genuinely distinct, which are aliases for the same thing, which are legacy artefacts with no future, and which truths must survive the transition. Without that decision, the target state becomes a polished version of the old confusion.


A practical example: Customer Onboarding

Take a SaaS platform building a customer onboarding capability. The business intent sounds straightforward: register a customer, provision access, create the initial user context, enable service usage.

Most teams jump straight to API and workflow design. If you ask an AI to help at that point, it will produce something that looks entirely reasonable: a POST /customers endpoint, a POST /accounts endpoint, a POST /users endpoint with a customerId foreign key. Plausible. Deployable. And built on a set of assumptions that nobody agreed — about what a Customer actually is, whether Account and Customer are the same thing in your domain, what “user” means relative to the organisation consuming the platform, and what constitutes a valid identity.

Those assumptions will diverge from what the business means. They will diverge between services. They will diverge between the onboarding flow and the billing system and the reporting layer. Not because the AI did anything wrong, but because nobody told it what these things mean in your specific domain. It inferred, based on what most systems do, not on what your system should do.

The fix is to define before you design.

Start by defining what exists. Not as a schema, not as a class hierarchy — as a plain statement of business reality.

A Customer is the commercial or contractual party consuming the platform. Depending on the business model, this might be an organisation or an individual. The key point is that it is the entity that holds the contract, owns the billing relationship, and is accountable under any regulatory or compliance framework. It may own one or more Accounts. It must be identifiable through at least one recognised Identifier.

An Account is the service or operational context through which capabilities are consumed. It is not a synonym for Customer. A Customer might have multiple Accounts representing different environments, regions, or product tiers. An Account belongs to exactly one Customer. It may be linked to subscriptions, service entitlements, billing rules, or provisioned environments. It may have multiple Users with different roles.

A User is an individual actor interacting with the platform. They act on behalf of a Customer and have access to one or more Accounts depending on the access model. They have one or more Roles that govern what they can do within each Account. They must have a unique identity within the defined identity boundary — which itself needs to be explicit. Is uniqueness scoped to the Account, the Customer, or the platform?

An Identifier is a domain-recognised reference used to uniquely identify a Customer, Account, or User within a given business context. This matters more than it looks. Teams routinely treat identifiers as just strings: a UUID here, an email there, a company registration number somewhere else. But identifiers carry semantic weight. A company registration number is regulated. An email is mutable. A UUID is opaque. Treating them as interchangeable creates problems in onboarding, auditing, and data sovereignty. The ontology names them explicitly and states what makes each one valid.

At this point: no API, no orchestration, no screen flow, no AI-generated service skeletons. Just a disciplined definition of reality.

Now add the invariants: the things that must always be true, regardless of how the system is built or changed. A Customer must have at least one valid Identifier before any Account can be created for it. An Account must belong to exactly one Customer and that relationship must be established at creation, not inferred later. A User must not exist without an owning Customer context. An onboarding flow must not activate service access unless a valid Customer, a linked Account, and at least one authorised User all exist. Service activation cannot proceed if any upstream entity creation failed.

These are not implementation details. They are truths. They must survive UI changes, API versions, batch imports, event-driven flows, data migrations, AI-generated refactors, and brownfield coexistence. If they are only enforced in one service or one form, they are local validations pretending to be architecture. The invariants belong in the ontology document, not scattered across validator classes.

With that foundation, the spec follows naturally. The business process — onboard a customer — now has a precise meaning. Capture Customer details and validate against the Identifier rules. Create the Customer only once all required Identifiers are confirmed. Create the Account and bind it to the Customer in the same transaction. Create the initial User and assign the appropriate Role within that Account. Activate service access only on confirmation that all three entities exist and are valid.

Notice what that spec does not do: it does not define what a Customer is. That was already done. It does not define what a valid Identifier looks like. That was already done. The spec operates on agreed concepts rather than trying to define them at the same time as specifying behaviour. That separation is what keeps specs clean and what keeps AI-generated implementations consistent across sessions, services, and teams.


What a strong ontology actually gives you

Once the ontology exists, AI becomes a reliable accelerator. Not before.

With agreed concepts and invariants in place, you can prompt the AI to generate first-pass specs that reference those concepts consistently. You can ask it to challenge edge cases against the invariants. You can use it to identify naming drift across services, generate test cases aligned to business truths, map brownfield artefacts to target concepts, and document process flows that respect the agreed semantics.

Without that foundation, the AI does all of those things anyway — based on inferences you never validated. It collapses distinct concepts into one when they look similar. It splits one concept into several when context varies. It generates APIs that expose implementation structure rather than business meaning, because implementation structure is what it can see.

There are five concrete benefits worth naming.

Ontology constrains AI productively. Instead of prompting “generate onboarding APIs”, you can prompt “generate onboarding APIs based on the agreed ontology where Customer, Account, User, and Identifier have the following meanings and invariants.” That is a completely different quality of instruction. The output reflects the constraint.

It reduces semantic drift across teams. When multiple teams are working in parallel, each AI-assisted stream speeds up independently. Without a shared conceptual foundation, the streams diverge by default. Ontology is what keeps multiple humans and multiple AI workflows aligned.

It makes brownfield modernisation safer. Ontology gives you a way to separate current implementation, current terminology, and target meaning. Legacy systems encode historical constraints, not ideal business concepts. Without making that distinction explicit, modernisation drags yesterday’s model into tomorrow’s platform.

It strengthens specs. A weak spec usually hides weak semantics — it describes steps but not meaning, flows but not truths. A strong ontology underneath makes specs simpler, clearer, and less contradictory. The spec can reference agreed concepts rather than redefining them each time.

It improves interface design. APIs, events, commands, and queries become more coherent when they are built on agreed domain semantics. You stop arguing about field names and start asking the better question: does this interface faithfully represent the domain concept and process we agreed?


What goes wrong without it

The failure modes are predictable once you know to look for them.

Inconsistent meanings: the same term means different things in different places, and integration becomes translation work. Fragmented rules: core truths get implemented differently across the UI, API, workflow, migration, and reporting layers, and nobody can tell which version is authoritative. Confused modernisation: brownfield systems get wrapped rather than clarified, and the target state inherits the old confusion. Poor AI outputs: generated artefacts look polished but disagree semantically. Expensive refactoring: the team eventually realises the disagreement is conceptual, not technical, which makes change far more invasive than if the concepts had been agreed upfront.


A better sequence for architects

The question most teams start with is: “What services and APIs do we need?”

The question that produces better systems is: “What exists in this domain?”

Start there. Define each core concept in a sentence — what it is and what it is not. Then define the invariants: the things that must always be true, regardless of how the system is built or changed. Then specify the behaviours that operate on those concepts. Then define the interfaces that expose those behaviours. Only then ask the AI to help build them.

That order matters. Meaning before mechanics is what prevents delivery speed from becoming architectural drift.


Devil’s advocate

The honest objection is overhead. Defining an ontology before building anything sounds like exactly the kind of architecture ceremony that slows teams down without visible output.

For a small, isolated, low-risk system with one team, one service, and no shared concepts, that objection has some merit. Loose modelling is a reasonable trade-off when the scope is genuinely contained.

It stops being reasonable the moment you have multiple teams, shared domain concepts across services, any meaningful integration surface, legacy modernisation, or AI-assisted generation of specs and code. At that point the ontology is not ceremony — it is the thing that stops multiple AI-assisted workflows from drifting apart the moment they speed up.

There is also a scale argument worth pushing back on. Getting ontology right upfront is not a week-long workshop. For a focused capability, a disciplined team can define the core concepts, their relationships, and the critical invariants in a few hours. The output is a short document — five concepts, ten invariants, one page. The cost of not doing it tends to be measured in weeks of integration rework, not hours of ceremony.


What to do

Before your next greenfield feature or brownfield change, do this before opening a prompt.

Write down the three to five core concepts involved in what you are building. For each one, write a single sentence that defines what it is and what it is not. Then write the invariants: the things that must always be true, regardless of how the system is built or changed.

Share that with the team and check for disagreement. Disagreement at this stage costs nothing. Disagreement after the AI has generated three services and a spec costs days.

Put the result in a file in your repo. Reference it in your CLAUDE.md. From that point, every prompt you write will be working with agreed concepts rather than inferred ones. The AI becomes a reliable accelerator rather than a very fast source of drift.

You stop rediscovering the domain in every service, every prompt, and every project. You start building on purpose.

Leave a Reply