How the Auto Combo Routing Strategy Works in OmniRoute
The auto combo routing strategy in OmniRoute dynamically selects the best LLM provider per request through a nine-step pipeline that combines intent classification, self-healing health checks, tiered scoring, and budget enforcement.
OmniRoute's auto combo is a self-optimizing routing mode designed to eliminate static provider lists. Instead of hard-coded priorities, the engine evaluates candidates at runtime using a multi-factor scoring system. This article breaks down the complete implementation as found in the OmniRoute source code.
What Is the Auto Combo Routing Strategy?
The auto combo is one of OmniRoute's configurable routing strategies. Unlike fixed-provider combos, it builds a candidate pool at request time and applies a sophisticated selection pipeline. The strategy lives primarily in open-sse/services/autoCombo/engine.ts and draws on supporting modules for scoring, health checks, and task fitness evaluation.
The core goal: deliver cost-aware, latency-optimized, and task-appropriate provider selection without manual tuning.
The 9-Step Auto Combo Pipeline
Step 1: Intent Classification
When callers don't specify a concrete taskType, the engine infers one from the conversation context. It extracts text from the last user message and runs classifyPromptIntent to categorize the request into built-in intents: code, reasoning, simple, or medium.
This inferred intent feeds into downstream task-fitness scoring. Implementation spans lines 30-45 of open-sse/services/autoCombo/engine.ts.
Step 2: Mode Pack and Weight Resolution
Combos can specify a mode pack—predefined weight profiles like "coding" or "fast"—that override raw config.weights. The engine normalizes final weights through normalizeScoringWeights.
This allows operational profiles without per-request configuration. See lines 48-55.
Step 3: Candidate Filtering
The engine applies two filters to build the initial candidate set:
- Pool restriction: Only providers in
config.candidatePoolare considered (empty pool = all providers eligible) - Health exclusion: The Self-Healing Manager (
getSelfHealingManager) evaluates each provider; unhealthy providers are excluded and tracked in theexcludedlist
This filtering occurs at lines 56-68.
Step 4: Provider Scoring
Remaining candidates pass through scorePool, which combines:
| Factor | Source |
|---|---|
| Static attributes | Cost, latency, reliability from provider metadata |
| Task fitness | getTaskFitness result using the Step 1 intent to bias toward appropriate model families |
The scoring implementation resides at lines 77-79.
Step 5: Second-Pass Self-Healing
After scoring, the Self-Healing manager re-evaluates providers using their actual scores. Any provider still deemed unhealthy is removed from consideration. This double-check prevents borderline-healthy providers from winning on score alone (lines 80-88).
Step 6: Exploration vs. Exploitation
The engine implements a configurable exploration rate (default 5%) via explorationRate. A random draw determines whether to:
- Explore: Select any candidate randomly to gather performance data on underutilized providers
- Exploit: Use deterministic Score-Tier Rotator selection
This trade-off between discovery and optimization appears at lines 96-104 and 98-106.
Step 7: Tiered Round-Robin Selection
When exploiting, providers are grouped into three tiers via groupIntoTiers:
- Top tier: Highest-scoring providers
- Mid tier: Moderate performers
- Rest tier: Lower-scoring options
If top-tier scores exceed the rest by CLEAR_WINNER_THRESHOLD, that tier wins outright. Otherwise, the combo name itself—"smart", "fast", "cheap"—drives weighted tier selection through chooseTierWeighted.
The tier logic spans lines 52-75, 78-84, 86-94, and 108-124.
Step 8: Budget Cap Enforcement
When config.budgetCap is set, the engine:
- Estimates USD cost for the selected provider
- If over cap, seeks a cheaper alternative within budget
- If no compliant candidate exists, applies
config.budgetFallback:"cheapest": Fall back to the cheapest provider (legacy behavior)"strict": ThrowBudgetExceededError, failing the request
Budget handling occupies lines 108-136 and 139-149.
Step 9: Result Construction
The final SelectionResult encapsulates:
- Selected provider and model
- Computed score
- Whether exploration was used
- Scoring factors breakdown
- Excluded providers list
- Connection ID (when applicable)
Assembly occurs at lines 138-147.
Configuration and Usage Example
import { selectProvider, type AutoComboConfig } from '@/open-sse/services/autoCombo/engine';
import { getProviderCandidates } from '@/open-sse/services/autoCombo/providerRegistryAccessor';
// Example auto-combo configuration
const config: AutoComboConfig = {
id: 'auto-chat',
name: 'smart',
type: 'auto',
candidatePool: [], // empty → consider all providers
weights: { cost: 0.2, latency: 0.3, reliability: 0.5 },
modePack: 'coding', // optional – overrides weights
budgetCap: 0.02, // $0.02 per request
budgetFallback: 'strict',
explorationRate: 0.05,
routerStrategy: 'cost',
};
// Pull the current provider candidates from the registry
const candidates = await getProviderCandidates();
// Optional: raw messages for intent classification
const promptMessages = [
{ role: 'user', content: 'Write a function to merge two sorted arrays in JavaScript.' },
];
// Perform the auto selection
try {
const result = selectProvider(config, candidates, 'default', promptMessages);
console.log('Selected provider:', result.provider);
console.log('Model:', result.model);
console.log('Score:', result.score);
console.log('Exploration:', result.isExploration);
} catch (e) {
if (e instanceof BudgetExceededError) {
console.error('Request exceeds budget cap:', e.message);
} else {
throw e;
}
}
Key Source Files in OmniRoute
| File | Purpose |
|---|---|
open-sse/services/autoCombo/engine.ts |
Core implementation: selection, tier rotation, budget handling, exploration logic |
open-sse/services/autoCombo/scoring.ts |
scorePool and weight normalization utilities |
open-sse/services/autoCombo/taskFitness.ts |
Task-specific fitness computation |
open-sse/services/autoCombo/selfHealing.ts |
Health-checking and provider exclusion |
open-sse/services/autoCombo/modePacks.ts |
Predefined weight profiles (coding, fast, etc.) |
open-sse/services/autoCombo/providerRegistryAccessor.ts |
Live provider candidate retrieval |
open-sse/services/autoCombo/__tests__/autoCombo.test.ts |
End-to-end validation suite |
Summary
- The auto combo routing strategy eliminates static provider ordering through runtime evaluation
- Nine pipeline steps handle intent detection, health filtering, scoring, exploration/exploitation trade-offs, tiered selection, and budget enforcement
- Self-healing health checks run twice to ensure reliability
- Mode packs and combo names provide operational tuning without code changes
- Strict budget fallback enables cost-guaranteed workloads
Frequently Asked Questions
How does OmniRoute's auto combo handle provider failures?
The auto combo uses a Self-Healing Manager that evaluates provider health during two separate phases. First, it filters out unhealthy providers before scoring. Second, after scoring, it re-checks remaining candidates and removes any that fail health validation. Unhealthy providers are tracked in the excluded list returned with the selection result.
What is the exploration rate in OmniRoute auto routing?
The explorationRate parameter (default 5%) controls probabilistic random selection. When triggered, the engine ignores scores and picks any candidate randomly. This gathers performance data on underutilized providers and prevents the system from over-optimizing to stale benchmarks. When not triggered, deterministic tier-based selection takes over.
Can the auto combo enforce strict budget limits?
Yes. Setting budgetCap enables cost estimation before final selection. If the chosen provider exceeds the cap, the engine seeks alternatives. With budgetFallback: 'strict', no valid candidate triggers a BudgetExceededError, failing the request rather than violating the budget. Use 'cheapest' for legacy fallback behavior instead.
How does OmniRoute determine which model fits a task?
If no taskType is provided, the engine runs classifyPromptIntent on the last user message to infer intent (code, reasoning, simple, medium). This intent feeds getTaskFitness, which biases the composite score toward providers with appropriate model families. Mode packs like "coding" further tune weight distributions for common workload patterns.
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 →