One Way To Spawn

Unifying session spawning behind spawn_bundle()

The setup

Amplifier spawned sessions in several places — each its own way

The CLI's session_spawner.py, the Foreman orchestrator, and background tasks each carried their own spawning logic. This is the story of collapsing that into one primitive.

First, proof that the single primitive is real.

spawn_bundle() is documented as THE primitive for all session spawning

A single async function — async def spawn_bundle at line 259 of a 696-line module — that all other spawning patterns are told to build on.

So what did it replace?

1
async function: spawn_bundle
696
lines in spawn.py

Before it, Foreman hand-rolled its own worker spawning

Foreman is Amplifier's worker orchestrator. It spawned workers with load_bundle() + PreparedBundle.create_session() and a bespoke _write_worker_session_state helper.

The primitive exists to delete exactly this.

# Foreman, before spawn_bundle() # Uses amplifier_foundation's load_bundle() # and PreparedBundle.create_session() from amplifier_foundation import load_bundle bundle = await load_bundle(...) async def _write_worker_session_state(...): ...

One disciplined path: 12 explicit numbered phases

spawn_bundle() unifies bundle resolution, config and context inheritance, and execution into 12 phases — with fine-grained inherit_providers, inherit_tools, inherit_hooks, and context controls.

And around that one call grew a whole platform.

Around it grew a cross-session, event-driven platform

Sessions can now react to each other and run reactively — a pub/sub router for events, a protocol for when a session activates, and declarative config for long-running work.

A coordinated proposal tried to ship all of this at once.

Four same-suffix PRs were proposed — but only one merged

A coordinated 4-repo effort shared the title suffix "Integrated Session Spawning & Event-Driven Orchestration." Only Foreman's PR #2 merged; the others didn't land wholesale.

So how did the code still reach users?

Commit ba97a86 deletes the hand-rolled spawner for one call

Foreman's refactor (Paul Payne, 2026-02-04) removes _write_worker_session_state and the raw load_bundle()+create_session() path, adds await spawn_bundle(...). PR #2 merged; the reusable primitives ship via the standalone amplifier-bundle-orchestration bundle.

The code survived even where the PRs didn't.

# refactor: use spawn_bundle() for worker spawning - async def _write_worker_session_state(...): - from amplifier_foundation import load_bundle - bundle = await load_bundle(...) + result = await spawn_bundle(...) # orchestrator.py: 396 lines changed (+331 / -259)
What to keep

One primitive plus an extractable bundle beats four coupled PRs

The reusable code — spawn.py, events.py, triggers.py, background.py — lives in microsoft/amplifier-bundle-orchestration, and Foreman runs on it today. Consolidate behind one primitive, then ship it as a reusable bundle.

Feature status: shipped on main (orchestration bundle); Foreman PR #2 merged
Sources

Research Methodology

Data as of: research verified against microsoft/amplifier-bundle-orchestration and payneio/amplifier-bundle-foreman clones.

Feature status: Orchestration primitives committed on main; Foreman adoption (PR #2) merged 2026-02-17. core #9 & foundation #63 CLOSED; cli #81 OPEN.

Commands run:

Gaps: "500+ tests" and "zero regressions" were NOT verified and are excluded. Feature-specific test functions total ~124 (orchestration 77 + foreman 47). The full spawn_bundle suite could not run locally (test_spawn.py needs amplifier_core); test_events.py + test_triggers.py passed 42/42.

Primary contributor: Paul Payne — author of spawn_bundle(), EventRouter, triggers, BackgroundSessionManager, the orchestration bundle, and the Foreman integration (8 of 11 orchestration commits; all 4 foreman feature commits).

More Amplifier Stories