vllm-project/semantic-router

feature: redesign management API around versioned config snapshots

Open

#2,326 opened on Jul 5, 2026

View on GitHub
 (1 comment) (0 reactions) (0 assignees)Go (699 forks)github user discovery
area/corearea/dashboardenhancementhelp wantedoperationspriority/P1roadmap

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, and hash.
  • 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/snapshot endpoint returns the active normalized config with generation, version, and hash.
  • A new /api/v1/config/validate endpoint validates candidate config without activation.
  • A new /api/v1/config/diff endpoint returns a structured diff between active and candidate config.
  • A new /api/v1/config/activate endpoint validates and atomically activates a candidate config.
  • activate supports dryRun.
  • activate supports expectedGeneration conflict detection.
  • A new /api/v1/config/rollback endpoint restores a previous activated version.
  • A new /api/v1/config/versions endpoint lists available activated versions.
  • A new /api/v1/config/dump endpoint provides an effective debug view.
  • Status responses expose observedGeneration and structured conditions.
  • 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="..."

Contributor guide