Skip to content

[AI Gateway] Add multi-provider routing for LLM proxies#2486

Merged
Arshardh merged 3 commits into
wso2:multi-provider-routingfrom
Aakashwije:feature/multi-provider-routing-clean
Jul 10, 2026
Merged

[AI Gateway] Add multi-provider routing for LLM proxies#2486
Arshardh merged 3 commits into
wso2:multi-provider-routingfrom
Aakashwije:feature/multi-provider-routing-clean

Conversation

@Aakashwije

@Aakashwije Aakashwije commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Purpose

Before this change, using more than one LLM vendor from a single app meant standing up a separate proxy and endpoint per vendor, and formatting requests differently for each. There was no way to route one OpenAI-shaped endpoint to multiple upstreams, and translator policies had to be declared separately from the provider they targeted - duplicating the provider id by hand and keeping it in sync.

Relates to #2490

Goals

  • Let a single LLM proxy fan out to multiple LLM providers behind one endpoint, with the target chosen per-request by a header.
  • Move each vendor translator inline onto the provider it belongs to (additionalProviders[].transformer), so provider auth and its translator live together and the provider id is injected automatically.
  • Keep the client contract unchanged: requests and responses stay OpenAI-shaped regardless of the selected vendor.
  • Reject invalid transformer config at deploy time, not request time.

Approach

A proxy declares a primary provider plus a list of additionalProviders, each with its own upstream auth and an inline transformer. The openai-header-router policy reads the x-provider header and writes the choice into metadata["selected_provider"]. The controller injects each provider's translator and upstream-auth as conditional policies gated on selected_provider == <provider>, so only the selected provider's translator and key are applied. Each additional provider is exposed as a named upstream for loopback routing.

Client (OpenAI-shaped request)
    │  Request + X-Provider
    ▼
LLM Proxy
    1. api-key-auth (consumer)
    2. openai-header-router  → metadata.selected_provider
    3. translator (openai-to-x)
    4. set-headers (loopback auth)
    │  Loopback
    ▼
Selected LLM Provider
    1. api-key-auth (validates the loopback key)
    2. upstream.auth (config) → injects vendor key
    │  HTTPS
    ▼
External LLM  (OpenAI · Anthropic · Azure OpenAI · Mistral · Gemini)

New config reads top-to-bottom as "provider + how to talk to it":

additionalProviders:
  - id: anthropic-provider
    auth: { type: api-key, header: X-API-Key, value: ... }
    transformer:
      type: openai-to-anthropic
      version: v1
      params:
        model: claude-sonnet-4-5-20250929   # id injected automatically

Implemented across three modules:

  • gateway-controlleradditionalProviders + inline transformer in the management schema and validator; transformProxy exposes each additional provider as a named upstream and injects auth/translator policies gated on a selected_provider execution condition.
  • platform-apiadditionalProviders across openapi, model, dto and service, carried into the deployment artifact sent to the gateway.
  • kubernetes-operatoradditionalProviders on the LlmProxy CRD (types, deepcopy, regenerated CRD manifests) and controller payload.

User stories

  • As an app developer, I can call one endpoint and switch LLM vendors with a single header, without changing my request format or my code.
  • As a platform admin, I can attach multiple providers to one proxy, declare each vendor's translator right next to its auth, and have invalid config rejected when I deploy it.
  • As a security-conscious operator, my app holds zero vendor credentials — vendor keys live only in provider config and are injected at the gateway.

Documentation

N/A for this PR. The example YAMLs under gateway/examples/ (openai-multi-provider-proxy.yaml and per-provider configs) serve as usage documentation. Product-doc updates, if any, will accompany the follow-up translator-policies PR.

Automation tests

Unit tests

  • New tests in gateway-controller/pkg/utils cover conditional upstream-auth injection and conditional transformer injection — correct selected_provider execution condition, injected id param, and per-provider isolation.
  • Full unit suites pass across gateway-controller, platform-api, and kubernetes-operator; no regressions in existing tests.

