The multi-agent system as a composite domain
We design multi-agent systems as compositions of domains, not as sums of agents. The distinction matters when several agents operate over the same company with crossed responsibilities: a digital SDR qualifying leads, a legal agent validating contracts, a document processor generating proposals. If each agent lives as an island with its own vocabulary and its own state, inconsistencies show up in production within weeks.
The body of theory that best solves this isn't new. It's Domain-Driven Design, proposed by Eric Evans over two decades ago. Applied to multi-agent systems, it offers the precise framework: each agent as a bounded context, aggregates as state owners, explicit translation when two agents communicate. This is the architecture we apply when a client goes from one agent to three or four.
Bounded contexts: each agent as a delimited context
A bounded context is an explicit boundary within which a domain model holds coherence. The word "customer" means exactly one thing inside that context, with a defined set of attributes, rules, and operations. Another bounded context may call something partially different "customer" — and it should.
Applied to AI agents: each agent lives inside its own bounded context. The digital SDR has a Lead model: fields for qualification, ICP fit, buying intent. The legal agent has a Customer model focused on legal personality, jurisdiction, and contractual terms. The document processor has a Customer model centered on tax data and delivery address.
The three entities may correspond to the same real-world person. But each agent reasons about the attributes relevant to its context, with its language and its rules. Forcing a single model across all three is the root of most multi-agent systems that get stuck.
Aggregates: who owns what state
An aggregate, in DDD, is the consistency boundary within which a change is transactional. An Order and its OrderLine form an aggregate: lines don't exist without an order, invariants get verified together, changes get persisted as a unit.
In multi-agent systems, the aggregate defines which agent can modify which entity and under what rules. The digital SDR can modify the Lead in its context, but doesn't touch the Customer from the legal agent. The legal agent can create and modify contracts, but doesn't touch the lead's ICP.
When an agent needs a change outside its aggregate, it doesn't write directly — it issues a request to the owning agent, which validates with its rules. This turns inter-agent coordination into a series of controlled operations, not chaotic concurrency on the same data.
Without explicit aggregates, two agents can write contradictions over the same entity within seconds. With explicit aggregates, every change goes through its owner and gets recorded.
Ubiquitous language: consistent vocabulary inside the context
Ubiquitous language is the discipline that code, agent prompts, documentation, and team conversation use the same words for the same concepts — inside a bounded context.
Applied to AI agents, ubiquitous language affects the system prompt and tool descriptions directly. A legal agent whose prompt speaks of "obligations", "performances", and "consideration" reasons coherently. The same agent whose prompt mixes "contract", "agreement", "deal", and "offer" as if they were synonyms makes incoherent decisions.
Investment in ubiquitous language pays double in systems with generative AI. The model reasons with the words it receives; precise words produce precise reasoning; ambiguous words produce contextual hallucinations.
Anti-corruption layer: translation between agents
The most useful DDD piece in multi-agent systems is the anti-corruption layer (ACL). When two bounded contexts communicate, the ACL explicitly translates between their models so neither contaminates the other.
In multi-agent systems, the ACL is the layer that takes a handoff from the digital SDR — "this lead is qualified and ready for proposal" — and translates it to the receiving agent's model — "create a customer in preliminary state with these commercial and tax attributes". The translation is code, not another agent. It's deterministic, auditable, testable with stubs.
Without an ACL, agents end up importing vocabulary from each other — the digital SDR starts speaking of "contractual obligations" because its legal counterpart does, and within weeks the qualifier is reasoning about concepts that aren't its job. With an ACL, each agent keeps its semantics and the translation happens outside any of them.
Communication patterns between agents
Three patterns we apply depending on the coordination type:
Orchestration. A director agent explicitly coordinates the others: it invokes the SDR to qualify, the legal one to validate, the document one to generate the proposal. The director knows all; the others only know their context. Useful when the flow is linear and predictable.
Event-driven choreography. Each agent emits events when it completes a significant action (LeadQualified, ContractValidated, ProposalGenerated). Other agents subscribe to relevant events and react. There's no central director. Useful when the flow is complex, branched, or evolves over time.
Request-response over a port. Agent A invokes agent B as if it were another tool. The invocation goes through an ACL that translates parameters and result. Useful for punctual synchronous queries.
The choice depends on the business flow, not on trends. Orchestration is simpler to reason about but introduces a single coordination point. Choreography is more resilient but demands careful observability to diagnose incidents.
Anti-patterns DDD prevents
Three frequent errors in multi-agent systems this discipline cuts at the root:
The "agent that knows everything" — a single agent tries to cover qualification, contracts, documents, and support. The prompt grows to thousands of tokens; decisions blur across domains; adding a new use case forces touching the whole system. Splitting into bounded contexts restores focus to each agent and keeps cost manageable.
The "shared state without owner" — several agents write over the same entity in HubSpot without coordination. Integrity breaks within weeks. Explicit aggregates define who's in charge of what.
The "contaminated language" — the team uses the same terms for different things because "that's how we say it". The LLM model, fed with that ambiguity, decides with incoherent criteria. Investment in ubiquitous language within each context solves this problem before it manifests.
A real case: four agents at a professional services firm
A client of ours operates four AI agents over HubSpot and a proprietary ERP:
- Digital SDR — qualifies inbound leads against ICP.
- Legal assistant agent — validates that proposals meet contractual and jurisdictional requirements.
- Document processor — generates commercial proposals from templates and client data.
- Customer success agent — watches active-client health and detects early churn signals.
Each agent lives in its bounded context, with its entity model and its prompt operating in ubiquitous vocabulary. State gets owned by explicit aggregates: the SDR owns the Lead, legal owns the Contract, the document processor owns the Proposal, customer success owns the HealthState. Inter-agent communications go through ACLs implemented as Java code, not as additional agents.
Result at twelve months: zero incidents from divergent "customer" models, adding a fifth agent (collections management) took three weeks because it had its bounded context well delimited, and the average operating cost per agent dropped when the prompts stopped mixing domains.
How we build it in production
In serious multi-agent projects, the first deliverable is not code. It's a context map: which agents exist or will exist, which entities live in each context, which ACLs translate between them, which communication pattern each crossing uses. That map is the equivalent of a classic DDD context map, adapted to systems with AI.
On top of that map, each agent gets built with its pure domain, its system prompt with ubiquitous vocabulary, and its tools bounded to its aggregate. ACLs get implemented as Java, Python, or TypeScript code — not as intermediate agents. The architecture is executable from the first commit, auditable, testable.
Behind each of these systems is a team of engineers who believe designing multi-agent systems is a domain-architecture exercise before it's a prompt-engineering exercise. The model's elegance matters less than the clarity of the contexts it reasons over. Multi-agent systems that scale, not orchestrations that break at the fourth agent.
If your company already has an AI agent in production and you're evaluating adding more, we can audit the current system and hand you the context map before the second agent collides with the first.


