跳到主要内容
版本:最新版

Unified Config Contract v0.3

Status: Implemented · Created: 2026-03-17

Problem

The router, CLI, dashboard, Helm chart, operator, and DSL previously interpreted overlapping configuration shapes. A file accepted by one surface could require translation or undocumented defaults in another. Model identity was also mixed with deployment endpoints and credentials.

Implemented contract

The public configuration has seven top-level sections:

version:
listeners:
providers:
routing:
entrypoints:
recipes:
global:
SectionResponsibility
versionSelects the configuration contract.
listenersDefines request-facing and management listeners.
providersBinds logical model names to provider identifiers and endpoints.
routingDefines the default model cards, signals, projections, decisions, algorithms, and plugins.
entrypointsMaps request-facing model names to the default profile or a named recipe.
recipesDefines additional isolated routing profiles that share providers and global infrastructure.
globalHolds router-wide services, stores, integrations, model modules, and sparse runtime overrides.

Unknown or retired shapes should fail with a clear validation error rather than be silently translated at runtime.

Provider and model boundary

providers.defaults owns the default provider behavior and default model. providers.models[].backend_refs[] owns physical backend bindings. providers.models[].api_format owns only the upstream wire format and never selects a Provider. A physical model in a Router-owned listener configuration must declare an explicit backend Provider; metadata-only external-gateway configuration and built-in virtual models may remain backendless. The local CLI serve path owns Envoy transport and rejects backendless physical models; external-gateway metadata-only configurations are deployed through the gateway integration rather than converted into a standalone Envoy data plane. providers.models[].pricing owns optional deployment cost metadata used by cost-aware selection and accounting. Pricing does not belong to routing model cards.

routing.modelCards describes routing-facing model identity. Optional routing.modelCards[].loras declare LoRA adapters that decisions may select with lora_name. Signals and decisions reference logical model names, not endpoints or credentials.

Routing and DSL boundary

Routing owns:

  • model cards;
  • named signals and projections;
  • decisions, candidate modelRefs, algorithms, and plugins;
  • route-local output and adaptation policy.

Algorithms may declare minimum_candidates as a portable Recipe contract. Model-free assets can carry the declaration with empty modelRefs; a concrete Entrypoint binding must satisfy it, and request-time eligibility filters must preserve it before selection or multi-model execution begins.

Structured request controls remain facts at the signal boundary. For example, conversation signals expose whether the protocol requires or forbids tool execution, projections reconcile those facts with text-derived observations, and decisions consume the resulting policy-facing output.

Top-level entrypoints select the default routing profile or a named item from top-level recipes; they are not nested inside routing.

The DSL is an authoring view of routing semantics. It does not own provider credentials, listeners, stores, or global runtime services. Import and export must preserve the same canonical routing document rather than invent another steady-state schema.

Classifier backend failures enter decision evaluation as Unknown. NOT preserves that state, while AND and OR use CEL-style short-circuit semantics. A decision resolves a terminal Unknown with root-level rules.on_unknown: no_match|match|fail_request; omission preserves the existing per-family compatibility behavior.

Entrypoints and multi-recipe routing

entrypoints[] map request model names to either top-level routing or one named recipe. recipes[] contain isolated routing profiles that reuse the same provider inventory and global runtime.

This keeps the public API stable while allowing several routing policies to coexist in one process. An entrypoint resolves the recipe before signals and decisions run.

Defaults and configuration source

Built-in defaults live in the router. global.router.config_source selects file-backed configuration or Kubernetes CRD reconciliation. External templates must not apply hidden defaults after validation.

Built-in category/domain inference keeps its runtime policy in global.model_catalog.modules.classifier.domain. The local model uses the canonical variant field; a remote classifier uses the shared backend block (protocol, contract, model, and deadline_ms) and resolves model by exact external-catalog name. The category consumer currently accepts http_classify plus label_distribution.v1, preserving the full label-score distribution. Prompt guard remains on its existing configuration surface until its separately scoped migration. Connector byte ceilings belong to the connector configuration. External LLM classifier entries and the MCP classifier module use max_response_bytes. The dashboard, Helm chart, and operator may help users author or transport config, but the resulting document still uses the same contract.

Repository sources

config/config.yaml is the exhaustive canonical reference config. Reusable examples live under:

  • config/fragments/signal/;
  • config/fragments/decision/;
  • config/fragments/algorithm/; and
  • config/fragments/plugin/.

Runtime deployment examples remain separate from routing fragments. Contract tests and make check keep the reference config, schema, examples, and public docs aligned.

Migration

Use vllm-sr config migrate --config old-config.yaml to convert supported legacy layouts. Review the result, resolve credentials through the deployment's secret mechanism, and validate it before serving.

vllm-sr init was removed. Canonical YAML is the steady-state configuration source; interactive or graphical authoring tools must export that same document.

Scope and non-goals

The contract unifies configuration ownership. It does not require every authoring surface to expose every advanced field in one form, nor does it make the DSL a deployment-language replacement.

References