Technical Architecture Deep-Dive

Composition All
the Way Down

How markdown files become AI agent systems —
the architecture of amplifier-foundation

Active — amplifier-foundation

February 2026

The Foundation Layer

8,645 lines of composition intelligence

amplifier-foundation is the library that turns 11-line YAML bundles into running AI agents. Without it, every application would need hundreds of lines of wiring code.

📦

Bundle Loading

load_bundle() — parses YAML front-matter + markdown body into the Bundle dataclass

🔗

Composition Engine

Bundle.compose() — merges bundles with 5 distinct strategies per field type

📎

@mention Resolution

Namespace-aware file references with recursive loading, SHA-256 dedup, max depth 3

⬇️

Module Activation

ModuleActivator — downloads modules from source URIs to local cache, installs deps

🌱

Spawn Utilities

Create child sessions with context inheritance, provider preferences, and session resume

🏭

PreparedBundle Factory

The expensive one-time step: activate all modules, build resolver, then create sessions cheaply

LIBRARY CORE
8,645 LOC
TOTAL WITH MODULES
22,996 LOC
PYTHON FILES
97
Data Structure

The Bundle dataclass — 14 fields in 4 groups

@dataclass class Bundle: # ── Identity ────────────────────────────── name: str # REQUIRED — also defines namespace version: str = "1.0.0" description: str = "" includes: list[str] = [] # URIs of bundles to compose # ── Mount Plan ──────────────────────────── session: dict[str, Any] = {} # orchestrator + context module specs providers: list[dict] = [] # LLM provider configurations tools: list[dict] = [] # tool module configurations hooks: list[dict] = [] # lifecycle hook configurations spawn: dict[str, Any] = {} # child session defaults # ── Resources ───────────────────────────── agents: dict[str, dict] = {} # agent name → definition context: dict[str, Path] = {} # context file references instruction: str | None = None # system prompt (from markdown body) # ── Internal ────────────────────────────── base_path: Path | None = None # filesystem root for this bundle source_base_paths: dict[str, Path] = {} # namespace → base_path (for @mentions)

Plus _pending_context for deferred namespace resolution. The source_base_paths dict is the key to multi-bundle @mention resolution — it maps every composed namespace to its filesystem root.

Composition Semantics

Bundle.compose(*others) — 5 merge strategies

Returns a new Bundle. The original is never mutated. Later bundles win for conflicts.

Field Strategy Effect
session deep_merge() Nested dicts merged recursively; scalars: later wins
spawn deep_merge() Same recursive merge as session
providers merge_module_lists() Index by module key; deep merge per module ID
tools merge_module_lists() Same — matching modules merge, new modules append
hooks merge_module_lists() Same — preserves module identity across compositions
agents dict.update() Later overrides entirely by agent name
context accumulate Namespaced with bundle_name: prefix — no collision
instruction replace Later replaces earlier entirely
source_base_paths accumulate First write wins per namespace; never overwrites

Lists are NOT merged by deep_merge — child replaces parent. Module lists use a special merge_module_lists() that indexes by the 'module' key for identity-preserving merges.

The Prepare Step

Bundle.prepare() — the expensive step, done once

Generate mount plan via bundle.to_mount_plan() — raw config dict
Create ModuleActivator with install_deps flag and base_path
Install bundle's own package via uv pip install (pyproject.toml) — critical: before modules
Install included bundles' packages from all source_base_paths
Collect ALL module specs across providers, tools, hooks, orchestrator, context, and agents
activator.activate_all() — download each module from source URI to local cache
activator.finalize() — persist install state for fast subsequent startups
Return PreparedBundle with resolver + mount plan + bundle_package_paths
# PreparedBundle — the output @dataclass class PreparedBundle: mount_plan: dict[str, Any] resolver: BundleModuleResolver bundle: Bundle bundle_package_paths: list[str] # BundleModuleResolver # Implements kernel's ModuleSourceResolver # - sync resolve: pre-activated paths # - async resolve: lazy activation # with asyncio.Lock() for safety

Key insight

prepare() is expensive (network I/O, package installs). But it's done once. After that, create_session() and spawn() are cheap — they reuse the resolver.

From Prepared to Session

PreparedBundle.create_session()

From 11 lines of YAML to a running agent loop. This is the wiring that foundation does so you don't have to.

AmplifierSession(mount_plan) — instantiate the kernel session with the prepared config
Mount BundleModuleResolver at module-source-resolver capability slot
Register bundle_package_paths capability for child session inheritance
Register session.working_dir — the filesystem root for @mention resolution
session.initialize() — kernel loads all modules from mount plan
Resolve pending context refs — deferred namespaced @mentions now have source_base_paths
Register mention_resolver + deduplicator as session capabilities
Create system prompt factory — re-reads all @mentioned files every turn (dynamic!)
Register factory with context manager — or fallback to pre-resolved static prompt

