Skip to content

feat(router): compile dataPlane: AgentGateway to AgentgatewayModel - #2162

Draft
Tanguille wants to merge 1 commit into
defilantech:mainfrom
Tanguille:feat/agentgateway-model-routing
Draft

Tanguille wants to merge 1 commit into
defilantech:mainfrom
Tanguille:feat/agentgateway-model-routing

Conversation

@Tanguille

@Tanguille Tanguille commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

What

This adds a second way for dataPlane: AgentGateway routers to work: agentGatewayRef.routing: Model.

Today an AgentGateway router creates an InferencePool for every model, needs an Endpoint Picker, and puts a body-parsing policy on the whole Gateway. With routing: Model it uses agentgateway's built-in model router instead (agentgateway v1.6.0 or later). The router creates:

  • one HTTPRoute that sends the listener's traffic to the model router
  • one AgentgatewayModel per backend, which points a model name at the InferenceService's Service

agentgateway reads the model from the request body, answers GET /v1/models itself, and returns a 404 for unknown models. You don't need the Inference Extension CRDs or an Endpoint Picker.

spec:
  dataPlane: AgentGateway
  agentGatewayRef:
    name: ai-gateway
    routing: Model
    sectionName: llm
  backends:
    - name: chat
      displayName: chat-large
      inferenceServiceRef: {name: chat-vllm}
    - name: reranker
      inferenceServiceRef: {name: reranker}

The default stays InferencePool, so existing routers don't change.

Why

Part of #2151 (phase 1), following the plan in the maintainer's comment. Phase 2 (fallback between backends, aliases with request defaults) will be a separate PR.

How

Going through the points in that comment:

  • Opt-in: routing defaults to InferencePool, and endpointPicker is rejected in Model mode. Since feat(router): per-backend Endpoint Picker for dataPlane: AgentGateway #2157, InferencePool mode already checks for a picker in the webhook and the reconciler, so I left that check there instead of adding a CEL rule.
  • Names: the model name clients send (displayName, else name) goes into match.model. The object name comes from the router and the backend (<router>-<backend>), so names like Qwen3.5-2B or org/model work.
  • Ownership: the router owns everything it creates and won't take over an object it didn't create. It deletes the model of a removed backend, and cleans up the other mode's objects when you switch routing.
  • The catch-all route: Model mode requires sectionName or hostnames, so it can't take over a whole Gateway.
  • CRD check: when the AgentgatewayModel CRD is missing, the router reports AgentgatewayModelCRDNotInstalled and doesn't fail.
  • Tests: see Testing below.

The API formats come from the InferenceService:

  • llama.cpp chat gets Completions.
  • vLLM chat gets Completions, Messages, AnthropicTokenCount and Responses.
  • Embedding models get Embeddings, and rerankers Rerank.
  • Any other runtime gets a clear condition instead of a guess.

Anything Model mode can't do yet is rejected at apply time and by the reconciler (UnsupportedInModelRouting): rules, defaultRoute, external backends, resolution: endpoint, per-backend pickers, and duplicate or wildcard model names.

Testing

  • Unit and envtest coverage:
    • the generated objects, per runtime and format
    • name derivation
    • CEL and webhook validation
    • the InferencePool default rendering unchanged
    • refusing to adopt foreign objects
    • the CRD check
    • pruning removed backends
    • switching modes in both directions
  • make test-e2e-rbac passes. The routing: Model fixture goes Ready and creates its route and model under the generated RBAC.
  • Live check against agentgateway v1.6.0:

AI assistance

Checklist

  • Tests added/updated
  • make test passes locally
  • make lint passes locally
  • Commit messages follow conventional commits
  • All commits are signed off (git commit -s) per DCO
  • AI assistance (if any) is disclosed above, per CONTRIBUTING.md
  • Documentation updated (if user-facing change)

@Tanguille
Tanguille force-pushed the feat/agentgateway-model-routing branch from 5210f68 to 8701523 Compare October 22, 2026 22:45
agentGatewayRef.routing: Model compiles a ModelRouter onto agentgateway's
own model router (agentgateway v1.6.0+): one HTTPRoute whose single rule
at "/" hands requests to AgentgatewayModel "*", and one AgentgatewayModel
per inferenceServiceRef backend that matches the backend's served name
and points a custom provider at the InferenceService's Service. For
single-replica backends this drops the Inference Extension CRDs, the
Endpoint Picker and the Gateway-wide PreRouting policy, and with them
the MultipleInferencePoolsUnsupported and ConflictingPreRoutingPolicy
refusals.

routing defaults to InferencePool, so existing routers compile as
before. Model mode requires sectionName or hostnames, so its catch-all
rule cannot take over a shared Gateway. It refuses inputs it cannot
express (rules, defaultRoute, external backends, resolution: endpoint,
pickers, unmapped runtimes) and gates on the AgentgatewayModel CRD. It
never adopts objects it did not create, prunes the models of removed
backends, and cleans up the other mode's objects when routing changes.

Part of defilantech#2151 (phase 1).

Signed-off-by: Tanguille <91473554+Tanguille@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant