Registry-driven LLM routing: build classifier prompts from agent descriptions, validate decisions, and dispatch.
Project description
agent-registry-router
Registry-driven LLM routing: build classifier prompts, validate decisions, and dispatch to the right agent.
Why
When you have multiple AI agents, something needs to decide which one handles each user message. Most teams hardcode if/else chains or build bespoke classifiers. This library gives you a clean, framework-agnostic way to:
- Build classifier prompts from a registry of agent descriptions
- Validate routing decisions with typed errors (no silent fallbacks)
- Dispatch to the selected agent with observability hooks
- Benchmark classifier accuracy across LLMs and embedding models
How It Works
graph LR
A[User Message] --> B{Classifier}
B -->|LLM| C[Build Prompt from Registry]
B -->|FAISS| D[Embed & Similarity Search]
C --> E[RouteDecision]
D --> E
E --> F[Validate Against Registry]
F --> G[Dispatch to Agent]
G --> H[Response]
Install
pip install agent-registry-router
With a framework adapter:
pip install "agent-registry-router[pydanticai]" # PydanticAI
pip install "agent-registry-router[openai-agents]" # OpenAI Agents SDK
pip install "agent-registry-router[google-adk]" # Google ADK
pip install "agent-registry-router[faiss]" # FAISS classifier
Quick Start
from agent_registry_router.core import (
AgentRegistry,
AgentRegistration,
RouteDecision,
build_classifier_system_prompt,
validate_route_decision,
)
# Register your agents
registry = AgentRegistry()
registry.register(AgentRegistration(name="billing", description="Handles billing and payments."))
registry.register(AgentRegistration(name="technical", description="Handles technical support."))
registry.register(AgentRegistration(name="general", description="Handles general inquiries."))
# Build a classifier prompt from the registry
prompt = build_classifier_system_prompt(registry, default_agent="general")
# Validate a routing decision
decision = RouteDecision(agent="billing", confidence=0.9, reasoning="Payment question.")
validated = validate_route_decision(decision, registry=registry, default_agent="general")
Adapters
Framework-specific dispatchers that handle classify → validate → dispatch. Each is opt-in — the core has no framework dependencies.
| Adapter | Install Extra | Dispatcher Class |
|---|---|---|
| PydanticAI | pydanticai |
PydanticAIDispatcher |
| OpenAI Agents SDK | openai-agents |
OpenAIAgentsDispatcher |
| Google ADK | google-adk |
GoogleADKDispatcher |
All adapters are duck-typed (no runtime imports of the framework). Any object matching the protocol works. All support:
route_and_run()— classify, validate, dispatchroute_and_stream()— same flow, streaming output- Pinned agent bypass (skip classifier, dispatch directly)
on_eventobservability hooks
from agent_registry_router.adapters.pydantic_ai import PydanticAIDispatcher
from agent_registry_router.adapters.openai_agents import OpenAIAgentsDispatcher
from agent_registry_router.adapters.google_adk import GoogleADKDispatcher
FAISS Classifier
An alternative to LLM-based classification: embed agent descriptions, find the nearest match by cosine similarity. Near-zero latency, near-zero cost.
from agent_registry_router.core import FaissClassifier
classifier = FaissClassifier(
registry=registry,
embed_fn=your_embedding_function, # any callable: list[str] -> list[list[float]]
)
decision = classifier.classify("I was charged twice")
Structured Logging
Built-in JSON logging for routing events. One line to set up.
from agent_registry_router.core import StructuredLogger
dispatcher = PydanticAIDispatcher(
...,
on_event=StructuredLogger(),
)
# Produces: {"ts": "...", "event": "classifier_run_success", "agent": "billing", "confidence": 0.92}
Eval Suite
Benchmarks the classifier prompts this library generates across LLMs and FAISS. Includes fixtures, a runner, and a report generator.
make install-eval
cp .env.example .env # add your API keys
make eval
See evals/README.md for details. Bring your own fixtures to benchmark your own agent registries.
Error Handling
Fail-fast with typed exceptions — no silent fallbacks.
InvalidRouteDecision— classifier picked a non-routable agentInvalidFallback— default agent isn't routable or registry is emptyAgentNotFound— validated agent can't be resolved for dispatchRegistryError— invalid names, descriptions, or empty registry
Design Principles
- Framework-agnostic core: routing logic has no opinion on your agent framework
- Duck-typed adapters: protocols, not imports — any compatible object works
- Fail-fast validation: typed errors, never silent wrong-agent routing
- Deterministic prompts: registration order preserved, routable-only, size-bounded
- Observable:
on_eventhooks +StructuredLoggerfor production monitoring
Development
make install # install dev dependencies
make lint # ruff + black + mypy
make test # pytest with 85% coverage gate
make format # auto-format
make eval # run classifier benchmarks (requires API keys)
License
Apache-2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_registry_router-0.3.0.tar.gz.
File metadata
- Download URL: agent_registry_router-0.3.0.tar.gz
- Upload date:
- Size: 20.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28998e968bc2ee5ca7d17e2752095261966cafb8f7283d4cddfadcc854624909
|
|
| MD5 |
e1bcf762d021f9ea001381101fd18a85
|
|
| BLAKE2b-256 |
86a9c52e0c44440dedad9d57c5957d1f8f2ceddcf6551bc0b2041f2eb08109ff
|
Provenance
The following attestation bundles were made for agent_registry_router-0.3.0.tar.gz:
Publisher:
publish-pypi.yml on agibson22/agent-registry-router
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_registry_router-0.3.0.tar.gz -
Subject digest:
28998e968bc2ee5ca7d17e2752095261966cafb8f7283d4cddfadcc854624909 - Sigstore transparency entry: 1009354396
- Sigstore integration time:
-
Permalink:
agibson22/agent-registry-router@3318ffad233a362dd143e16b54777ca8777127dd -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/agibson22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@3318ffad233a362dd143e16b54777ca8777127dd -
Trigger Event:
push
-
Statement type:
File details
Details for the file agent_registry_router-0.3.0-py3-none-any.whl.
File metadata
- Download URL: agent_registry_router-0.3.0-py3-none-any.whl
- Upload date:
- Size: 33.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ca5084c6c2d0f7ed056ff137b98eef225a324eb72b2997176bf9331ad0e0e73
|
|
| MD5 |
786cfd906e93dfef2579153bb6d54528
|
|
| BLAKE2b-256 |
c60bc928d4d6762f3f4319d40f40339440004914c55b859f98948ae0b8784148
|
Provenance
The following attestation bundles were made for agent_registry_router-0.3.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on agibson22/agent-registry-router
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_registry_router-0.3.0-py3-none-any.whl -
Subject digest:
2ca5084c6c2d0f7ed056ff137b98eef225a324eb72b2997176bf9331ad0e0e73 - Sigstore transparency entry: 1009354403
- Sigstore integration time:
-
Permalink:
agibson22/agent-registry-router@3318ffad233a362dd143e16b54777ca8777127dd -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/agibson22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@3318ffad233a362dd143e16b54777ca8777127dd -
Trigger Event:
push
-
Statement type: