ADR-0005 — Two-layer architecture
The decision that determines what “agent platform” even means.
What this decision settles
Section titled “What this decision settles”The platform serves multiple verticals — e-commerce is first, but B2B SaaS, healthcare, fintech, internal tooling could all be next. The question this ADR answers is: what’s business-agnostic and what’s vertical-specific, and how do they relate?
The answer is two layers:
- Platform Core — business-agnostic. The runtime, the
six-layer context model, the agent definition format, the
memory subsystem, the tool registry, the event bus.
Published as
@agent-platform/core,@agent-platform/runtime,@agent-platform/memory, and friends. - Business Packs — vertical-specific. Agents, their tools,
integrations with third-party services. Today there’s one:
@agent-platform/shopifyplus the YAML agents inapps/worker/agents/. Tomorrow there’s@agent-platform/hubspot,@agent-platform/stripe, etc.
The dependency arrow only ever points from Business Packs into Platform Core. Platform Core has zero knowledge of any vertical.
Why this matters
Section titled “Why this matters”Without this discipline, the easy path is to add e-commerce
concepts directly to the runtime. You’d find OrderId in the
core types, ShopifyClient in the runtime, refund-specific
handling in the agent dispatcher. Every future vertical would
either fight against that vocabulary or re-implement the same
runtime from scratch.
The two-layer model means:
- Adding a new vertical is purely additive. A new package
under
packages/(or a new repo if it’s external), zero edits to core. The marketing pitch — “the platform is business-agnostic” — is provable architecturally. - Code review has a hard rule. Anything e-commerce-shaped
in
packages/core/,packages/runtime/,packages/memory/, orpackages/agent-loader/is a smell. Reviewers can call it out without ambiguity. - The first vertical costs slightly more. When you only have one customer, the temptation is to put their concepts in core “just for now.” This ADR is the reason we don’t.
The decision
Section titled “The decision”Two layers:
- Platform Core — business-agnostic. Defines the runtime, orchestrator, memory system, tool registry, event bus, context assembler, and the types that everything else uses.
- Business Packs — vertical-specific. Defines agents, their tool sets, integrations with third-party services, and domain events. Each pack is a separate package.
The dependency arrow only ever points from Business Packs into Platform Core. Platform Core has zero knowledge of any vertical.
What got considered and rejected
Section titled “What got considered and rejected”- Monolithic (single package). Faster now, much slower later. Painful to extract at the second vertical. The “we’ll refactor later” tax is what kills these projects.
- Three layers (core + common-business + vertical-specific). Premature. We have one vertical and no observed need for shared-business-logic. Worth revisiting at the second or third vertical, not the first.
- Plugin system without formal package split. Harder to enforce the dependency direction. Harder to version pieces independently.
- Keep vertical-agnostic logic separate but deploy as one thing. Mixes concerns. Keeping packages distinct even when deployed together preserves the discipline; the deploy decision is separate from the architectural decision.
What this looks like in the repo today
Section titled “What this looks like in the repo today”| Platform Core (business-agnostic) | Business Pack (vertical) |
|---|---|
packages/core (types) | packages/shopify (Shopify client) |
packages/runtime | apps/worker/agents/triage.yaml |
packages/memory | apps/worker/agents/refund-decision.yaml |
packages/event-bus | apps/worker/agents/communication.yaml |
packages/agent-loader | apps/worker/agents/merchandising.yaml |
packages/builtin-tools (recall, store, emit) |
The runtime doesn’t know what a “refund” is. The Shopify package
doesn’t define agent semantics. The YAMLs reference both, but
sit in apps/worker/ because they’re application configuration,
not framework code.
Where to next
Section titled “Where to next”For the original ADR with full Context / Decision / Consequences / Alternatives sections (substantially the same as the narrative above; we lifted it from there), see ADR-0005 source.
Related foundational decisions: