Repository navigation
routing show: honour provider family aliases; warn when the hook isn't mounted in the active bundle - #321
Merged
Brian Krabach (bkrabach) merged 1 commit intoSep 7, 2026
Conversation
… isn't mounted
`amplifier routing show` misled two kinds of user. Both found on 2026-09-07,
both fixed in commands/routing.py.
1. THE ALIAS-BLIND USER
-----------------------
A ChatGPT-subscription-only user (`openai-chatgpt` module, no `openai`
module) is routed fine at runtime: the routing hook's PROVIDER_FAMILY_ALIASES
maps `provider: openai` onto that mount. But `_get_configured_provider_types`
fed a bare set-membership test that never consulted the alias table, so the
display told exactly that user "not configured" for every openai role.
Measured in a DTU.
Fix: `_get_configured_provider_types` now also adds every canonical family a
configured module SATISFIES, reading the table from
`amplifier_module_hooks_routing.resolver.PROVIDER_FAMILY_ALIASES` itself --
one home, so the display cannot disagree with the resolver. All four
downstream `in provider_types` sites become alias-aware with no change. The
import is guarded: on a clean install before the bundle is first fetched it
degrades to "no aliases" (the pre-alias behaviour), never an error. The alias
is directional, as in the resolver: a plain `openai` mount does not make
`openai-chatgpt` look configured.
2. THE HOOK-LESS USER
---------------------
`routing show` reads matrix files straight from the bundle cache -- it even
lazy-fetches the bundle -- so it renders a matrix as "* active" on a host whose
ACTIVE BUNDLE never mounts `hooks-routing`. Then nothing applies the matrix
and every sub-agent silently inherits the parent session's provider.
Measured on a project pinned to `anchors-amp-dev` (a lean base that does not
include routing-matrix): `routing show` printed "balanced ... <- active" for
all 13 roles while the session's `delegate:agent_spawned` event carried
`provider_preferences: null` and the explorer ran on the parent's
claude-opus-5 instead of the matrix's gpt-5.6-terra.
Fix: `_routing_hook_is_composed` composes the session the way `runtime/
config.py` does -- active bundle + every app bundle, in order -- but stops at
`to_mount_plan()`: no `prepare()`, so no module installs and no network beyond
what is already cached (~0.1s on a warm host). If `hooks-routing` is absent,
`show` prints a warning naming the active bundle and the exact remediation:
amplifier bundle add git+https://github.com/microsoft/amplifier-bundle-routing-matrix@main#subdirectory=behaviors/routing.yaml --app
Only runs when an active bundle is EXPLICITLY set: with none set the CLI
starts its built-in default, `foundation`, which includes routing-matrix, so
there is nothing to warn about -- and skipping the composition keeps this out
of every code path and test fixture that never chose a bundle (an earlier
draft composed the real `foundation` bundle inside the shadowing tests, 12s
per invocation, and its side effects made two runs of `show` disagree).
Any failure inside the check returns None and prints nothing: a diagnostic
must never break the command.
Verified live on the host that surfaced it: from the anchors-amp-dev project
the warning prints with the copy-pasteable command (soft_wrap, so Rich cannot
fold it); from a directory on the default bundle it prints nothing.
Tests: tests/test_routing_family_alias_and_mount_warning.py (10) -- chatgpt
alone makes openai configured; alias is directional; empty table is
byte-identical to before; table is read from the hook, never copied; warning
names the bundle, the hook and the exact command; silent when composed;
silent when it cannot tell; detection failure degrades to None; no active
bundle means no composition; remediation URI is the bundle's real behaviors
file. Full suite 1917 passed, ruff clean on touched files.
Generated with Amplifier
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Brian Krabach (bkrabach)
deleted the
fix/routing-show-alias-and-mount-warning
branch
September 7, 2026 18:25
Brian Krabach (bkrabach)
added a commit
that referenced
this pull request
Sep 7, 2026
…level policy (#322) This CLI ships `amplifier routing show/use/create/manage` and `amplifier init`'s routing panel. Until now the hook those commands describe was mounted only if the base bundle happened to include routing-matrix -- and the DEFAULT bundle, `anchors` (runtime/config.py:1415), did not. So every default user had the routing UX and no routing. Measured 2026-09-07: `routing show` printed "balanced ... <- active" for every role while the session's `delegate:agent_spawned` carried `provider_preferences: null` and the explorer ran on the parent's model. The existing post-hoc injection in `_apply_config_overrides` (the `routing_hook_override` block) only fires when `routing.matrix` is SET in settings, so a user on defaults got nothing; and it appends a bare hook entry, not the behavior -- no model_role contract in context, no role-definitions skill. Fix: `_build_routing_behaviors(app_settings)`, composed on every session next to `_build_skills_behaviors` / `_build_wayfinder_behaviors`, same shape and same reasoning as their docstrings ("regardless of which base bundle the user selected"). Behavior file only -- never the bundle root bundle.md. Swapping the implementation: `sources.bundles["routing-matrix"]` -- the existing `amplifier source add` vocabulary -- is consulted first. A user who prefers a fork composes THAT bundle's behaviors/routing.yaml instead of ours, so exactly one routing hook is ever composed. Without an override the URI is derived from WELL_KNOWN_BUNDLES["routing-matrix"], the same entry `_routing_hook_source`, `amplifier routing` and `amplifier update` read: one home for where the bundle lives. Composed BEFORE app bundles, so an app-bundle fork composes later and wins by module id. Bases that already include routing-matrix (`foundation`; `anchors` as of amplifier-foundation#374) are unaffected -- compose dedupes hooks by module id. Verified on this host: the workspace's `anchors-amp-dev` session, which mounted 0 routing hooks before, now mounts exactly 1 through the real compose path, with GitHub main's anchors (i.e. before #374 lands). The existing `routing_hook_override` block is left as-is: with the hook now always present its append-with-source path is a no-op and its config-merge path is exactly what should happen when a user sets `routing.matrix`. Retires #321's "displayed but not mounted" warning in `routing show`. It composed active + app bundles but not the CLI's always-composed behaviors, so after this change it would FALSE-ALARM on every anchors user -- and the condition it guarded is now unreachable. Its helpers and tests are removed; the alias fix from #321 stays (tests/test_routing_family_alias.py). Tests: tests/test_runtime_routing_composition.py (7) -- default is the well-known behavior file; never the bare root; one home with _routing_hook_source; sources.bundles override swaps; override means exactly one behavior (swap, not add); unrelated overrides don't touch it; the builder is actually called at the compose site and before app bundles. Full suite 1918 passed, ruff clean on touched files. Generated with Amplifier Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
amplifier routing showmisled two kinds of user. Both found 2026-09-07 while shipping routing-matrix#71; both fixed incommands/routing.py.1. The alias-blind user
A ChatGPT-subscription-only user (
openai-chatgptmodule, noopenaimodule) is routed fine at runtime — the hook'sPROVIDER_FAMILY_ALIASESmapsprovider: openaionto that mount. But_get_configured_provider_typesfed a bare set-membership test that never consulted the alias table, so the display told exactly that user "✗ not configured" for every openai role. Measured in a DTU.Fix:
_get_configured_provider_typesalso adds every canonical family a configured module satisfies, reading the table fromamplifier_module_hooks_routing.resolver.PROVIDER_FAMILY_ALIASESitself — one home, so the display cannot disagree with the resolver. All four downstreamin provider_typessites become alias-aware with no change. Guarded import: on a clean install before the bundle is first fetched it degrades to "no aliases" (pre-alias behaviour), never an error. Directional, as in the resolver.2. The hook-less user — the one that actually bit
routing showreads matrix files straight from the bundle cache (it even lazy-fetches the bundle), so it renders a matrix as "★ active" on a host whose active bundle never mountshooks-routing. Nothing then applies the matrix; every sub-agent silently inherits the parent's provider.Measured on a project pinned to
anchors-amp-dev— a lean base that does not include routing-matrix:Fix:
_routing_hook_is_composedcomposes the session the wayruntime/config.pydoes — active bundle + every app bundle, in order — but stops atto_mount_plan(): noprepare(), no module installs, no network beyond what's cached (~0.1s warm). Ifhooks-routingis absent,showprints:(command printed with
soft_wrap=Trueso Rich can't fold it mid-URI).Scope guard: only runs when an active bundle is explicitly set. With none set the CLI starts its built-in default
foundation, which includes routing-matrix — nothing to warn about, and skipping the composition keeps this out of every code path and test fixture that never chose a bundle. (An earlier draft composed the realfoundationbundle inside the shadowing tests: 12s per invocation, and its side effects made two runs ofshowdisagree. That's why the guard exists.) Any failure inside the check →None→ prints nothing. A diagnostic must never break the command.Verified live on the host that surfaced it
routing showanchors-amp-dev/tmpfoundation)Tests
tests/test_routing_family_alias_and_mount_warning.py(10): chatgpt alone makes openai configured · alias is directional · empty table is byte-identical to before · table is read from the hook, never copied · warning names bundle + hook + exact command · silent when composed · silent when it can't tell · detection failure degrades toNone· no active bundle means no composition · remediation URI is the bundle's real behaviors file.Full suite 1917 passed; ruff clean on touched files (the 9 pre-existing findings elsewhere are untouched).