Amplifier Foundation Examples

June 26, 2026 ยท View on GitHub

Progressive examples demonstrating how to use Amplifier Foundation, organized by learning progression.

Quick Start

# Set your API key
export ANTHROPIC_API_KEY='your-key-here'

# Run the first example
cd amplifier-foundation
uv run python examples/01_hello_world.py

Examples Overview

โœจ Tier 1: Quick Start (01-03)

Goal: Get running in 15 minutes

01_hello_world.py - Your first AI agent
The simplest possible Amplifier agent. Load foundation, compose with provider, execute a prompt. See the basic flow that all applications follow.

02_custom_configuration.py - Tailor agents via composition
See how to add tools, use streaming orchestrators, and customize behavior by composing different modules. Composition over configuration - swap capabilities, not flags.

03_custom_tool.py - Build domain-specific capabilities
Build custom tools (WeatherTool, DatabaseTool) that integrate seamlessly. Learn the Tool protocol: name, description, input_schema, execute().

๐Ÿ”ง Tier 2: Foundation Concepts (04-07)

Goal: Understand how Amplifier works internally

04_load_and_inspect.py - Load and inspect bundles
Learn how load_bundle() works and what a bundle contains. See the mount plan structure.

05_composition.py - Bundle composition and merge rules
Understand how compose() merges configuration. See how session, providers, tools, and instruction fields combine.

06_sources_and_registry.py - Loading from remote sources
Learn source formats (git, file, package). Use BundleRegistry for named bundle management.

07_full_workflow.py - Complete workflow with execution
See the full flow: prepare() โ†’ create_session() โ†’ execute(). Interactive demo with provider selection and LLM execution.

๐Ÿ—๏ธ Tier 3: Building Applications (08-09)

Goal: Production patterns and complex systems

08_cli_application.py - CLI application architecture See application architecture patterns: configuration management, logging, error handling, lifecycle management. Build reusable application classes.

09_multi_agent_system.py - Coordinate specialized agents Create specialized agents (Architect, Implementer, Reviewer) with different tools and instructions. See sequential workflows and context passing between agents.

23_spawn_with_agents.py - Spawn sub-sessions with named agents Wire the session.spawn capability for agent delegation using the two sanctioned agent-config shapes: inline overlays (partial mount-plan dicts) and agent .md files (resolved via load_bundle()). Shows that a generic observability hook composed into the parent bundle is inherited by every spawned child via compose=True โ€” no per-child wiring required.

๐ŸŒ Tier 4: Real-World Applications (10-21)

Goal: Practical use cases and advanced patterns

10_meeting_notes_to_actions.py - Text processing workflow Transform meeting notes into structured action items. Shows practical document processing.

11_provider_comparison.py - Compare LLM providers Run the same prompt across multiple providers. Useful for evaluation and selection.

12_approval_gates.py - Human-in-the-loop patterns Add approval gates for sensitive operations. See hooks for control flow.

13_event_debugging.py - Session observability Debug and monitor session events. Learn the event system for observability.

14_session_persistence.py - Save and restore sessions Persist session state across runs. Enable conversation continuity.

17_multi_model_ensemble.py - Ensemble patterns Combine multiple models for improved results. Advanced orchestration patterns.

18_custom_hooks.py - Build custom hooks Create hooks for logging, redaction, and control. Extend session behavior.

19_github_actions_ci.py - CI/CD integration Run Amplifier in GitHub Actions. Automation and testing patterns.

20_calendar_assistant.py - External API integration Build a calendar assistant with external API calls. Real-world integration patterns.

21_bundle_updates.py - Bundle update detection Check for and apply updates to bundle sources. Two-phase pattern: check status (no side effects) โ†’ refresh (side effects). Foundation provides mechanism, app provides policy.

Learning Paths

For Beginners

Start here to understand Amplifier basics:

  1. 01_hello_world.py - See it work immediately
  2. 02_custom_configuration.py - Understand composition
  3. 03_custom_tool.py - Build your first custom capability

For Building Real Tools

Learn patterns for production-quality applications:

  1. Tier 1: 01-03 (get started)
  2. Tier 2: 04-07 (understand core concepts)
  3. Tier 3: 08-09 (see production patterns)

For Understanding Internals

Deep dive into how Amplifier works:

  1. 04_load_and_inspect.py - Bundle structure
  2. 05_composition.py - Merge rules and composition
  3. 06_sources_and_registry.py - Module resolution and sources
  4. 07_full_workflow.py - Complete preparation and execution flow

Key Concepts Demonstrated

Bundles

Composable configuration units that produce mount plans for AmplifierSession. A bundle specifies which modules to load, how to configure them, and what instructions to provide.

bundle = Bundle(
    name="my-agent",
    providers=[...],  # LLM backends
    tools=[...],      # Capabilities
    hooks=[...],      # Observability
    instruction="..." # System prompt
)

Composition

Combine bundles to create customized agents. Later bundles override earlier ones, allowing progressive refinement.

foundation = await load_bundle("foundation")
custom = Bundle(name="custom", tools=[...])
composed = foundation.compose(custom)  # custom overrides foundation

Preparation

Download and activate all modules before execution. The prepare() method resolves module sources (git URLs, local paths) and makes them importable.

prepared = await composed.prepare()  # Downloads modules if needed
session = await prepared.create_session()

Module Sources

Specify where to download modules from. Every module needs a source field for prepare() to resolve it.

tools=[
    {
        "module": "tool-filesystem",
        "source": "git+https://github.com/microsoft/amplifier-module-tool-filesystem@main"
    }
]

Tool Protocol

Custom tools implement a simple protocol - no inheritance required:

class MyTool:
    @property
    def name(self) -> str:
        return "my-tool"
    
    @property
    def description(self) -> str:
        return "What this tool does..."
    
    @property
    def input_schema(self) -> dict:
        return {
            "type": "object",
            "properties": {
                "param": {"type": "string"}
            },
            "required": ["param"]
        }
    
    async def execute(self, input: dict) -> ToolResult:
        return ToolResult(success=True, output="result")

Common Patterns

Pattern: Hello World

The minimal Amplifier application:

foundation = await load_bundle(foundation_path)
provider = await load_bundle(provider_path)
composed = foundation.compose(provider)
prepared = await composed.prepare()
session = await prepared.create_session()

async with session:
    response = await session.execute("Your prompt")

Pattern: Adding Tools

Compose tools into your agent:

tools = Bundle(
    name="tools",
    tools=[
        {"module": "tool-filesystem", "source": "git+https://..."},
        {"module": "tool-bash", "source": "git+https://..."},
    ]
)
composed = foundation.compose(provider).compose(tools)

Pattern: Custom Tool

Register custom tools after session creation:

# After session is created
await session.coordinator.mount("tools", MyTool(), name="my-tool")

# Then use in session
async with session:
    response = await session.execute("Use my custom tool")

Pattern: Multi-Agent

Sequential agent workflow:

# Agent 1: Design
architect = foundation.compose(provider).compose(architect_config)
prepared1 = await architect.prepare()
session1 = await prepared1.create_session()
async with session1:
    design = await session1.execute("Design the system")

# Agent 2: Implement (uses Agent 1 output)
implementer = foundation.compose(provider).compose(implementer_config)
prepared2 = await implementer.prepare()
session2 = await prepared2.create_session()
async with session2:
    code = await session2.execute(f"Implement: {design}")

Troubleshooting

"Module not found" Error

Modules need source fields so prepare() can download them:

{"module": "tool-bash", "source": "git+https://..."}

First Run Takes 30+ Seconds

This is normal - modules are downloaded from GitHub and cached in ~/.amplifier/cache/. Subsequent runs are fast.

"API key error"

Set your provider's API key:

export ANTHROPIC_API_KEY='your-key-here'
# or
export OPENAI_API_KEY='your-key-here'

Path Issues

Examples assume you're running from the amplifier-foundation directory:

cd amplifier-foundation
uv run python examples/XX_example.py

If path errors occur, check that Path(__file__).parent.parent resolves to the amplifier-foundation directory.

Architecture Principles

Composition Over Configuration

Amplifier favors swapping modules over toggling flags. Want streaming? Use orchestrator: loop-streaming. Want different tools? Compose a different tool bundle. No complex configuration matrices.

Protocol-Based

Tools, providers, hooks, and orchestrators implement protocols (duck typing), not base classes. No framework inheritance required - just implement the interface.

Explicit Sources

Module sources are explicit in configuration. No implicit discovery or magic imports. If you need a module, specify where it comes from: git repository, local path, or package name.

Preparation Phase

Modules are resolved and downloaded before execution (prepare()), not during runtime. This ensures deterministic behavior and clear error messages.

Next Steps

  • Read the docs: amplifier-foundation documentation
  • Explore modules: Check out pre-built modules on GitHub
  • Build your own: Use 03_custom_tool.py as a template for custom capabilities
  • Study patterns: 08_cli_application.py shows application architecture best practices

Getting Help