Integration tests

  • Verified end-to-end on a local gateway stack: 5 providers (OpenAI, Anthropic, Azure OpenAI, Mistral, Gemini) each route correctly by x-provider header and return their own vendor model.
  • Consumer auth returns 401 on wrong/missing key; deploy-time validation returns 400 for a transformer missing type/version.
  • Concurrency burst (100 requests across 5 providers, 10 concurrent) showed zero cross-provider routing.
  • The godog llm-proxies.feature scenarios land with the follow-up translator-policies PR (they depend on those policy binaries).

Security checks

  • Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes
  • Ran FindSecurityBugs plugin and verified report? N/A - FindSecurityBugs is a Java/SpotBugs tool; this change is Go. go vet was run clean.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes - staged diff scanned; only REPLACE_WITH_* placeholders and non-secret loopback identifiers. Real keys kept in a gitignored local path.

Samples

  • gateway/examples/openai-multi-provider-proxy.yaml - one proxy fanning out to multiple providers with inline transformers.
  • Per-provider configs: openai-provider.yaml, anthropic-provider.yaml, azure-openai-provider.yaml, mistral-provider.yaml, gemini-provider.yaml.

Related PRs

Follow-up (separate PR): translator policy implementations (openai-to-anthropic / azure-openai / mistral / gemini, openai-header-router), their build.yaml / build-manifest.yaml wiring, and the llm-proxies.feature integration test.

Test environment

  • Go 1.26.2 (matches gateway-controller/go.mod)
  • Docker Desktop — gateway-runtime, gateway-builder, gateway-controller images (tag 1.2.0-M2-SNAPSHOT)
  • macOS (darwin)
  • SQLite (controller local store)
866034cc-5297-4283-8222-f24b0649f220

Introduce additionalProviders on LLM proxies so one proxy can fan out to
multiple LLM upstreams, with per-provider conditional upstream auth and inline
request/response translators gated on the selected provider.

- gateway-controller: additionalProviders + inline transformer in the
  management API schema and validator; transformProxy exposes each additional
  provider as a named upstream and injects auth/translator policies with
  selected_provider execution conditions
- platform-api: additionalProviders across openapi, model, dto and service,
  and carried into the deployment artifact sent to the gateway
- kubernetes-operator: additionalProviders on the LlmProxy CRD (types,
  deepcopy, CRD manifests) and controller payload
- examples: multi-provider proxy and per-provider sample configs

Translator policy implementations, their build config and the integration
feature test follow in a separate PR.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 20cd9935-bc9b-435a-b6b7-44a50583b052

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds additionalProviders support to LLM proxies, allowing a single proxy to route requests to multiple upstream LLM providers based on request metadata. Changes span OpenAPI/CRD schemas, gateway transformer/validator logic, Kubernetes operator controllers, platform-api service layers, and new example configurations.

Changes

Multi-provider LLM proxy support

