← Blog
DDDSDDAIarchitecturespecification

Your Agent Doesn't Need a Better Spec, It Needs a Boundary

DDD and SDD aren’t two methods to stack. They’re two levels of the same thing: specification.


Plausible code

A retail team adopted spec-driven development for real. Every change starts with a structured specification, a plan, atomic tasks. The agent implements.

On paper, the loop is clean.

Then comes an ordinary ticket: reject the order if stock is insufficient. The agent produces this.

if (stock.quantite >= quantiteDemandee) {
    // ...
}

The code compiles, the tests pass, the review passes. The developer reviewing it that day doesn’t have the subtleties of the stock promise in mind.

Three weeks later, a flash sale generates four hundred orders that can’t be honored on a single SKU. About a hundred get charged.

Nobody did bad work: the agent did exactly what was asked. But the same word meant three different things.

The ticket said “stock.” The business meant what can still be promised. The agent read the column named stock.

Nothing, from ticket to code, carried that difference.

What SDD solves, and what it doesn’t

Spec-driven development crystallized in 2025, against “vibe coding.” Microsoft gave a name to what SDD fights: “translation loss.”

Meaning leaks at every handoff. From business need to requirements, then to architecture, to code, to validation.

AI speeds up these handoffs, but, in Microsoft’s words, “it cannot correct ambiguity that was never resolved.”

What SDD brings is the transmission of intent. What you want, under what conditions, with what verifiable criteria.

It leaves two gaps.

Vocabulary. A specification is written in natural language. If the term is ambiguous, the specification is too, and no formalism catches that.

Reject if stock is insufficient is a well-formed sentence that says nothing.

Scope. SDD works at the feature level. But offer in-store pickup within two hours touches Assortment, Availability, Sales and Fulfillment.

Where does the agent stop? Which tables can it write to? Which tests are authoritative?

A feature-level specification can’t answer that. It’s not the right level.

These are the two gaps DDD fills, with three notions instead of thirty. Microsoft’s guidance on enterprise SDD reaches the same conclusion: modular, layered specs rather than a monolithic document, split along bounded contexts.

Three levers

1. The ubiquitous language compresses the domain

The word that cost four hundred orders:

Context”Stock” means
Saleswhat I can still promise, on this channel
Warehousewhat’s physically on the shelves
Purchasingphysical + in transit − reserved

All three definitions are true, each in its own home.

This is a property of the model, laid out by Evans in 2003: each bounded context carries its own “ubiquitous language,” and the same word takes different meanings across them. The Azure Architecture Center repeats it, using “account” as an example. Ours is “stock.”

Write “stock” in a specification without pinning the context, and the agent picks one of the three meanings. Almost always the one that looks like a database column, because that’s the strongest signal in the repo.

The price of that choice is a hallucination consistent with the rest of the code, and therefore invisible in review.

Picking one official meaning doesn’t work: none of the three will yield, and all three are right.

The way out is two moves. Name the context that owns the question, Availability. Forge a term there that can’t be read three ways, sellable.

A well-chosen term saves two hundred words of explanation. “Sellable” alone carries the deduction of reserved units, disputes, and safety stock.

Retail has already coined this under its English name, “available-to-promise”: what you can promise, not what you own.

And “stock” disappears from specifications. It never belonged there.

One mix-up worth flagging: identifiers cross contexts; meanings don’t.

A GTIN identifies the same product everywhere, which is what makes integrations possible. But a shared identifier doesn’t force a shared model. Conflating the two builds a distributed monolith.

2. The bounded context limits the agent’s work

A “bounded context,” in Evans’s sense, is a zone of the system where every term has one stable meaning. A context, for short.

Its boundary answers three questions an agent asks before writing a line:

  • what to load? the files of the relevant context, not the whole repo;
  • what can it break? the “blast radius” of a change;
  • what’s authoritative? the “acceptance gate,” the test suite that decides whether the behavior is right.

A repo with no explicit boundaries answers “everything,” “everything,” and “nothing.” Stack as many specifications on top as you want: those three answers won’t move.

3. Invariants must be written down, in black and white

An agent produces code. It doesn’t enforce the model’s invariants: it manipulates an aggregate directly, it bypasses the rule that protects its consistency.

It has no memory of business constraints, only what it’s given to read.

Work on “Constitutional SDD” draws the consequence: non-negotiable constraints live in a versioned, machine-readable “Constitution,” honored “by construction rather than inspection.”

Our invariant sits on the Reservation aggregate: the sum of active reservations for a SKU and a channel never exceeds the sellable quantity.

Written once, in the right place, it survives every feature. Every specification that follows inherits it.

The map

What follows is an example, not a reference architecture. At another retailer, the boundaries and the teams would fall differently, and the invariant wouldn’t read quite the same.

It’s the approach that transfers, not the map.

Context map of an omnichannel retail system, grouped by owning team: Sales and Availability connected by an Open-Host Service, Availability protected by an anticorruption layer against the legacy ERP, Billing as a conformist against payment, and a partnership between Availability and Fulfillment within the Supply team

Three takeaways.

A feature is not a boundary. In-store pickup crosses four contexts. A specification written at that level describes a path, not a territory.

Zones are teams, and that’s what justifies the patterns. In Khononov’s framing, the integration pattern follows from the balance of power between teams, not from technology.

ERP and payment sit outside the organization. In both cases the downstream side takes what it’s given. And yet the response isn’t the same. Availability protects itself behind an “anticorruption layer,” because it carries the core. Billing settles for a “conformist,” because it has nothing to protect.

Availability and Fulfillment belong to the same team. That’s what makes their “partnership” workable.

A “core” is a subdomain, not a bounded context. What sets a retailer apart isn’t taking an order. It’s the sellable-quantity calculation, which lives inside Availability.

Hence the absence of color-coding by subdomain type on the boxes. The “core / supporting / generic” classification applies to subdomains, not to contexts.

The ERP makes the point well: a single context that spans accounting, purchasing, and stock.

Two levels of specification, and the code they govern

Three levels: strategic (DDD, stable) showing Sales and Availability connected by an Open-Host Service with the invariant on active reservations, contractual (SDD, revisable) with a given/when/then acceptance criterion and the event contract, implementation (agent, disposable) with write scope limited to the Availability context and the acceptance gate fixed at the contractual level

The first two levels are specifications. The third is the code they govern.

What separates them isn’t the level of detail, it’s lifespan.

Strategic, measured in years. The sellable quantity is defined only inside Availability, where the Reservation aggregate carries the invariant.

And crucially: Sales never reads the stock. It requests a reservation, and gets an answer back. Bypassing it becomes impossible, not just discouraged.

All of this was decided with business people, in a room. It doesn’t get regenerated.

Contractual, measured in iterations. Given a SKU and a channel, when the requested quantity exceeds the sellable quantity, then the reservation is rejected with reason code INSUFFICIENT_SELLABLE, with no partial write.

The vocabulary comes from the level above, word for word. This level invents nothing.

Implementation, disposable. The agent works inside contexts/availability, with no write access to the Sales schema. Its “acceptance gate” is set elsewhere, and it can’t rewrite it.

Microsoft pushes the same logic on the tooling side: confine the agent to the files tied to a “spec ID,” fail the build the moment code drifts from the contract.

The if (stock.quantite >= quantiteDemandee) from the start is no longer just a bad idea. It’s no longer writable: the table it queries is out of scope, and the word it uses doesn’t exist in that context.

The classic mistake is treating all three levels at the same cadence.

Regenerating the first one on every ticket means starting from zero each time. Freezing the third one means giving up the one gain AI actually offers. Merging the first two into a single upfront document means redoing waterfall with modern tools.

An article on “Protocol-Driven Development” sums up the idea: “code is transient, while the protocol carries durable authority.”

Four traps

The dead glossary. A ubiquitous language written once and then forgotten is worse than nothing: it gives the agent false confidence in terms that have drifted.

If it isn’t versioned alongside the code, it won’t survive six months.

The data dictionary mistaken for a ubiquitous language. A reference dictionary enforces one meaning per term across the whole information system. A ubiquitous language allows three for “stock,” as long as the boundaries are explicit.

Many teams believe they’ve done the work because they have a dictionary. They’ve erased the one piece of information that mattered.

The context traced over the org chart. Retail organizations are often split by channel: web, store, drive-through. Splitting contexts the same way produces three stock models that contradict each other, and three agents that drive them apart three times faster.

The Azure Architecture Center gives a simple test: if a team owns several unrelated contexts, or if a context requires coordination across several teams, it’s the boundary or the organization that needs revisiting.

Believing the agent will do the work for you. A 2026 study ran a full DDD analysis through a chain of prompts: language, simulated EventStorming, contexts, aggregates, architecture.

The first three steps produce usable artifacts. The last two accumulate errors until the artifacts become unworkable.

The agent is good at naming, and weak where invariants live. The authors describe it as a “collaborative sparring partner” for the architect, not an automation.

Compression and transmission

DDD compresses the domain: a boundary, a language, a handful of invariants.

SDD transmits it: an executable, verifiable, disposable contract.

Without compression, transmission saturates. Specifications grow longer and longer, in an increasingly blurry vocabulary.

Without transmission, compression stays on the whiteboard. The domain is well modeled, but nobody handed it to the machine.

This isn’t a new method. It’s an old discipline, finally addressed to a machine that takes everything literally.


References

Foundations

  • Eric Evans, Domain-Driven Design, 2003: the source of “bounded context,” “ubiquitous language,” “anticorruption layer,” and the subdomain classification, which the Microsoft pages below apply.
  • Vlad Khononov, Learning Domain-Driven Design, 2021: chapter 3 for the subdomain / bounded context relationship, chapter 4 for integration patterns and the role of teams.

Microsoft

Research

  • The Productivity-Reliability Paradox: Specification-Driven Governance for AI-Augmented Software Development, arXiv, 2026: generated code violates DDD invariants, for lack of persistent understanding of domain constraints. https://arxiv.org/abs/2605.01160
  • Srinivas Rao Marri, Constitutional Spec-Driven Development: Enforcing Security by Construction in AI-Assisted Code Generation, arXiv, January 2026: a versioned, machine-readable “Constitution,” honored “by construction rather than inspection.” https://arxiv.org/abs/2602.02584
  • Jun He and Deying Yu, Protocol-Driven Development: Governing Generated Software Through Invariants and Continuous Evidence, arXiv, May 2026: “code is transient, while the protocol carries durable authority.” https://arxiv.org/abs/2605.12981
  • Tobias Eisenreich, Husein Jusic, and Stefan Wagner, Automating Domain-Driven Design: Experience with a Prompting Framework, arXiv, March 2026: DDD analysis via five prompts, validated at FTAPI. https://arxiv.org/abs/2603.26244
  • Deepak Babu Piskala, Spec-Driven Development: From Code to Contract in the Age of AI Coding Assistants, arXiv, 2026: three levels of rigor, “spec-first,” “spec-anchored,” and “spec-as-source.” https://arxiv.org/abs/2602.00180