Skip to content
Open
78 changes: 78 additions & 0 deletions event-gateway/default-policies/openai-header-router.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: openai-header-router
version: v1.0.0
description: |
Selects a target LLM provider for each incoming OpenAI Chat Completions
request by inspecting a request header, then publishes the chosen
provider id into SharedContext.Metadata["selected_provider"].

This policy is a "setter" — its only job is to publish the selection.
Downstream consumer policies (the per-provider translators such as
openai-to-anthropic, openai-to-azure-openai, and openai-to-mistral)
read that key and own both the translation and the upstream-cluster
selection.

Selection algorithm:

1. The configured header is read from the request (case-insensitive).
2. Each entry in "mappings" is checked: if its "headerValue" matches the
incoming header value (case-insensitive), the entry's "provider" is
selected.
3. If the header is absent, empty, or no mapping matches, the configured
"defaultProvider" is selected.

The defaultProvider field is required so this policy always produces a
selection — there is no "pass through with no provider" mode.

parameters:
type: object
additionalProperties: false
properties:
headerName:
type: string
x-wso2-policy-advanced-param: false
description: |
Name of the request header to read for provider selection.
Comparison is case-insensitive.
default: x-provider
minLength: 1
defaultProvider:
type: string
x-wso2-policy-advanced-param: false
description: |
Provider id selected when the header is missing, empty, or does
not match any entry in "mappings". This must be a provider id that
a downstream translator is bound to.
minLength: 1
mappings:
type: array
x-wso2-policy-advanced-param: false
description: |
Mapping from incoming header values to provider ids. The first
matching entry wins.
items:
type: object
additionalProperties: false
properties:
headerValue:
type: string
description: |
Header value to match (case-insensitive, leading/trailing
whitespace trimmed).
minLength: 1
provider:
type: string
description: |
Provider id published to SharedContext.Metadata
["selected_provider"] when this entry matches.
minLength: 1
required:
- headerValue
- provider
minItems: 1
required:
- mappings
- defaultProvider

systemParameters:
type: object
properties: {}
84 changes: 84 additions & 0 deletions event-gateway/default-policies/openai-to-anthropic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: openai-to-anthropic
version: v1.0.0
description: |
Translates an incoming OpenAI Chat Completions request into the Anthropic
Messages API format and forwards it to an Anthropic-compatible upstream.

Request transformations:
- system/developer messages are lifted into the top-level "system" field.
- messages[] is converted to Anthropic role/content blocks.
- assistant tool_calls become tool_use content blocks; tool-role messages
are grouped into a single user message of tool_result blocks.
- tools[] / tool_choice are converted to the Anthropic equivalents.
- stop is mapped to stop_sequences; image_url parts to image blocks.
- The request path is rewritten to /v1/messages and the anthropic-version
header is set.

Response transformations:
- The Anthropic Messages response body is rewritten into the OpenAI
ChatCompletion shape (id, object, created, model, choices, usage).
- text content blocks become choice.message.content; tool_use blocks
become choice.message.tool_calls; stop_reason is mapped to
finish_reason; cache token counts are carried in usage
.prompt_tokens_details.
- Anthropic error envelopes are rewritten into OpenAI error envelopes
so clients see consistent error shapes regardless of provider.
- Streaming (Server-Sent Events) responses are passed through
untouched in this policy version; clients that need true streaming
should request non-streaming (omit "stream": true) until a streaming
variant ships.

Execution modes:

1. Routed (multi-provider proxies): set the "provider" parameter to the
provider id this translator is bound to. The policy only runs when an
upstream setter (e.g. openai-header-router) publishes the same id into
SharedContext.Metadata["selected_provider"]. Non-matching requests pass
through untouched.

2. Unconditional (single-provider proxies): omit "provider". The
translator runs on every request.

The upstream host and Anthropic API key must be configured on the
upstream LlmProvider — this policy does not inject credentials.

