The race to build AI agents is on. Enterprises are standing up autonomous systems faster than they can think through what those systems should actually do. The result is a familiar pattern: overlapping responsibilities, unclear ownership, agents that hallucinate at the seams where systems hand off, and architectures that collapse under the weight of their own complexity.
We've been here before — not with AI, but with microservices.
A decade ago, teams discovered that decomposing a monolith into services wasn't a technical problem. It was a design problem. You couldn't just split a codebase arbitrarily and call it distributed architecture. You needed principled boundaries. You needed Domain-Driven Design.
I believe the same is true today for AI agents. And I've found that the most powerful framework we have for deciding what agents to build and where their responsibilities begin and end is one we already know: DDD.
Ask most engineering teams building agentic systems how they decided on their agent architecture and you'll get some version of: "We knew we needed a research agent, so we built one. Then we needed something to take actions, so we added another. Then things got complicated."
This is bottom-up, feature-driven agent design. It works until it doesn't — which is usually the moment you need to scale, debug, or hand it to someone else.
The missing ingredient is a top-down, domain-informed view of where intelligence should live and why.
Domain-Driven Design, introduced by Eric Evans in 2003, was designed to manage complexity in large software systems by aligning software structure with business reality. Its central concepts — Bounded Contexts, Ubiquitous Language, Domain Events, and Context Maps — were built to answer one question: how do you carve up a complex system into parts with clear ownership and minimal coupling?
That is exactly the question we face with AI agents. The translation is more natural than you might expect.
The most important concept in DDD is the Bounded Context: a boundary within which a particular model is internally consistent and meaningful. Inside the boundary, terms have precise definitions. Outside it, the same word might mean something different.
In agent design, a Bounded Context maps almost directly to an agent boundary.
Consider an e-commerce platform. Order Management, Inventory, Payments, Shipping, and Customer are natural Bounded Contexts — each with its own data, rules, and language. Each becomes a natural agent. The Order Management Agent doesn't need to understand how Payments works internally; it only needs to know what signals to send and receive.
This gives you something invaluable: agents that can fail and recover in isolation. When your Payments Agent hits an edge case, it doesn't take down your entire system. The boundary contains the blast radius.
DDD distinguishes between three types of subdomains, and this distinction is one of the most practically useful ideas for AI systems:
Core Domains are your competitive differentiators — the things that make your business unique. This is where you invest the most engineering effort in DDD, and it's where AI adds the most transformative value. A logistics company's route optimization, a fintech's credit decisioning model, a healthcare company's clinical summarization engine — these are Core Domain agents worth investing heavily in.
Supporting Domains are necessary but not differentiating. They support the core but aren't where the magic happens. A simpler, well-constrained agent (or even a rules-based system) is often sufficient here.
Generic Domains are commodity — things like email, calendar, document generation. Wrap these in thin agent shells or call APIs directly. Don't build elaborate reasoning systems for things that don't create competitive advantage.
This taxonomy prevents one of the most expensive mistakes in AI development: building sophisticated agents for things that don't matter, and under-investing in the ones that do.
In DDD, Bounded Contexts communicate through Domain Events — immutable records of things that happened, expressed in past tense: OrderPlaced, PaymentFailed, InventoryDepleted.
This is the right model for inter-agent communication for three reasons.
First, it preserves loose coupling. Agents don't call each other directly. They emit events and react to events. The Order Management Agent doesn't know or care how the Payments Agent processes a payment — it only knows that PaymentConfirmed arrived, and it can proceed.
Second, it creates an audit trail. Every event is a record. When something goes wrong in a multi-agent system — and something always will — you can trace the exact sequence of events that led to the failure. This makes debugging agentic systems dramatically less painful.
Third, it enables asynchronous operation. Not every agent needs to respond in real time. Some can batch events and process them on their own schedule. The event-based model accommodates this naturally.
Every DDD Bounded Context has a Ubiquitous Language: a precise, shared vocabulary used consistently by domain experts, engineers, and the codebase itself. The same word means the same thing everywhere within the boundary — and possibly something different outside it.
For AI agents, this maps directly to system prompt design and schema definition.
An Inventory Agent should think and speak in terms of SKUs, reorder points, safety stock, and lead times — not generic terms like "product" or "quantity." This precision isn't just good engineering practice; it materially reduces ambiguity in the agent's reasoning and lowers the likelihood of hallucinations at the conceptual seams.
When you define your agent's input and output schemas, you are publishing its Ubiquitous Language. Do this deliberately.
DDD's Context Map documents how Bounded Contexts relate to each other. The patterns it defines translate directly into orchestration design:
The Customer-Supplier pattern, where one context produces for another, maps to a linear pipeline: a Research Agent produces a structured brief that a Writing Agent consumes.
The Anti-Corruption Layer pattern, where a translator sits between two contexts with incompatible models, maps to an adapter agent that normalizes outputs from a legacy system before passing them to a modern agent.
The Published Language pattern, where contexts agree on a shared event format, maps to a common schema that all agents in your ecosystem adhere to — the foundation of a composable agent platform.
Drawing your Context Map before writing a single line of agent code is one of the highest-leverage activities you can undertake.
The most common question I get when walking teams through this framework is: how fine-grained should agents be?
Here is a practical rule of thumb: Bounded Context = one agent by default. Then ask:
A tool is deterministic and stateless. An agent reasons, decides, and can fail in interesting ways. The distinction matters because agents are expensive to run, hard to debug, and introduce non-determinism. Don't create agents where tools will do.
Let me ground this with a concrete example: a recruiting platform.
The Core Domain is candidate matching — algorithmically and semantically connecting the right candidates to the right roles. This is the competitive differentiator. It gets a sophisticated, heavily-tuned agent with deep context about the company's hiring philosophy, role requirements, and candidate signals.
The Supporting Domains — resume parsing, interview scheduling, feedback aggregation — get leaner agents. Each has a defined input, a defined output, and a constrained set of tools.
The Generic Domains — sending emails, updating calendars — become tool wrappers. Not agents. Just functions.
The Context Map defines that CandidateShortlisted is the event that flows from the Matching Agent to the Scheduling Agent. The Scheduling Agent doesn't need to understand why a candidate was shortlisted — only that they were.
I want to be honest about where this framework has limits, because applying it too rigidly creates its own problems.
If you're a CTO or architect beginning this work, here is where to start:
Map your domain. Before a single prompt is written, draw your domain map. Identify your Bounded Contexts and classify your subdomains as Core, Supporting, or Generic.
Draw your Context Map. Define how contexts relate and what events flow between them. This is your orchestration architecture before it's code.
Define the Ubiquitous Language for each agent. Write the system prompt with the vocabulary of that domain. Define the input and output schemas precisely.
Build the simplest thing that could work. Start with one agent. Expand when a real limitation demands it — not because it feels more sophisticated.
That discipline — taking the domain seriously — is what DDD has always been about. It turns out it's what great agent architecture is about too.
Rohit Sinha is a CTO with experience building large-scale AI and distributed systems. He writes about the intersection of engineering architecture and emerging technology.