OmniRoute Combo Schema Validation: A Complete Guide to Zod Constraints and Rules
OmniRoute validates all combo configurations using comprehensive Zod schemas located in src/shared/validation/schemas/combo.ts, enforcing strict constraints on naming, model steps, runtime configuration, and routing strategies before any data reaches the database.
Every routing configuration in the OmniRoute open-source repository is governed by a robust validation layer that ensures type safety and data integrity. Whether you are creating combos via the REST API, CLI, or UI, the system applies server-side validation through Zod schemas that define precise boundaries for strings, numbers, enums, and nested objects. This validation guarantees that the routing engine receives only well-formed configurations, preventing runtime errors and ensuring consistent behavior across the multi-provider inference pipeline.
Core Validation Layers
The validation logic in OmniRoute is modular, with specific schemas dedicated to distinct aspects of combo configuration. Each layer targets a particular data structure, from simple name strings to complex runtime configurations.
Combo Name Validation
The comboNameSchema enforces strict naming conventions for all combo definitions. According to the source code in src/shared/validation/schemas/combo.ts, combo names must be between 1 and 100 characters after trimming, and may only contain letters, numbers, spaces, and the special characters - _ / . [ ]. The schema automatically trims whitespace and rejects empty strings, ensuring that every combo has a readable, URL-safe identifier.
Model Step Validation
Individual steps within a combo are validated by comboModelStepInputSchema. This schema requires a model string (1–300 characters) and accepts optional fields including provider, providerId, and connectionId. The prompt field—representing system instructions—accepts up to 20,000 characters. Weight and metadata constraints are inherited from comboStepMetaSchema, which restricts weights to the 0–100 range and labels to 200 characters maximum.
For steps that reference other combos rather than direct models, comboRefStepInputSchema validates the comboName field (1–100 characters) and applies the same metadata constraints as model steps.
The comboModelEntry schema acts as a union validator, accepting either a plain string (legacy format), a full comboModelStepInputSchema object, or a comboRefStepInputSchema object, providing backward compatibility while encouraging structured configurations.
Runtime Configuration Constraints
The comboRuntimeConfigSchema is the most comprehensive validator in the system, containing all tunable knobs for combo execution. It enforces numeric ranges such as maxRetries (0–10), timeoutMs (minimum 1,000), and queueDepth (maximum 100). The schema also validates queue limits (concurrencyPerModel ≤ 20) and boolean flags for session stickiness, health checks, and zero-latency optimizations.
Importantly, this schema uses .passthrough() to allow unknown keys for future-proofing, but implements a custom .transform() hook that automatically enables zeroLatencyOptimizationsEnabled when legacy flags like hedging or predictiveTtftMs are detected without the new flag being present.
Shadow and Evaluation Routing
Optional advanced routing features have dedicated validators. shadowRoutingSchema validates the silent traffic duplication feature, ensuring sampleRate falls between 0 and 1, maxTargets stays within 1–10, and the targets array contains no more than 20 entries of comboModelEntry. The timeoutMs for shadow requests must be between 1,000 and 120,000 milliseconds.
For automated testing, evalRoutingSchema validates evaluation suite configurations. It accepts up to 50 suiteIds (each 1–200 characters), sets maxAgeHours between 1 and 8,760, and requires minCases between 1 and 100,000. Weighting fields are constrained to the 0–1 range.
Strategy and Compression Enums
The comboStrategySchema restricts routing strategies to values exported from ROUTING_STRATEGY_VALUES in src/shared/constants/routingStrategies.ts, preventing invalid algorithm selections.
Compression settings are governed by compressionModeSchema, which restricts values to the enum: "off", "lite", "standard", "aggressive", "ultra", "rtk", or "stacked". The comboCompressionOverrideSchema extends this with an empty string option to represent "no override" configurations.
Composite Tier Configuration
For hierarchical routing in composite combos, compositeTierEntrySchema and compositeTiersSchema validate tier structures. Each entry requires a stepId (≤ 200 characters) and supports optional fallback tiers, labels, and descriptions. The defaultTier field is mandatory, and the tiers property must be a record keyed by tier name.
Response Validation Rules
The responseValidationSchema defines runtime checks for upstream provider responses, used primarily for fail-over logic. It validates forbiddenSubstrings and requiredSubstrings arrays (max 50 items each, each string ≤ 500 characters), sets minContentLength between 0 and 1,000,000 bytes, and restricts jsonPathPredicates to 20 objects with specific condition enums (exists, nonEmpty, equals, notEquals).
CRUD Operation Schemas
Creating New Combos
The createComboSchema validates payloads for POST /api/combos requests. It requires a name (validated by comboNameSchema), accepts an optional description (≤ 2,000 characters), and expects a models array of comboModelEntry items (defaulting to empty). The strategy field defaults to "priority", while optional fields include config (runtime configuration), allowedProviders, system_message, and tool_filter_regex.
Updating Existing Combos
For PATCH operations, updateComboSchema makes all fields optional but enforces a custom superRefine check that requires at least one field to be present. If no valid fields are provided, it returns the error "No valid fields to update". This schema additionally accepts a compressionOverride field not present in the creation schema.
Global Defaults and Reordering
The updateComboDefaultsSchema validates updates to global combo defaults that affect all combos. It uses a custom superRefine to reject empty bodies and explicitly disallow compositeTiers on defaults or provider overrides, as hierarchical tiers are per-combo configurations.
For UI operations, reorderCombosSchema ensures that comboIds arrays contain unique identifiers (1–200 characters each) with a length between 1 and 1,000 items.
Testing Combos
The testComboSchema supports the health-check endpoint by requiring a trimmed, non-empty comboName string.
Schema Wiring and Backward Compatibility
The validation system uses composition to maintain consistency. The comboStepMetaSchema defines shared metadata fields (id, weight, label) that are spread into both model and reference step schemas using the spread operator (...comboStepMetaSchema).
The transform logic in comboRuntimeConfigSchema ensures backward compatibility by automatically injecting zeroLatencyOptimizationsEnabled: true when any legacy zero-latency flags are detected but the new unified flag is missing. This prevents stored configurations from failing validation after schema updates.
Practical Validation Examples
Creating a Simple Combo
{
"name": "my-first-combo",
"description": "Demo combo that routes to OpenAI gpt‑4o.",
"models": [
{
"model": "gpt-4o",
"provider": "openai",
"weight": 100,
"prompt": "You are a helpful assistant."
}
],
"strategy": "priority",
"config": {
"maxRetries": 3,
"timeoutMs": 30000,
"compressionMode": "lite",
"responseValidation": {
"forbiddenSubstrings": ["error", "failed"],
"minContentLength": 50
}
}
}
This payload satisfies all constraints: the name is ≤ 100 characters, the model string is ≤ 300 characters, the weight is within 0–100, timeout is ≥ 1,000 ms, compression uses an allowed enum value, and forbidden substrings are ≤ 500 characters each.
Partial Update with Scoring Weights
{
"description": "Updated description with more detail.",
"config": {
"strategy": "weighted",
"weights": {
"quota": 0.4,
"health": 0.2,
"costInv": 0.1,
"latencyInv": 0.1,
"taskFit": 0.1,
"stability": 0.1
},
"zeroLatencyOptimizationsEnabled": true
}
}
The updateComboSchema accepts this partial payload because at least one field is present, and all numeric weights fall within the 0–1 range as enforced by scoringWeightsSchema.
Advanced Configuration with Shadow and Eval Routing
{
"name": "shadow‑eval‑combo",
"models": [
{ "model": "claude-3-5-sonnet", "provider": "anthropic", "weight": 80 },
{ "model": "gpt-4o-mini", "provider": "openai", "weight": 20 }
],
"config": {
"shadowRouting": {
"enabled": true,
"targets": [
{ "model": "gpt-4o-mini", "provider": "openai" }
],
"sampleRate": 0.1,
"maxTargets": 5,
"timeoutMs": 20000
},
"evalRouting": {
"enabled": true,
"suiteIds": ["qa‑suite-01", "latency‑suite-02"],
"maxAgeHours": 24,
"minCases": 10
}
}
}
This configuration demonstrates the validation of shadow routing (with sampleRate between 0–1 and maxTargets ≤ 10) and evaluation routing (with suiteIds ≤ 50 and maxAgeHours ≤ 8,760).
Key Source Files
src/shared/validation/schemas/combo.ts– Central Zod definitions for all combo validation including names, steps, runtime config, and overrides.src/shared/constants/routingStrategies.ts– Enum values used bycomboStrategySchema.src/shared/constants/batchEndpoints.ts– Constants for batch-endpoint validation in runtime config.src/app/api/v1/combos/route.ts– API route that applies Zod schemas to HTTP requests.
Summary
- OmniRoute validates all combo data using Zod schemas in
src/shared/validation/schemas/combo.tsbefore database storage. - Name constraints limit combo names to 1–100 characters with specific allowed characters and automatic trimming.
- Step validation supports both direct model references and nested combo references, with weights restricted to 0–100 and prompts up to 20,000 characters.
- Runtime configuration enforces numeric ranges for retries (0–10), timeouts (≥ 1,000 ms), and queue depths (≤ 100), while using
.passthrough()and.transform()for backward compatibility. - Shadow and eval routing schemas validate advanced features with strict bounds on sample rates, target counts, and suite configurations.
- CRUD operations use distinct schemas (
createComboSchema,updateComboSchema,updateComboDefaultsSchema) with customsuperRefinechecks to prevent empty updates and invalid default configurations.
Frequently Asked Questions
What is the maximum length for a combo name in OmniRoute?
The comboNameSchema restricts combo names to between 1 and 100 characters after trimming. The validation also limits allowed characters to letters, numbers, spaces, and the specific symbols - _ / . [ ], ensuring URL-safe and readable identifiers.
How does OmniRoute handle backward compatibility when combo schemas change?
The system uses Zod's .passthrough() method to allow unknown keys in comboRuntimeConfigSchema, preventing immediate rejection of configs with legacy fields. Additionally, a custom .transform() hook automatically enables zeroLatencyOptimizationsEnabled when older zero-latency flags like hedging or predictiveTtftMs are present but the new flag is missing, ensuring stored combos remain valid after updates.
What validation is applied to the weights field in a combo configuration?
The scoringWeightsSchema validates all scoring weights as numbers between 0 and 1. This schema applies to the auto-combo engine's weighting fields, including tierPriority, tierAffinity, specificityMatch, and contextAffinity, ensuring that the weighted routing algorithm receives normalized input values.
Can I update a combo without providing all fields?
Yes. The updateComboSchema allows partial updates where all fields are optional, but it enforces a custom superRefine validation that requires at least one field to be present. If you submit an empty payload, the schema returns the error "No valid fields to update", preventing no-op database operations.
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 →