The Sidecar's Missing Metadata

An Amplifier Story

When freezing Python breaks a plugin loader

The whole game

How Amplifier is packaged isn't a detail — it's the whole game

Amplifier is a modular Python framework that finds its own plugins at runtime by reading packaging metadata off disk. So the way it's shipped determines whether it can find itself at all.

The claim sounds abstract — until you look at the code that does the finding.

The loader literally reads entry points off disk

In loader.py the framework calls importlib.metadata.entry_points(group="amplifier.modules") — and 9 installed modules register themselves through that exact group.

Discovery-by-metadata is a fact in the code. Now watch where that code runs.

109 & 319
loader.py lines calling entry_points(group="amplifier.modules")
9
installed modules shipping [amplifier.modules] entry_points.txt

In the Kepler desktop app, Amplifier runs as an HTTP sidecar

Kepler (michaeljabbour/amplifier-desktop) is a cross-platform desktop app. Its Tauri shell spawns Amplifier as a FastAPI/uvicorn process named amplifier-sidecar and talks to it over a WebSocket.

A separate Python process — which means how that process is packaged now matters directly.

The conflict

But the sidecar is frozen into a "single standalone executable"

Today that sidecar is packaged with PyInstaller (sidecar.spec, bundle-sidecar.cjs) into one frozen binary — the exact model that collapses the on-disk .dist-info the loader reads. It has been packaged this way since the very first commit.

So what happens to a loader that expects metadata on disk when the disk metadata is gone?

PyInstaller can't see dynamic modules — so the spec hand-lists them all

Because entry-point modules load dynamically, PyInstaller can't detect them. The spec is forced to hand-enumerate a hidden_imports list of every amplifier_* package, or they vanish from the frozen build.

Hand-maintained fragility. There's a cleaner path.

# sidecar.spec — "These are dynamically # loaded and PyInstaller can't detect them" hidden_imports = [ "amplifier_core", "amplifier_core.session", "amplifier_foundation", "amplifier_distro", # ... + many submodules ]
The cleaner path

Run a real Python venv as the sidecar — and the metadata just stays put

If the sidecar is a real Python environment instead of a frozen archive, the .dist-info simply stays on disk, intact, exactly where the loader expects to read it. No hand-maintained hidden_imports list required.

And it turns out that environment already exists.

A real python3.11 venv already sits on disk — with intact metadata for all 9 modules

Under oob/app/sidecar/.venv, a real python3.11 site-packages carries intact dist-info for all 9 modules — proof the fix works. Yet it's an untracked, git-ignored artifact: no commit landed it, no build script ships it.

The resolution is proven in principle — and still aspirational in this repo.

9
modules with intact dist-info in the on-disk venv
0
files of that venv tracked by git (.gitignore lists .venv/)
The lesson

When a framework discovers itself through metadata, how you ship it IS the architecture

Keep the packaging metadata real and the loader finds its plugins for free. Collapse it into a frozen binary and you hand-maintain fragility forever — one hidden import at a time.

Package the metadata, not around it.

Sources

Research Methodology

Feature status: Aspirational / Not Shipped — the venv-instead-of-freeze resolution is demonstrated on disk but not committed or built by any script in the primary repo.

Primary sources: repos under /home/ramparte/dev/ANext (amplifier-core, amplifier-foundation, amplifier-distro-kepler, oob, amplifier-module-*). Every claim re-derived from command output; nothing trusted from input.

Research performed:

Gaps / caveats: The desktop shell is Tauri, not Electron. "python-build-standalone" appears only inside PyInstaller's vendored source, not in any Amplifier build script. No build-time metadata-verification step was found, and no repo evidence of an observed crash exists — the failure is stated as mechanism/risk, not an incident.

Primary contributors: Michael J. Jabbour (38 commits), Marc Goodner (15), Sam Schillace (13) on amplifier-distro-kepler.

More Amplifier Stories