Skip to content

ADR-0006: Clean Architecture + Domain-Driven Design

Status: Accepted
Date: 2026-06-27
Deciders: Architecture Team
Supersedes:


The platform spans many domains (agents, workflows, memory, tools, plugins, billing) and must remain testable, swappable (datastores, providers), and maintainable as it grows. We need a consistent internal structure across services.


Adopt Clean Architecture principles with Domain-Driven Design (DDD), as described in Clean Architecture and Domain-Driven Design.

  • Dependencies point inward: domain core has no infrastructure dependencies; databases, providers, and transports are outer-layer adapters behind traits.
  • Ports & adapters: e.g. MemoryProvider, AIProvider, tool traits are ports; Qdrant/PostgreSQL/OpenAI are adapters.
  • Bounded contexts map to subsystems/crates (ADR-0001).

Positive

  • Infrastructure is swappable (e.g. vector store, provider) without touching domain logic — directly enabled the Provider SDK and pluggable memory backends.
  • Domain logic is unit-testable in isolation with fakes (unit testing).
  • Clear boundaries reduce coupling across a large codebase.

Negative

  • More upfront structure/boilerplate (traits, mapping at boundaries).
  • Risk of over-abstraction; requires judgment on where ports add value.

  • Layered/transaction-script — simpler initially but tends toward tight coupling to the database and hard-to-test logic at this scale. Rejected.
  • Pure hexagonal without DDD — similar benefits; DDD adds the domain/bounded- context vocabulary that fits a multi-domain platform. Adopted together.