Skip to content

ADR-0005 — Two-layer architecture

The decision that determines what “agent platform” even means.

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:

  1. 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.
  2. Business Packs — vertical-specific. Agents, their tools, integrations with third-party services. Today there’s one: @agent-platform/shopify plus the YAML agents in apps/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.

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/, or packages/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.

Two layers:

  1. Platform Core — business-agnostic. Defines the runtime, orchestrator, memory system, tool registry, event bus, context assembler, and the types that everything else uses.
  2. 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.

  • 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.
Platform Core (business-agnostic)Business Pack (vertical)
packages/core (types)packages/shopify (Shopify client)
packages/runtimeapps/worker/agents/triage.yaml
packages/memoryapps/worker/agents/refund-decision.yaml
packages/event-busapps/worker/agents/communication.yaml
packages/agent-loaderapps/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.

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:

  • ADR-0006 — six-layer context system
  • ADR-0009 — types-only Platform Core package (the “how” of keeping core lean)