Layer / File(s) Summary
API and OpenAPI schemas
gateway/gateway-controller/api/management-openapi.yaml, gateway/gateway-controller/pkg/api/management/generated.go, platform-api/api/generated.go, platform-api/resources/openapi.yaml
Adds LLMProxyAdditionalProvider and LLMProxyTransformer schemas/types and additionalProviders property to proxy config, plus regenerated Go models and swagger spec.
Proxy validation
gateway/gateway-controller/pkg/config/llm_validator.go
Validates provider/additionalProviders auth (api-key header/value) and transformer configuration (type/version), with duplicate upstream-name detection.
Transformer: multi-upstream and conditional policies
gateway/gateway-controller/pkg/utils/llm_transformer.go, gateway/gateway-controller/pkg/utils/llm_transformer_multiprovider_test.go
Builds per-provider upstream definitions and conditional auth/translator policies gated by selected_provider request metadata, with new unit tests.
Kubernetes operator CRD/types
kubernetes/gateway-operator/api/v1alpha1/llmproxy_types.go, .../zz_generated.deepcopy.go, kubernetes/gateway-operator/config/crd/bases/*, kubernetes/helm/operator-helm-chart/crds/*
Adds LLMProxyAdditionalProvider Go type, deepcopy methods, and CRD schema with value/valueFrom auth validation.
Operator controller auth resolution
kubernetes/gateway-operator/internal/controller/llmproxy_controller.go, management_upstream_auth_payload.go, management_valuefrom_enqueue.go, management_valuefrom_fingerprint.go, llmproxy_controller_test.go
Resolves and flattens additionalProviders[].auth credentials (including secret valueFrom), tracks secret references, and updates fingerprinting.
Platform-api DTO/model/service
platform-api/internal/dto/llm_deployment.go, platform-api/internal/model/llm.go, platform-api/internal/service/llm.go, llm_deployment.go
Adds LLMProxyDeploymentAdditionalProvider DTO and wires AdditionalProviders through Create/Update/mapping and deployment YAML generation.
Example configurations
gateway/examples/*.yaml
Adds standalone provider/proxy examples (Anthropic, Azure OpenAI, Gemini, Mistral, OpenAI) and a combined multi-provider proxy with header-based routing.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Gateway
  participant HeaderRouter as openai-header-router
  participant AuthPolicy as Upstream Auth Policy
  participant Translator as Translator Policy
  participant Upstream as Selected Provider

  Client->>Gateway: POST /chat/completions (x-provider: anthropic)
  Gateway->>HeaderRouter: resolve x-provider header
  HeaderRouter->>Gateway: set selected_provider metadata
  Gateway->>AuthPolicy: check ExecutionCondition(selected_provider)
  AuthPolicy->>Translator: inject provider API key, run translator if defined
  Translator->>Upstream: forward transformed request
  Upstream-->>Client: response
Loading
sequenceDiagram
  participant Controller as llmProxyAdapter.Deploy
  participant K8sAPI
  participant Secret
  participant Payload as Deployment Payload

  Controller->>Controller: convert LlmProxy spec to JSON map
  Controller->>K8sAPI: resolve provider.auth (valueFrom)
  K8sAPI->>Secret: fetch secret key
  Secret-->>Controller: resolved credential
  Controller->>Payload: flatten provider auth value
  loop each additionalProviders[i]
    Controller->>K8sAPI: resolve additionalProviders[i].auth (valueFrom)
    K8sAPI->>Secret: fetch secret key
    Secret-->>Controller: resolved credential
    Controller->>Payload: flattenAdditionalProviderAuthCredentialValue
  end
  Controller->>K8sAPI: POST deployment payload
Loading

Possibly related PRs

  • wso2/api-platform#521: Introduced the original LLM proxy transformation and validation logic in llm_transformer.go and llm_validator.go that this PR extends with additionalProviders handling.

Suggested reviewers: Krishanx92, RakhithaRR, Tharsanan1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: multi-provider routing for LLM proxies.
Description check ✅ Passed The description covers all required sections and is detailed, with acceptable N/A placeholders where no extra docs or tests were needed.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Aakashwije Aakashwije changed the title feat(llm): add multi-provider routing for LLM proxies [AI Gateway] Add multi-provider routing for LLM proxies Jul 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (6)
kubernetes/gateway-operator/internal/controller/llmproxy_controller.go (1)

167-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated resolve/nil-check/flatten pattern between provider and additionalProviders.

The provider.Auth block (Lines 167-178) and the AdditionalProviders loop (Lines 179-194) repeat the same resolve → nil-check → flatten sequence with only the field path/flatten target differing. Consider extracting a small helper, e.g. resolveAndFlattenUpstreamAuth(ctx, k8sClient, ns, auth, fieldPath, flattenFn), to reduce duplication and centralize the nil-guard error message format.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kubernetes/gateway-operator/internal/controller/llmproxy_controller.go`
around lines 167 - 194, The provider.Auth handling and the AdditionalProviders
loop in llmproxy_controller.go repeat the same resolve, nil-check, and flatten
flow. Extract that shared logic into a small helper (for example,
resolveAndFlattenUpstreamAuth) that takes the auth object, field path, and a
flatten callback so both the main provider and additional providers use the same
code path. Preserve the existing error handling and nil-guard messages by having
the helper call resolveLLMProviderUpstreamAuth and then either
flattenUpstreamAuthCredentialValue or
flattenAdditionalProviderAuthCredentialValue based on the supplied target.
kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload.go (1)

33-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Near-duplicate logic between the two flatten helpers.

flattenUpstreamAuthCredentialValue and flattenAdditionalProviderAuthCredentialValue share the same "assert object → find auth → set value" shape, differing only in how the parent is located (map key vs. indexed array element). Consider factoring out a shared setAuthValue(parent map[string]interface{}, plaintext string) error helper to avoid maintaining two copies of this logic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload.go`
around lines 33 - 64, The two flatten helpers duplicate the same “get parent
auth object and set value” logic, so refactor to reduce maintenance risk. Keep
the parent lookup differences in flattenUpstreamAuthCredentialValue and
flattenAdditionalProviderAuthCredentialValue, but extract the shared auth update
into a helper such as setAuthValue that takes the parent map and plaintext.
Update both helpers to call the shared helper after their respective type/range
checks, preserving the existing error messages for spec.%s and
spec.additionalProviders[%d] paths.
gateway/gateway-controller/pkg/config/llm_validator.go (1)

649-694: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate auth-validation logic vs. validateUpstreamWithAuth.

validateLLMUpstreamAuth reimplements the same three checks already present in validateUpstreamWithAuth (Lines 454-485): type required, type must be api-key, header/value required when api-key. The two operate on structurally-identical but distinct generated types (LLMUpstreamAuth vs. the inline upstream-auth object), so a straightforward fix is to extract a primitive-based helper (e.g., authType string, header, value *string) that both call sites can delegate to.

♻️ Suggested extraction
-func (v *LLMValidator) validateLLMUpstreamAuth(fieldPrefix string, auth *api.LLMUpstreamAuth) []ValidationError {
-	var errors []ValidationError
-	if auth.Type == "" {
-		...
-	}
-	...
-	return errors
-}
+func (v *LLMValidator) validateAuthFields(fieldPrefix string, authType string, header, value *string) []ValidationError {
+	var errors []ValidationError
+	if authType == "" {
+		errors = append(errors, ValidationError{Field: fieldPrefix + ".type", Message: "Auth type is required"})
+	} else if authType != "api-key" {
+		errors = append(errors, ValidationError{Field: fieldPrefix + ".type", Message: "Auth type must be 'api-key'"})
+	}
+	if authType == "api-key" {
+		if header == nil || *header == "" {
+			errors = append(errors, ValidationError{Field: fieldPrefix + ".header", Message: "Auth header is required when api-key auth type is set"})
+		}
+		if value == nil || *value == "" {
+			errors = append(errors, ValidationError{Field: fieldPrefix + ".value", Message: "Auth value is required when api-key auth type is set"})
+		}
+	}
+	return errors
+}
+
+func (v *LLMValidator) validateLLMUpstreamAuth(fieldPrefix string, auth *api.LLMUpstreamAuth) []ValidationError {
+	return v.validateAuthFields(fieldPrefix, string(auth.Type), auth.Header, auth.Value)
+}

Then validateUpstreamWithAuth (Lines 454-485) can delegate to validateAuthFields too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/gateway-controller/pkg/config/llm_validator.go` around lines 649 -
694, `validateLLMUpstreamAuth` is duplicating the same auth checks already
implemented in `validateUpstreamWithAuth`. Extract the shared validation into a
small helper that works on primitive inputs (for example, auth type plus
header/value pointers or strings) and have both `validateLLMUpstreamAuth` and
`validateUpstreamWithAuth` delegate to it. Keep the existing field-specific
error paths/messages in each caller while removing the repeated
type/header/value logic.
gateway/examples/openai-multi-provider-proxy.yaml (1)

76-104: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New examples use the deprecated policies: field.

This is a brand-new example file, but it (and the sibling mistral-openai-proxy.yaml, mistral-provider.yaml, openai-provider.yaml) uses the deprecated top-level policies: list rather than operationPolicies:. Since LLMPolicy/LLMPolicyPath and OperationPolicy/OperationPolicyPath have the same shape (name/version/paths with path/methods/params), this is essentially a key rename with no behavior change — worth doing in fresh docs to avoid teaching the deprecated pattern.

♻️ Suggested rename
-  policies:
+  operationPolicies:
     - name: api-key-auth
       version: v1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/examples/openai-multi-provider-proxy.yaml` around lines 76 - 104, The
example configuration still uses the deprecated top-level policies list, so
update this and the related example YAMLs to use operationPolicies instead. This
is a straight field rename with the same structure, so keep each policy entry
and its nested paths/methods/params unchanged while moving them under
operationPolicies. Make sure the openai-header-router and api-key-auth entries
remain functionally identical after the rename.
gateway/gateway-controller/pkg/utils/llm_transformer.go (1)

162-165: 📐 Maintainability & Code Quality | 🔵 Trivial

Duplicate upstream-name resolution logic.

The ap.Id/ap.As fallback logic is repeated verbatim in two loops. Consider extracting a small helper, e.g. additionalProviderUpstreamName(ap api.LLMProxyAdditionalProvider) string.

Also applies to: 244-247

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/gateway-controller/pkg/utils/llm_transformer.go` around lines 162 -
165, The ap.Id/ap.As fallback logic is duplicated in both loops inside
llm_transformer.go, so extract it into a small helper named something like
additionalProviderUpstreamName that takes api.LLMProxyAdditionalProvider and
returns the resolved upstream name. Update both call sites in the transformer
code to use that helper instead of repeating the nil/empty check and assignment
logic.
gateway/gateway-controller/pkg/utils/llm_transformer_multiprovider_test.go (1)

119-121: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider asserting Url/BasePath on the generated UpstreamDefinition.

Only Name is checked here. Given the Url/BasePath split question raised in llm_transformer.go, asserting the full upstream shape would catch regressions in how the provider context path is represented.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/gateway-controller/pkg/utils/llm_transformer_multiprovider_test.go`
around lines 119 - 121, The test for the generated UpstreamDefinition only
verifies Name, so it can miss regressions in how provider routing is
represented. Update the assertion in the multiprovider transformer test around
result.Spec.UpstreamDefinitions to also validate the generated Url and/or
BasePath values, using the same upstream object created by llm_transformer.go so
the provider context path split is covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@gateway/examples/openai-multi-provider-proxy.yaml`:
- Around line 76-104: The example configuration still uses the deprecated
top-level policies list, so update this and the related example YAMLs to use
operationPolicies instead. This is a straight field rename with the same
structure, so keep each policy entry and its nested paths/methods/params
unchanged while moving them under operationPolicies. Make sure the
openai-header-router and api-key-auth entries remain functionally identical
after the rename.

In `@gateway/gateway-controller/pkg/config/llm_validator.go`:
- Around line 649-694: `validateLLMUpstreamAuth` is duplicating the same auth
checks already implemented in `validateUpstreamWithAuth`. Extract the shared
validation into a small helper that works on primitive inputs (for example, auth
type plus header/value pointers or strings) and have both
`validateLLMUpstreamAuth` and `validateUpstreamWithAuth` delegate to it. Keep
the existing field-specific error paths/messages in each caller while removing
the repeated type/header/value logic.

In `@gateway/gateway-controller/pkg/utils/llm_transformer_multiprovider_test.go`:
- Around line 119-121: The test for the generated UpstreamDefinition only
verifies Name, so it can miss regressions in how provider routing is
represented. Update the assertion in the multiprovider transformer test around
result.Spec.UpstreamDefinitions to also validate the generated Url and/or
BasePath values, using the same upstream object created by llm_transformer.go so
the provider context path split is covered.

In `@gateway/gateway-controller/pkg/utils/llm_transformer.go`:
- Around line 162-165: The ap.Id/ap.As fallback logic is duplicated in both
loops inside llm_transformer.go, so extract it into a small helper named
something like additionalProviderUpstreamName that takes
api.LLMProxyAdditionalProvider and returns the resolved upstream name. Update
both call sites in the transformer code to use that helper instead of repeating
the nil/empty check and assignment logic.

In `@kubernetes/gateway-operator/internal/controller/llmproxy_controller.go`:
- Around line 167-194: The provider.Auth handling and the AdditionalProviders
loop in llmproxy_controller.go repeat the same resolve, nil-check, and flatten
flow. Extract that shared logic into a small helper (for example,
resolveAndFlattenUpstreamAuth) that takes the auth object, field path, and a
flatten callback so both the main provider and additional providers use the same
code path. Preserve the existing error handling and nil-guard messages by having
the helper call resolveLLMProviderUpstreamAuth and then either
flattenUpstreamAuthCredentialValue or
flattenAdditionalProviderAuthCredentialValue based on the supplied target.

In
`@kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload.go`:
- Around line 33-64: The two flatten helpers duplicate the same “get parent auth
object and set value” logic, so refactor to reduce maintenance risk. Keep the
parent lookup differences in flattenUpstreamAuthCredentialValue and
flattenAdditionalProviderAuthCredentialValue, but extract the shared auth update
into a helper such as setAuthValue that takes the parent map and plaintext.
Update both helpers to call the shared helper after their respective type/range
checks, preserving the existing error messages for spec.%s and
spec.additionalProviders[%d] paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: db63d46e-d73e-4d99-b795-7d4b119c46af

📥 Commits

Reviewing files that changed from the base of the PR and between d99d49a and 9288a1e.

📒 Files selected for processing (29)
  • gateway/examples/anthropic-openai-proxy.yaml
  • gateway/examples/anthropic-provider.yaml
  • gateway/examples/azure-openai-provider.yaml
  • gateway/examples/azure-openai-proxy.yaml
  • gateway/examples/gemini-provider.yaml
  • gateway/examples/mistral-openai-proxy.yaml
  • gateway/examples/mistral-provider.yaml
  • gateway/examples/openai-multi-provider-proxy.yaml
  • gateway/examples/openai-provider.yaml
  • gateway/gateway-controller/api/management-openapi.yaml
  • gateway/gateway-controller/pkg/api/management/generated.go
  • gateway/gateway-controller/pkg/config/llm_validator.go
  • gateway/gateway-controller/pkg/utils/llm_transformer.go
  • gateway/gateway-controller/pkg/utils/llm_transformer_multiprovider_test.go
  • kubernetes/gateway-operator/api/v1alpha1/llmproxy_types.go
  • kubernetes/gateway-operator/api/v1alpha1/zz_generated.deepcopy.go
  • kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproxies.yaml
  • kubernetes/gateway-operator/internal/controller/llmproxy_controller.go
  • kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go
  • kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload.go
  • kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go
  • kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go
  • kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml
  • platform-api/api/generated.go
  • platform-api/internal/dto/llm_deployment.go
  • platform-api/internal/model/llm.go
  • platform-api/internal/service/llm.go
  • platform-api/internal/service/llm_deployment.go
  • platform-api/resources/openapi.yaml

@Arshardh
Arshardh changed the base branch from main to multi-provider-routing July 8, 2026 08:59
Comment on lines +5854 to +5862
as:
type: string
description: >
Logical upstream name used by policies to select this provider. Must
be unique within the proxy. Defaults to `id` when omitted.
pattern: '^[a-zA-Z0-9\-_]+$'
minLength: 1
maxLength: 100
example: anthropic-upstream

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Arshardh can you remember why we need this as?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed to have an optional alias just in case the provider names will not be readable enough to configure in a routing policy

Comment thread gateway/gateway-controller/api/management-openapi.yaml Outdated
Comment thread gateway/examples/anthropic-openai-proxy.yaml
Comment thread gateway/examples/anthropic-provider.yaml Outdated
Comment thread gateway/examples/openai-multi-provider-proxy.yaml
Comment thread platform-api/resources/openapi.yaml
Message: "spec.provider.id must consist of lowercase alphanumeric characters, hyphens, or dots, and must start and end with an alphanumeric character",
})
}
if spec.Provider.Auth != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Arshardh

Do we need to make provider auth required?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, we don't need to

Aakashwije and others added 2 commits July 10, 2026 14:19
edit upstream to LLM Provider

Co-authored-by: Renuka Piyumal Fernando <renukapiyumal@gmail.com>
- examples: add Apache license headers to the nine new LLM provider and
  proxy samples, matching the short 2026 form used by recent examples
- examples: remove the loopback ApiKey documents and their hardcoded key
  material from the five provider samples; point at api-key.yaml instead
  and use REPLACE_WITH_... placeholders for the proxies' provider.auth
- examples: document the optional `as` alias on openai-multi-provider-proxy
- platform-api: add LLMProxyTransformer and the transformer property to
  LLMProxyAdditionalProvider, mirroring the gateway-controller schema, and
  carry it through the model, dto, service mappers and deployment artifact
- platform-api: align the `as` description with the gateway-controller spec
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.

3 participants