feature: redesign management API around versioned config snapshots
#2,326 opened on Jul 5, 2026
Repository metrics
- Stars
- (4,293 stars)
- PR merge metrics
- (PR metrics pending)
Description
Problem
The current vLLM Semantic Router management API has grown around several overlapping configuration paths: router config update, YAML update, deploy preview/deploy, global config update, raw global config update, rollback, runtime-generated config, and dashboard-specific wrappers.
This makes the control-plane semantics hard to reason about:
- desired config, runtime state, status, and debug output are mixed together
- dashboard, CLI, and router server do not share one clear mutation contract
- config changes do not consistently follow validate -> diff -> activate semantics
- partial updates and raw YAML updates make it hard to know which version is active
- there is no Envoy-style config dump / snapshot view for debugging
- future cluster-level provider/inference abstractions will be harder to add safely
We should redesign the management API around versioned, validated config snapshots.
Goal
Introduce a v1 management API that treats router configuration as a desired-state snapshot with explicit validation, diff, activation, rollback, status, and debug dump semantics.
This issue is only about the management API semantics. It should not implement endpoint scheduling, inference-pool discovery, or provider/inference cluster refactors directly.
Proposed API
Add a new /api/v1 management surface:
GET /api/v1/config/snapshot
POST /api/v1/config/validate
POST /api/v1/config/diff
POST /api/v1/config/activate
POST /api/v1/config/rollback
GET /api/v1/config/versions
GET /api/v1/config/dump
GET /api/v1/status/resources
GET /api/v1/runtime/snapshot
GET /api/v1/endpoints
GET /api/v1/policies/effective
Semantics
GET /api/v1/config/snapshot
Returns the normalized desired configuration currently active in the router.
Example response:
{
"generation": 12,
"version": "2026-07-05T12:00:00Z",
"hash": "...",
"config": {}
}
POST /api/v1/config/validate
Validates a candidate config without activating it.
The response should include structured errors and warnings tied to resource paths.
POST /api/v1/config/diff
Compares the active snapshot with a candidate config.
The response should include added, removed, and changed resources.
POST /api/v1/config/activate
Validates and activates a candidate config atomically.
Example request:
{
"mode": "replace",
"dryRun": false,
"expectedGeneration": 12,
"config": {}
}
Example response:
{
"generation": 13,
"version": "2026-07-05T12:05:00Z",
"hash": "...",
"warnings": [],
"conditions": []
}
expectedGeneration should protect against lost updates.
dryRun should run validation and diff without changing the active config.
mode can start with replace; merge can be added once merge semantics are clearly defined.
POST /api/v1/config/rollback
Rolls back to a previous known activated version.
GET /api/v1/config/versions
Lists previously activated snapshots.
GET /api/v1/config/dump
Returns an Envoy-style debug dump of the effective runtime config, including normalized config and compiled/effective policy state.
GET /api/v1/status/resources
Returns observed status per resource using generation, observedGeneration, and conditions.
GET /api/v1/runtime/snapshot
Returns runtime-only state and overrides.
Runtime state should be separate from desired config.
Design Requirements
- Desired config, runtime state, status, and debug dump must be separate concepts.
- Config activation must be atomic: validate the full snapshot first, then activate.
- Every active config should have a stable
generation,version, andhash. - Validation errors should be structured and tied to resource paths.
- Dashboard and CLI should eventually use this same API instead of maintaining separate mutation paths.
- Existing APIs should remain as compatibility shims during migration.
- Runtime-generated YAML should become an internal artifact, not the public source of truth.
- The API should leave room for future Envoy-like resources such as routes, clusters, endpoint sets, and policies.
Non-Goals
- Do not implement provider/inference cluster refactoring in this issue.
- Do not implement endpoint load balancing or prefix-cache-aware scheduling here.
- Do not remove existing dashboard or router config APIs immediately.
- Do not change the existing extproc request routing behavior as part of this issue.
- Do not introduce Kubernetes endpoint discovery in this issue.
Affected Areas
Likely affected files:
src/semantic-router/pkg/apiserver/routes.go
dashboard/backend/router/
src/vllm-sr/cli/
src/semantic-router/pkg/config/
Existing APIs should be wrapped or bridged into the new v1 semantics where possible.
Acceptance Criteria
- A new
/api/v1/config/snapshotendpoint returns the active normalized config withgeneration,version, andhash. - A new
/api/v1/config/validateendpoint validates candidate config without activation. - A new
/api/v1/config/diffendpoint returns a structured diff between active and candidate config. - A new
/api/v1/config/activateendpoint validates and atomically activates a candidate config. activatesupportsdryRun.activatesupportsexpectedGenerationconflict detection.- A new
/api/v1/config/rollbackendpoint restores a previous activated version. - A new
/api/v1/config/versionsendpoint lists available activated versions. - A new
/api/v1/config/dumpendpoint provides an effective debug view. - Status responses expose
observedGenerationand structuredconditions. - Existing router/dashboard config update paths continue to work during migration.
- Tests cover validate failure, dry-run activation, successful activation, generation conflict, rollback, and dump output.
Validation
Use the repo harness to select the exact gate for the final change:
make agent-report ENV=cpu CHANGED_FILES="..."
make agent-validate
make agent-lint CHANGED_FILES="..."
make agent-ci-gate CHANGED_FILES="..."