How OpenMontage Selector Tools Transparently Route to Providers
OpenMontage selector tools like tts_selector and video_selector transparently route to providers by automatically discovering capable backends through the ToolRegistry, scoring them against normalized task contexts, and delegating requests while enriching results with selection metadata.
OpenMontage abstracts concrete provider implementations behind capability-level selectors, enabling agents to request high-level functions like text-to-speech or video generation without hardcoding specific APIs. The selector tools handle the complex logic of provider discovery, ranking, and adaptation internally, presenting a unified interface that routes requests to the most appropriate available backend. This architecture ensures that selector tools transparently route to providers based on real-time availability, task requirements, and user preferences.
Automatic Provider Discovery via ToolRegistry
The routing process begins with automatic discovery in the selector's _providers() method. Located in tools/audio/tts_selector.py, this method queries the global ToolRegistry at runtime to locate any BaseTool instance whose capability field matches the selector's designated capability—"tts" for audio generation or "video" for video generation.
This discovery mechanism requires no manual registration. When developers add new providers to the system, they automatically become available to the selector provided they implement the correct capability constant, ensuring the routing pool expands dynamically as the ecosystem grows.
Dynamic Provider Matrix Construction
Each discovered provider contributes a row to the internal provider_matrix, a data structure that records the provider name alongside its "strength" rating. The strength value derives from the provider's best_for field, which describes optimal use cases and performance characteristics.
This matrix serves dual purposes: it drives the scoring algorithm that determines routing decisions, and it provides UI-side explanations for why specific providers were selected for particular tasks.
Task-Context Normalization and Preparation
Before scoring occurs, the selector prepares a normalized task-context dictionary from user inputs such as text, language, voice, or prompt. This normalization happens via lib.scoring.normalize_task_context, which standardizes parameters across different provider APIs to ensure fair comparison.
By passing the same structured context to every candidate provider, the system eliminates interface discrepancies that could skew routing decisions, creating a level playing field for the ranking engine.
Scored Ranking with Operation Modes
The core routing logic resides in lib.scoring.rank_providers, which evaluates candidates against the normalized context and returns ScoreItem objects containing suitability scores. The tts_selector and video_selector support two distinct operation modes controlled by the operation parameter:
operation="rank"— Returns the full ranked provider list without invoking any backend. This mode is useful for UI inspection, debugging provider selection logic, or presenting options to users before committing resources.operation="generate"(default) — Selects the highest-scoring available provider and executes the actual generation task, handling all delegation transparently.
When users specify preferred_provider or allowed_providers in the request, the selector filters the candidate list before scoring, ensuring explicit preferences override automatic selection when provided.
Fallback Handling and Availability Management
If no providers are available for the requested capability, the selector returns ToolStatus.UNAVAILABLE along with a failure result. The fallback_tools property dynamically mirrors the names of all discovered providers, allowing downstream components to present alternative options when primary choices fail or constraints eliminate all high-scoring candidates.
This design ensures graceful degradation while maintaining transparency about available alternatives.
Input Adaptation for Provider APIs
Before delegating to the concrete provider, the selector performs input adaptation to match provider-specific requirements. For example, it might convert generic parameters like speaking_rate to Azure's specific rate parameter, or normalize output_format values to match individual provider expectations.
This translation layer prevents provider-specific quirks from leaking into the high-level selector interface, maintaining the abstraction that selector tools transparently route to providers regardless of backend differences.
Result Enrichment and Transparency Metadata
After the chosen provider completes execution, the selector augments the ToolResult object with metadata fields defined in tools/audio/tts_selector.py:
selected_tool: The concrete provider implementation usedselected_provider: The provider identifier stringselection_reason: Human-readable explanation of the ranking logicalternatives_considered: List of other providers evaluated during selection
These fields provide full visibility into routing decisions, supporting debugging and enabling user interfaces to explain why specific backends were chosen.
Practical Implementation Examples
The following examples demonstrate how to use the selectors with different routing configurations.
Using tts_selector with an explicit provider preference:
result = registry.get("tts_selector").execute({
"text": "Hello, world!",
"preferred_provider": "elevenlabs", # Force ElevenLabs if available
"voice": "Rachel",
"operation": "generate"
})
print(result.data["selected_provider"]) # → "elevenlabs"
print(result.data["selection_reason"]) # Explanation of why it was chosen
Ranking providers without generating audio:
rankings = registry.get("tts_selector").execute({
"text": "Testing ranking mode",
"operation": "rank"
})
for entry in rankings.data["rankings"]:
print(f"{entry['provider']}: {entry['score']:.2f}")
Using video_selector in the same way:
video_result = registry.get("video_selector").execute({
"prompt": "A futuristic cityscape at sunrise",
"preferred_provider": "runway",
"operation": "generate"
})
print(video_result.data["selected_tool"]) # e.g., "runway_video"
Summary
- Automatic Discovery: Selectors query
ToolRegistryforBaseToolinstances matching their capability ("tts"or"video") through the_providers()method without requiring manual registration. - Dynamic Ranking: The
provider_matrixandlib.scoring.rank_providersevaluate candidates based on task context andbest_forstrengths to determine optimal routing. - Flexible Operations: Support for
operation="rank"(inspection) andoperation="generate"(execution) modes adapts to different workflow requirements. - User Preferences: The
preferred_providerandallowed_providersparameters allow explicit override of automatic selection logic. - Transparent Metadata: Results include
selected_provider,selection_reason, andalternatives_consideredfor full routing visibility. - Provider-Agnostic Interface: Input adaptation and result enrichment hide provider-specific complexity behind unified capability selectors in
tools/audio/tts_selector.pyandtools/video/video_selector.py.
Frequently Asked Questions
How does the selector choose between multiple available providers?
The selector uses lib.scoring.rank_providers to evaluate each candidate against a normalized task context created by lib.scoring.normalize_task_context. Each provider's best_for characteristics are compared against task requirements to generate relevance scores, with the highest-scoring available provider selected by default. Users can override this behavior by setting the preferred_provider parameter in the request.
What happens if my preferred provider is unavailable?
If the specified preferred_provider is not found or unavailable, the selector filters it from the candidate list and proceeds to rank remaining providers according to the provider_matrix. If no providers remain available, the selector returns ToolStatus.UNAVAILABLE and populates fallback_tools with the names of all discovered alternatives, allowing your application to suggest other options or retry with different constraints.
Can I inspect provider rankings without triggering a generation?
Yes. Set operation="rank" when calling tts_selector or video_selector. This mode returns the full ranked list of providers and their scores through the rankings field without invoking any actual provider execution, making it ideal for debugging or presenting options to end users before committing to a generation task.
Where is the provider routing logic implemented in the codebase?
The routing implementation spans several key files: tools/audio/tts_selector.py and tools/video/video_selector.py contain the selector implementations with _providers() and result enrichment logic; lib/scoring.py houses the rank_providers and normalize_task_context functions; tools/tool_registry.py manages provider discovery; and tools/base_tool.py defines the interface shared by all providers and selectors. Architectural documentation is available in docs/ARCHITECTURE.md.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →