Least Privilege by Default

Tools that activate only when an agent needs them

The Question

Every agent declares its own tools. Who turns them on — and when?

In Amplifier, each spawned agent names exactly the tools it needs. That declaration is stable. The open question is timing: does the parent session pre-activate everything up front, or does each tool come on only when it's actually used?

Start with what the agents themselves ask for.

Foundation ships 16 agents, and each one asks for a narrow tool set

The git-ops agent declares just two tools — tool-bash and tool-filesystem. The explorer agent declares a different narrow set. Agents genuinely want little.

So the appetite is small. The question is what it cost to satisfy it.

16
agent definition files under agents/
2
git-ops tools: tool-bash + tool-filesystem
3
explorer tools: tool-filesystem, tool-search, tool-lsp

One 81-line change flipped activation from eager to just-in-time

The feature arrived in a single commit adding lazy module activation to BundleModuleResolver — small, localized, and real.

Small change, big shift. First, why it was needed.

1
file changed — amplifier_foundation/bundle.py
+81
insertions (−8 deletions)
dfbe1ce
commit — feat(bundle): add lazy module activation to BundleModuleResolver

A tool missing from the parent's set simply failed

Before lazy activation, any tool an agent might use had to be pre-activated in the parent bundle. Ask for one that wasn't there, and the resolver raised CoreModuleNotFoundError.

So parents over-provisioned — cluttering the root, over-granting tools, paying activation cost for tools that might never run.

# resolve() on a module not in the pre-activated set raise CoreModuleNotFoundError( "Module ... not found in prepared bundle. Available modules: ..." )

Now the resolver holds an activator and turns tools on at first ask

Bundle.prepare() passes the ModuleActivator into BundleModuleResolver. A new async_resolve() lazily activates any declared module the first time a child session asks for it, using the source hint in the agent's tool config.

That one move changes where and when activation happens.

Activation moves from the parent's setup to the child's first use

The cost no longer sits in the parent's initial set. It shifts to exactly the agent that needs the tool, exactly when it needs it — guarded by a double-checked asyncio activation lock so concurrent spawns stay safe.

Which turns an abstract shift into a concrete, provable result.

Parent
stays clean
Child spawn
first use
Activate
lock-guarded

A parent with 7 tools spawns an agent that reaches 9

Per the feature commit's own test description, an agent session obtained python-check and python-execute without the parent ever pre-activating them.

The parent gave nothing up front. The agent got exactly what it declared.

7parent tools
9agent tools
The Takeaway

Least-privilege stops being a discipline you enforce, and becomes the default you get for free

The parent stays clean. Agents get exactly the tools they declared — activated only when a child session actually asks. Nobody has to over-provision to be safe.

Shipped / present on current working branch

Sources

Sources & Research Methodology

Feature status: Shipped / present on current working branch fix/session-naming-timeout-configurable (origin microsoft/amplifier-foundation).

Feature commit: dfbe1ce — authored 2026-01-14 16:41 PST, committed 2026-01-15 05:08 PST, by Brian Krabach <brkrabac@microsoft.com>.

Commands run:

Gaps: The 7→9 tool figure and the python-check/python-execute example are quoted verbatim from the feature commit's own message; the underlying test was not independently re-run. No standalone user-facing doc exists — the concept lives in docstrings and the commit message.

Note: bundle.py was later split into a bundle/ package on 2026-03-20; BundleModuleResolver and async_resolve now live in bundle/_prepared.py.

Primary contributor: Brian Krabach (author of commit dfbe1ce).

More Amplifier Stories