Dynamic system prompts

The system prompt factory is re-called on every get_messages_for_request(). Files are re-read fresh each turn. Edit AGENTS.md mid-session and changes are picked up immediately.

Context Sink Architecture

40+ agents, zero context poisoning

Heavy documentation loads only when the expert spawns. The root session never sees it. Context flows through a two-parameter model: depth × scope.

Root
"bundle system exists, delegate to foundation-expert"
~30 lines
spawn()
Expert
@foundation:docs/BUNDLE_GUIDE.md, PATTERNS.md ...
15,000+ tok
return
Result
Distilled answer — structured summary
~500 tok

Depth — how much history

none — clean slate
recent — last N turns (default 5)
all — full conversation

Scope — which content

conversation — text only
agents — + delegate results
full — + all tool results

3 depth options × 3 scope options = 9 context inheritance strategies. Messages >2,000 chars are truncated. Tool use/result blocks are stripped in non-full scopes.

Namespace Resolution

How @mentions resolve — a 3-layer pipeline

# 1. Parser (regex extraction) parse_mentions(text) → list[str] # Extracts @mentions, skips code blocks # Preserves order, returns unique list # 2. Resolver (namespace + path) class BaseMentionResolver: # @bundle-name:path → bundles[ns].resolve() # @path → base_path / path # @~/path → expanduser() # 3. Loader (recursive + dedup) load_mentions(text, resolver, dedup, relative_to, max_depth=3) # SHA-256 content deduplication # Directories → listing # Recursive @mentions in loaded files

Namespace rules

Namespace comes from bundle.name, always. Not the repo name, not the directory. Root bundles establish namespaces; composed bundles share the parent's.

YAML vs Markdown syntax

YAML sections: no @ prefix
my-bundle:context/guide.md
Markdown body: @ prefix required
@my-bundle:context/guide.md

Opposite semantics, intentionally

context.include propagates upward (parent sees it).
@mentions stay local (only the loading session sees the content).

Spawn — Agent Delegation

PreparedBundle.spawn()

async def spawn(self, child_bundle: Bundle, instruction: str, *, compose: bool = True, # compose child with parent? parent_session: Any = None, # lineage tracking + UX session_id: str = None, # resume existing session orchestrator_config: dict = None, # override orchestrator parent_messages: list = None, # inject parent context provider_preferences: list = None, # ordered fallback chain self_delegation_depth:int = 0, # recursion limiter ) → dict[str, Any]: # Returns: {output, session_id, status, turn_count, metadata}
Compose child with parent bundle (inherits parent's tools)
Generate child mount plan + merge orchestrator config
Apply provider preferences with glob pattern resolution
Create AmplifierSession with parent_id linking
Mount resolver, register working_dir, initialize
Inject parent_messages via context manager (new sessions only)
Register system prompt factory for child
Hook orchestrator:complete to capture metadata
session.execute(instruction) — the agent does its work
Return result dict — session_id enables resume
The Three-Layer Architecture

Why this works

Bundles — User Intent

11-line YAML files. What agents to include, what behaviors to compose. Thin, declarative, composed via includes:

Foundation — Composition Intelligence

8,645 LOC. Bundle loading, compose(), prepare(), spawn(), @mentions, activation. The library that makes 11-line bundles possible.

Kernel — Mechanisms Only

4,492 LOC. Session lifecycle, module loading, event dispatch, coordinator. Five protocols. Zero opinions about composition.

11
Lines for a behavior
8,645
LOC foundation core
4,492
LOC kernel
5
Kernel protocols

The foundation layer is the secret weapon. Like a programming language's standard library — not part of the spec, but essential to making the language usable.

Structural Isomorphism

The design system parallel

Both systems solve the same problem: composable, constrained, semantically meaningful primitives enabling diverse creators to build consistent, high-quality experiences.

Amplifier
Design System
Protocol types
Design tokens
Configured modules
Semantic tokens
Behaviors
Design patterns
Bundles
Components
.amplifier/settings.yaml
Themes
Running session
Rendered application

Atomic primitives → meaningful mappings → reusable compositions → complete units → environmental application → running output. The pattern is fractal.

Sources

Research Methodology

Data as of: February 26, 2026

Feature status: Active

Research performed:

Repositories: amplifier-foundation (local), amplifier-core (local submodule)

Gaps: Production session counts and performance benchmarks not available in source code. Community bundle count not surveyed.

Composition All the Way Down

Three layers. Two libraries.
Five protocols. Eleven lines of YAML.
Infinite possibility.

That's composition all the way down.

Bundles
Foundation
Kernel
More Amplifier Stories