parameters:
type: object
additionalProperties: false
properties:
provider:
type: string
x-wso2-policy-advanced-param: false
description: |
Provider id this translator is bound to. When set, the policy runs
only if SharedContext.Metadata["selected_provider"] equals this
value. Omit for single-provider proxies.
minLength: 1
model:
type: string
x-wso2-policy-advanced-param: false
description: |
Anthropic model name used in the translated request (for example
claude-sonnet-4-20250514). Overrides the OpenAI "model" field.
minLength: 1
upstreamName:
type: string
x-wso2-policy-advanced-param: false
description: |
Name of the upstream cluster declared in the LlmProxy
additionalProviders list. When omitted, routing is left to whatever
the route's default upstream resolves to.
minLength: 1
anthropicVersion:
type: string
x-wso2-policy-advanced-param: true
description: |
Value of the anthropic-version request header sent upstream.
default: "2023-06-01"
minLength: 1
required:
- model

systemParameters:
type: object
properties: {}
78 changes: 78 additions & 0 deletions event-gateway/default-policies/openai-to-azure-openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: openai-to-azure-openai
version: v1.0.0
description: |
Translates an incoming OpenAI Chat Completions request into the Azure
OpenAI request shape and forwards it to an Azure-OpenAI-compatible
upstream.

Transformation:
- The request path is rewritten to
/openai/deployments/{deployment}/{pathSuffix}?api-version=<apiVersion>.
- The body passes through unchanged — Azure OpenAI accepts the OpenAI
request shape directly.
- The deployment id is taken from the "model" parameter when set,
otherwise from the request body's "model" field.

Execution modes:

1. Routed (multi-provider proxies): set the "provider" parameter to the
provider id this translator is bound to. The policy only runs when an
upstream setter (e.g. openai-header-router) publishes the same id into
SharedContext.Metadata["selected_provider"]. Non-matching requests
pass through untouched.

2. Unconditional (single-provider proxies): omit "provider". The
translator runs on every request.

The upstream host and Azure api-key must be configured on the upstream
LlmProvider — this policy does not inject credentials.

parameters:
type: object
additionalProperties: false
properties:
provider:
type: string
x-wso2-policy-advanced-param: false
description: |
Provider id this translator is bound to. When set, the policy runs
only if SharedContext.Metadata["selected_provider"] equals this
value. Omit for single-provider proxies.
minLength: 1
apiVersion:
type: string
x-wso2-policy-advanced-param: false
description: |
Azure OpenAI api-version query-string value (for example
2024-02-15-preview). Required because Azure rejects requests
without it.
minLength: 1
model:
type: string
x-wso2-policy-advanced-param: false
description: |
Azure deployment id used in the rewritten path. When omitted, the
request body's "model" field is used as the deployment id.
minLength: 1
upstreamName:
type: string
x-wso2-policy-advanced-param: false
description: |
Name of the upstream cluster declared in the LlmProxy
additionalProviders list. When omitted, routing is left to whatever
the route's default upstream resolves to.
minLength: 1
pathSuffix:
type: string
x-wso2-policy-advanced-param: true
description: |
Endpoint suffix appended after the deployment segment in the
rewritten path. Defaults to /chat/completions.
default: /chat/completions
minLength: 1
required:
- apiVersion

systemParameters:
type: object
properties: {}
86 changes: 86 additions & 0 deletions event-gateway/default-policies/openai-to-gemini.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: openai-to-gemini
version: v1.0.0
description: |
Translates an incoming OpenAI Chat Completions request into the Gemini
generateContent API format and forwards it to a Gemini-compatible
upstream.

Request transformations:
- system/developer messages are lifted into the top-level
"systemInstruction" field.
- messages[] is converted to Gemini contents[] with role/parts blocks;
assistant tool_calls become functionCall parts and tool-role messages
become functionResponse parts.
- tools[] are converted to functionDeclarations and tool_choice to a
functionCallingConfig.
- sampling fields (temperature, top_p, max_tokens, stop, etc.) are mapped
into generationConfig; image_url parts become inlineData/fileData.
- The request path is rewritten to
/{apiVersion}/models/{model}:generateContent.

Response transformations:
- The Gemini generateContent response body is rewritten into the OpenAI
ChatCompletion shape (id, object, created, model, choices, usage).
- text parts become choice.message.content; functionCall parts become
choice.message.tool_calls; finishReason is mapped to finish_reason and
usageMetadata token counts are carried in usage.
- Streaming (Server-Sent Events) responses are passed through untouched
in this policy version; clients that need true streaming should request
non-streaming (omit "stream": true) until a streaming variant ships.

Execution modes:

1. Routed (multi-provider proxies): set the "provider" parameter to the
provider id this translator is bound to. The policy only runs when an
upstream setter (e.g. openai-header-router) publishes the same id into
SharedContext.Metadata["selected_provider"]. Non-matching requests
pass through untouched.

2. Unconditional (single-provider proxies): omit "provider". The
translator runs on every request.

The upstream host and Gemini API key must be configured on the upstream
LlmProvider — this policy does not inject credentials.

parameters:
type: object
additionalProperties: false
properties:
provider:
type: string
x-wso2-policy-advanced-param: false
description: |
Provider id this translator is bound to. When set, the policy runs
only if SharedContext.Metadata["selected_provider"] equals this
value. Omit for single-provider proxies.
minLength: 1
model:
type: string
x-wso2-policy-advanced-param: false
description: |
Gemini model name used in the translated request (for example
gemini-2.5-pro). Overrides the OpenAI "model" field and is used in
the rewritten path.
minLength: 1
upstreamName:
type: string
x-wso2-policy-advanced-param: false
description: |
Name of the upstream cluster declared in the LlmProxy
additionalProviders list. When omitted, routing is left to whatever
the route's default upstream resolves to.
minLength: 1
apiVersion:
type: string
x-wso2-policy-advanced-param: true
description: |
Gemini API version segment used in the rewritten path
(/{apiVersion}/models/{model}:generateContent).
default: "v1beta"
minLength: 1
required:
- model

systemParameters:
type: object
properties: {}
61 changes: 61 additions & 0 deletions event-gateway/default-policies/openai-to-mistral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: openai-to-mistral
version: v1.0.0
description: |
Translates an incoming OpenAI Chat Completions request into the format
expected by Mistral AI's chat completions endpoint and forwards it to a
Mistral-compatible upstream.

Mistral's chat completions API is largely OpenAI-compatible, so the
translation is small in scope:
- The "model" field is overridden with the configured Mistral model.
- OpenAI request fields that Mistral does not accept (logprobs, n,
service_tier, store, metadata, user, etc.) are stripped.
- The request path is rewritten to /v1/chat/completions.

Execution modes:

1. Routed (multi-provider proxies): set the "provider" parameter to the
provider id this translator is bound to. The policy only runs when an
upstream setter (e.g. openai-header-router) publishes the same id into
SharedContext.Metadata["selected_provider"]. Non-matching requests
pass through untouched.

2. Unconditional (single-provider proxies): omit "provider". The
translator runs on every request.

The upstream host and Mistral API key must be configured on the upstream
LlmProvider — this policy does not inject credentials.

parameters:
type: object
additionalProperties: false
properties:
provider:
type: string
x-wso2-policy-advanced-param: false
description: |
Provider id this translator is bound to. When set, the policy runs
only if SharedContext.Metadata["selected_provider"] equals this
value. Omit for single-provider proxies.
minLength: 1
model:
type: string
x-wso2-policy-advanced-param: false
description: |
Mistral model name used in the translated request (for example
mistral-large-latest). Overrides the OpenAI "model" field.
minLength: 1
upstreamName:
type: string
x-wso2-policy-advanced-param: false
description: |
Name of the upstream cluster declared in the LlmProxy
additionalProviders list. When omitted, routing is left to whatever
the route's default upstream resolves to.
minLength: 1
required:
- model

systemParameters:
type: object
properties: {}
Loading