zuplo 7.8.23 → 7.8.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/docs/ai-gateway/azure-ai.mdx +6 -6
  2. package/docs/ai-gateway/bedrock-mantle.mdx +4 -4
  3. package/docs/ai-gateway/bedrock-runtime.mdx +9 -9
  4. package/docs/ai-gateway/integrations/ai-sdk.mdx +2 -2
  5. package/docs/ai-gateway/integrations/claude-code.mdx +3 -3
  6. package/docs/ai-gateway/integrations/claude-desktop.mdx +2 -2
  7. package/docs/ai-gateway/integrations/codex.mdx +4 -4
  8. package/docs/ai-gateway/integrations/github-copilot.mdx +4 -4
  9. package/docs/ai-gateway/integrations/goose.mdx +3 -3
  10. package/docs/ai-gateway/integrations/langchain.mdx +3 -3
  11. package/docs/ai-gateway/integrations/openai.mdx +3 -3
  12. package/docs/ai-gateway/universal-api.mdx +3 -3
  13. package/docs/ai-gateway/usage-limits.mdx +1 -1
  14. package/docs/ai-gateway/vertex-ai.mdx +1 -1
  15. package/docs/dedicated/akamai/ai-powered-applications.mdx +3 -3
  16. package/docs/policies/_index.md +11 -10
  17. package/docs/policies/{akamai-ai-firewall-v2-inbound → ai-gateway-akamai-firewall-inbound}/doc.md +2 -2
  18. package/docs/policies/{akamai-ai-firewall-v2-inbound → ai-gateway-akamai-firewall-inbound}/schema.json +5 -6
  19. package/docs/policies/{ai-gateway-auth-v2-inbound → ai-gateway-auth-inbound}/doc.md +4 -4
  20. package/docs/policies/{ai-gateway-auth-v2-inbound → ai-gateway-auth-inbound}/schema.json +5 -6
  21. package/docs/policies/{ai-gateway-configuration-executor-v2-inbound → ai-gateway-configuration-executor-inbound}/doc.md +16 -16
  22. package/docs/policies/{ai-gateway-configuration-executor-v2-inbound → ai-gateway-configuration-executor-inbound}/schema.json +5 -6
  23. package/docs/policies/{ai-gateway-configuration-loader-v2-inbound → ai-gateway-configuration-loader-inbound}/doc.md +4 -4
  24. package/docs/policies/{ai-gateway-configuration-loader-v2-inbound → ai-gateway-configuration-loader-inbound}/schema.json +5 -6
  25. package/docs/policies/ai-gateway-dlp-inbound/schema.json +0 -1
  26. package/docs/policies/{ai-gateway-fallback-model-v2-inbound → ai-gateway-fallback-model-inbound}/doc.md +2 -2
  27. package/docs/policies/{ai-gateway-fallback-model-v2-inbound → ai-gateway-fallback-model-inbound}/schema.json +5 -6
  28. package/docs/policies/{galileo-tracing-v2-inbound → ai-gateway-galileo-tracing-inbound}/doc.md +2 -2
  29. package/docs/policies/{galileo-tracing-v2-inbound → ai-gateway-galileo-tracing-inbound}/schema.json +5 -6
  30. package/docs/policies/ai-gateway-internal-only-inbound/schema.json +0 -1
  31. package/docs/policies/{ai-gateway-metering-v2-inbound → ai-gateway-metering-inbound}/schema.json +5 -6
  32. package/docs/policies/{ai-gateway-model-filtering-v2-inbound → ai-gateway-model-filtering-inbound}/doc.md +6 -4
  33. package/docs/policies/{ai-gateway-model-filtering-v2-inbound → ai-gateway-model-filtering-inbound}/schema.json +5 -6
  34. package/docs/policies/ai-gateway-model-override-inbound/doc.md +154 -0
  35. package/docs/policies/ai-gateway-model-override-inbound/intro.md +5 -0
  36. package/docs/policies/ai-gateway-model-override-inbound/schema.json +126 -0
  37. package/docs/policies/{comet-opik-tracing-v2-inbound → ai-gateway-opik-tracing-inbound}/doc.md +2 -2
  38. package/docs/policies/{comet-opik-tracing-v2-inbound → ai-gateway-opik-tracing-inbound}/schema.json +5 -6
  39. package/docs/policies/{ai-gateway-semantic-cache-v2-inbound → ai-gateway-semantic-cache-inbound}/schema.json +4 -5
  40. package/docs/policies/ai-gateway-smart-router-inbound/doc.md +2 -2
  41. package/docs/policies/ai-gateway-smart-router-inbound/schema.json +0 -1
  42. package/package.json +5 -5
  43. /package/docs/policies/{akamai-ai-firewall-v2-inbound → ai-gateway-akamai-firewall-inbound}/intro.md +0 -0
  44. /package/docs/policies/{ai-gateway-auth-v2-inbound → ai-gateway-auth-inbound}/intro.md +0 -0
  45. /package/docs/policies/{ai-gateway-configuration-executor-v2-inbound → ai-gateway-configuration-executor-inbound}/intro.md +0 -0
  46. /package/docs/policies/{ai-gateway-configuration-loader-v2-inbound → ai-gateway-configuration-loader-inbound}/intro.md +0 -0
  47. /package/docs/policies/{ai-gateway-fallback-model-v2-inbound → ai-gateway-fallback-model-inbound}/intro.md +0 -0
  48. /package/docs/policies/{galileo-tracing-v2-inbound → ai-gateway-galileo-tracing-inbound}/intro.md +0 -0
  49. /package/docs/policies/{ai-gateway-metering-v2-inbound → ai-gateway-metering-inbound}/doc.md +0 -0
  50. /package/docs/policies/{ai-gateway-metering-v2-inbound → ai-gateway-metering-inbound}/intro.md +0 -0
  51. /package/docs/policies/{ai-gateway-model-filtering-v2-inbound → ai-gateway-model-filtering-inbound}/intro.md +0 -0
  52. /package/docs/policies/{comet-opik-tracing-v2-inbound → ai-gateway-opik-tracing-inbound}/intro.md +0 -0
  53. /package/docs/policies/{ai-gateway-semantic-cache-v2-inbound → ai-gateway-semantic-cache-inbound}/doc.md +0 -0
  54. /package/docs/policies/{ai-gateway-semantic-cache-v2-inbound → ai-gateway-semantic-cache-inbound}/intro.md +0 -0
@@ -23,9 +23,9 @@ Add the loader, the executor, and every policy an application may select to
23
23
  "policies": [
24
24
  {
25
25
  "name": "ai-gateway-configuration-loader-v2-inbound",
26
- "policyType": "ai-gateway-configuration-loader-v2",
26
+ "policyType": "ai-gateway-configuration-loader",
27
27
  "handler": {
28
- "export": "AIGatewayConfigurationLoaderV2InboundPolicy",
28
+ "export": "AIGatewayConfigurationLoaderInboundPolicy",
29
29
  "module": "$import(@zuplo/runtime)",
30
30
  "options": {
31
31
  "cacheTtlSeconds": 60
@@ -34,9 +34,9 @@ Add the loader, the executor, and every policy an application may select to
34
34
  },
35
35
  {
36
36
  "name": "ai-gateway-configuration-executor-v2-inbound",
37
- "policyType": "ai-gateway-configuration-executor-v2",
37
+ "policyType": "ai-gateway-configuration-executor",
38
38
  "handler": {
39
- "export": "AIGatewayConfigurationExecutorV2InboundPolicy",
39
+ "export": "AIGatewayConfigurationExecutorInboundPolicy",
40
40
  "module": "$import(@zuplo/runtime)",
41
41
  "options": {
42
42
  "cacheTtlSeconds": 60
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft-07/schema",
3
- "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-configuration-loader-v2-inbound.json",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-configuration-loader-inbound.json",
4
4
  "type": "object",
5
5
  "title": "AI Gateway Configuration Loader",
6
6
  "isDeprecated": false,
@@ -10,7 +10,7 @@
10
10
  "isBeta": false,
11
11
  "isHidden": false,
12
12
  "requiresAI": true,
13
- "policyType": "ai-gateway-configuration-loader-v2",
13
+ "policyType": "ai-gateway-configuration-loader",
14
14
  "products": ["ai-gateway"],
15
15
  "description": "Loads the AI Gateway app configuration for the request into the request-scoped channel and does nothing else.\n\nPlace this policy on AI Gateway routes before `ai-gateway-configuration-executor-v2-inbound` when you want configuration loading separated from chain execution. When `ai-gateway-auth-v2-inbound` already populated the channel, this policy reuses it. Otherwise it loads the configuration with the route's `app_id` path parameter.\n\nIf this policy is omitted, the configuration executor still loads configuration itself before running the application chain.",
16
16
  "deprecatedMessage": "",
@@ -22,7 +22,7 @@
22
22
  "required": ["export", "module", "options"],
23
23
  "properties": {
24
24
  "export": {
25
- "const": "AIGatewayConfigurationLoaderV2InboundPolicy",
25
+ "const": "AIGatewayConfigurationLoaderInboundPolicy",
26
26
  "description": "The name of the exported type"
27
27
  },
28
28
  "module": {
@@ -30,8 +30,7 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-configuration-loader-v2",
34
- "title": "AIGatewayConfigurationLoaderV2InboundPolicyOptions",
33
+ "title": "AIGatewayConfigurationLoaderInboundPolicyOptions",
35
34
  "type": "object",
36
35
  "description": "Options for loading each application's AI Gateway configuration into the request-scoped channel.",
37
36
  "additionalProperties": false,
@@ -48,7 +47,7 @@
48
47
  },
49
48
  "examples": [
50
49
  {
51
- "export": "AIGatewayConfigurationLoaderV2InboundPolicy",
50
+ "export": "AIGatewayConfigurationLoaderInboundPolicy",
52
51
  "module": "$import(@zuplo/runtime)",
53
52
  "options": {
54
53
  "cacheTtlSeconds": 10
@@ -30,7 +30,6 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-dlp",
34
33
  "type": "object",
35
34
  "title": "AIGatewayDlpInboundPolicyOptions",
36
35
  "description": "The options for the Data Loss Prevention (DLP) policy. Scans the content of AI requests and responses — system prompts, messages, and tool-call arguments — for sensitive data such as credit cards, national identifiers, and API keys, applying a per-rule action (mask, block, or log). Detection runs entirely inside the gateway; streaming responses are scanned as they stream (or collected and scanned whole with `streaming.mode: \"buffer\"`).",
@@ -35,9 +35,9 @@ A fallback that names the same model as the primary selection is skipped.
35
35
  ```json
36
36
  {
37
37
  "name": "ai-gateway-fallback-model-v2-inbound",
38
- "policyType": "ai-gateway-fallback-model-v2",
38
+ "policyType": "ai-gateway-fallback-model",
39
39
  "handler": {
40
- "export": "AIGatewayFallbackModelV2InboundPolicy",
40
+ "export": "AIGatewayFallbackModelInboundPolicy",
41
41
  "module": "$import(@zuplo/runtime)",
42
42
  "options": {
43
43
  "models": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft-07/schema",
3
- "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-fallback-model-v2-inbound.json",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-fallback-model-inbound.json",
4
4
  "type": "object",
5
5
  "title": "AI Gateway Fallback Model",
6
6
  "isDeprecated": false,
@@ -10,7 +10,7 @@
10
10
  "isBeta": false,
11
11
  "isHidden": false,
12
12
  "requiresAI": true,
13
- "policyType": "ai-gateway-fallback-model-v2",
13
+ "policyType": "ai-gateway-fallback-model",
14
14
  "products": ["ai-gateway"],
15
15
  "description": "Adds failure and quota fallbacks to an existing AI Gateway model selection.\n\nPlace this policy after AI Gateway Model Filtering. It never creates a model selection, so a misplaced policy cannot bypass filtering.",
16
16
  "deprecatedMessage": "",
@@ -22,7 +22,7 @@
22
22
  "required": ["export", "module", "options"],
23
23
  "properties": {
24
24
  "export": {
25
- "const": "AIGatewayFallbackModelV2InboundPolicy",
25
+ "const": "AIGatewayFallbackModelInboundPolicy",
26
26
  "description": "The name of the exported type"
27
27
  },
28
28
  "module": {
@@ -30,9 +30,8 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-fallback-model-v2",
34
33
  "type": "object",
35
- "title": "AIGatewayFallbackModelV2InboundPolicyOptions",
34
+ "title": "AIGatewayFallbackModelInboundPolicyOptions",
36
35
  "description": "Options for adding failure and quota fallbacks to an existing AI Gateway model selection.",
37
36
  "additionalProperties": false,
38
37
  "required": ["models"],
@@ -110,7 +109,7 @@
110
109
  },
111
110
  "examples": [
112
111
  {
113
- "export": "AIGatewayFallbackModelV2InboundPolicy",
112
+ "export": "AIGatewayFallbackModelInboundPolicy",
114
113
  "module": "$import(@zuplo/runtime)",
115
114
  "options": {
116
115
  "models": {
@@ -19,9 +19,9 @@ traces:
19
19
  ```json
20
20
  {
21
21
  "name": "galileo-tracing-v2-inbound",
22
- "policyType": "galileo-tracing-v2",
22
+ "policyType": "ai-gateway-galileo-tracing",
23
23
  "handler": {
24
- "export": "GalileoTracingV2InboundPolicy",
24
+ "export": "AIGatewayGalileoTracingInboundPolicy",
25
25
  "module": "$import(@zuplo/runtime)",
26
26
  "options": {
27
27
  "apiKey": "$env(GALILEO_API_KEY)",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft-07/schema",
3
- "$id": "https://cdn.zuplo.com/policies/runtime/schemas/galileo-tracing-v2-inbound.json",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-galileo-tracing-inbound.json",
4
4
  "type": "object",
5
5
  "title": "Galileo Tracing",
6
6
  "isDeprecated": false,
@@ -10,7 +10,7 @@
10
10
  "isBeta": false,
11
11
  "isHidden": false,
12
12
  "requiresAI": true,
13
- "policyType": "galileo-tracing-v2",
13
+ "policyType": "ai-gateway-galileo-tracing",
14
14
  "products": ["ai-gateway"],
15
15
  "description": "Galileo Tracing Inbound Policy",
16
16
  "deprecatedMessage": "",
@@ -22,7 +22,7 @@
22
22
  "required": ["export", "module", "options"],
23
23
  "properties": {
24
24
  "export": {
25
- "const": "GalileoTracingV2InboundPolicy",
25
+ "const": "AIGatewayGalileoTracingInboundPolicy",
26
26
  "description": "The name of the exported type"
27
27
  },
28
28
  "module": {
@@ -30,8 +30,7 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "galileo-tracing-v2",
34
- "title": "Galileo Tracing",
33
+ "title": "AIGatewayGalileoTracingInboundPolicyOptions",
35
34
  "description": "Track AI Gateway requests and responses using Galileo's LLM observability platform.",
36
35
  "type": "object",
37
36
  "examples": [
@@ -88,7 +87,7 @@
88
87
  },
89
88
  "examples": [
90
89
  {
91
- "export": "GalileoTracingV2InboundPolicy",
90
+ "export": "AIGatewayGalileoTracingInboundPolicy",
92
91
  "module": "$import(@zuplo/runtime)",
93
92
  "options": {
94
93
  "apiKey": "$env(GALILEO_API_KEY)",
@@ -30,7 +30,6 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-internal-only",
34
33
  "title": "AIGatewayInternalOnlyInboundPolicyOptions",
35
34
  "type": "object",
36
35
  "description": "The options for this policy. It has none.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft-07/schema",
3
- "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-metering-v2-inbound.json",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-metering-inbound.json",
4
4
  "type": "object",
5
5
  "title": "AI Gateway Metering",
6
6
  "isDeprecated": false,
@@ -10,7 +10,7 @@
10
10
  "isBeta": false,
11
11
  "isHidden": false,
12
12
  "requiresAI": true,
13
- "policyType": "ai-gateway-metering-v2",
13
+ "policyType": "ai-gateway-metering",
14
14
  "products": ["ai-gateway"],
15
15
  "description": "Meters AI Gateway usage and enforces limits configured by the application.\n\nThe authentication policy must run before this policy so the app configuration id is available for meter storage and analytics.",
16
16
  "deprecatedMessage": "",
@@ -22,7 +22,7 @@
22
22
  "required": ["export", "module", "options"],
23
23
  "properties": {
24
24
  "export": {
25
- "const": "AIGatewayMeteringV2InboundPolicy",
25
+ "const": "AIGatewayMeteringInboundPolicy",
26
26
  "description": "The name of the exported type"
27
27
  },
28
28
  "module": {
@@ -30,8 +30,7 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-metering-v2",
34
- "title": "AIGatewayMeteringV2InboundPolicyOptions",
33
+ "title": "AIGatewayMeteringInboundPolicyOptions",
35
34
  "type": "object",
36
35
  "description": "Options for metering AI Gateway usage and enforcing request-time limits.",
37
36
  "additionalProperties": false,
@@ -338,7 +337,7 @@
338
337
  },
339
338
  "examples": [
340
339
  {
341
- "export": "AIGatewayMeteringV2InboundPolicy",
340
+ "export": "AIGatewayMeteringInboundPolicy",
342
341
  "module": "$import(@zuplo/runtime)",
343
342
  "options": {
344
343
  "budgetRules": [
@@ -60,8 +60,10 @@ These Responses API operations do not have a request body:
60
60
  - `DELETE /v1/responses/:responseId`
61
61
 
62
62
  Because they cannot supply `model`, they require routing to be selected before
63
- the handler runs. Configure a `completions.allowList` in Model Filtering so its
64
- first entry supplies the default, or use a custom inbound policy that calls
63
+ the handler runs. Attach AI Gateway Model Override with a
64
+ `models.completions.default` model, configure a `completions.allowList` in Model
65
+ Filtering so its first entry supplies the default, or use a custom inbound
66
+ policy that calls
65
67
  `AIGatewayModelRouting.set(context, { completions: "providerName/model" })`.
66
68
  Without preselected routing, the handler returns an OpenAI-compatible 400
67
69
  `invalid_request_error` with this configuration guidance.
@@ -106,9 +108,9 @@ capability to add.
106
108
  ```json
107
109
  {
108
110
  "name": "ai-gateway-model-filtering-v2-inbound",
109
- "policyType": "ai-gateway-model-filtering-v2",
111
+ "policyType": "ai-gateway-model-filtering",
110
112
  "handler": {
111
- "export": "AIGatewayModelFilteringV2InboundPolicy",
113
+ "export": "AIGatewayModelFilteringInboundPolicy",
112
114
  "module": "$import(@zuplo/runtime)",
113
115
  "options": {
114
116
  "models": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft-07/schema",
3
- "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-model-filtering-v2-inbound.json",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-model-filtering-inbound.json",
4
4
  "type": "object",
5
5
  "title": "AI Gateway Model Filtering",
6
6
  "isDeprecated": false,
@@ -10,7 +10,7 @@
10
10
  "isBeta": false,
11
11
  "isHidden": false,
12
12
  "requiresAI": true,
13
- "policyType": "ai-gateway-model-filtering-v2",
13
+ "policyType": "ai-gateway-model-filtering",
14
14
  "products": ["ai-gateway"],
15
15
  "description": "Matches AI Gateway requests against curated allow lists or open block lists, then stores the winning model reference for the route handler.",
16
16
  "deprecatedMessage": "",
@@ -22,7 +22,7 @@
22
22
  "required": ["export", "module", "options"],
23
23
  "properties": {
24
24
  "export": {
25
- "const": "AIGatewayModelFilteringV2InboundPolicy",
25
+ "const": "AIGatewayModelFilteringInboundPolicy",
26
26
  "description": "The name of the exported type"
27
27
  },
28
28
  "module": {
@@ -30,9 +30,8 @@
30
30
  "description": "The module containing the policy"
31
31
  },
32
32
  "options": {
33
- "x-zuplo-policy-type": "ai-gateway-model-filtering-v2",
34
33
  "type": "object",
35
- "title": "AIGatewayModelFilteringV2InboundPolicyOptions",
34
+ "title": "AIGatewayModelFilteringInboundPolicyOptions",
36
35
  "description": "Options for allowing or blocking providerName/model references for each AI Gateway capability.",
37
36
  "additionalProperties": false,
38
37
  "required": ["models"],
@@ -146,7 +145,7 @@
146
145
  },
147
146
  "examples": [
148
147
  {
149
- "export": "AIGatewayModelFilteringV2InboundPolicy",
148
+ "export": "AIGatewayModelFilteringInboundPolicy",
150
149
  "module": "$import(@zuplo/runtime)",
151
150
  "options": {
152
151
  "models": {
@@ -0,0 +1,154 @@
1
+ Use this policy when the gateway operator, not the client, decides which model
2
+ an AI Gateway route uses. Each capability picks one mode:
3
+
4
+ - `force` sends every request to the configured model. A model in the request
5
+ body is ignored.
6
+ - `default` supplies the configured model only when the request omits `model`. A
7
+ request that selects a model keeps its selection.
8
+
9
+ `providerName` is the Provider Name configured in the Zuplo Portal. The text
10
+ after the first slash is the provider-specific model ID, so model IDs may
11
+ contain additional slashes.
12
+
13
+ ## Choosing a mode
14
+
15
+ Use `force` to:
16
+
17
+ - Pin a route to one vetted model regardless of client input.
18
+ - Repoint existing traffic at a new model without a client release.
19
+ - Expose a stable route like `/fast/v1/chat/completions` whose model you swap
20
+ server-side.
21
+
22
+ Use `default` to:
23
+
24
+ - Let clients omit `model` while keeping full choice for clients that send one.
25
+ - Give Responses management operations (`GET`/`DELETE /v1/responses/*`), which
26
+ have no request body, the routing they require.
27
+
28
+ ## Policy order
29
+
30
+ Place Model Override first among the model-selection policies:
31
+
32
+ ```text
33
+ Model Override -> Model Filtering -> Fallback Model -> AI Gateway handler
34
+ ```
35
+
36
+ - A selection made by an earlier policy is never overwritten. When this policy
37
+ sets the selection, AI Gateway Model Filtering leaves it unchanged, so a
38
+ forced model does not also need an allow-list entry.
39
+ - In `default` mode, a request that selects its own model passes through
40
+ unchanged, and Model Filtering or the handler validates it as usual. The
41
+ default never masks an invalid request model; a malformed value is still
42
+ rejected downstream with a 400 response.
43
+ - AI Gateway Fallback Model placed after this policy enriches the selection with
44
+ `fallback` and `quotaFallback` models. Keep fallback fields in that policy;
45
+ this one accepts plain `providerName/model` strings only.
46
+ - A custom inbound policy placed before this one stays authoritative. For
47
+ example, an experiment policy can select routing for a fraction of traffic and
48
+ let `force` catch the rest.
49
+
50
+ ## Options
51
+
52
+ `models` must contain `completions`, `embeddings`, or both. Each capability sets
53
+ exactly one of:
54
+
55
+ - `force` - the model every request uses.
56
+ - `default` - the model used only when the request omits `model`.
57
+
58
+ Values are plain `providerName/model` strings. Unsupported fields and malformed
59
+ references are rejected as configuration errors naming the field. If the policy
60
+ is attached but the route's capability has no rule, the policy passes the
61
+ request through unchanged.
62
+
63
+ ## Force example
64
+
65
+ ```json
66
+ {
67
+ "name": "ai-gateway-model-override-inbound",
68
+ "policyType": "ai-gateway-model-override",
69
+ "handler": {
70
+ "export": "AIGatewayModelOverrideInboundPolicy",
71
+ "module": "$import(@zuplo/runtime)",
72
+ "options": {
73
+ "models": {
74
+ "completions": {
75
+ "force": "openai/gpt-5"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ ## Default example
84
+
85
+ ```json
86
+ {
87
+ "models": {
88
+ "completions": {
89
+ "default": "anthropic/claude-haiku-4-5"
90
+ },
91
+ "embeddings": {
92
+ "default": "openai/text-embedding-3-small"
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Request behavior
99
+
100
+ | Situation | `force` | `default` |
101
+ | -------------------------------------------------- | -------------------------------- | ----------------------------------------------- |
102
+ | Request omits `model` | Configured model is selected. | Configured model is selected. |
103
+ | Request selects a model | Configured model replaces it. | The request's model continues downstream. |
104
+ | Request model is malformed | Configured model is selected. | Passed through; rejected downstream with a 400. |
105
+ | Bodyless request (Responses management operations) | Configured model is selected. | Configured model is selected. |
106
+ | An earlier policy already selected routing | Skipped; earlier selection wins. | Skipped; earlier selection wins. |
107
+ | Route capability has no rule | Passed through unchanged. | Passed through unchanged. |
108
+
109
+ When the policy selects the configured model, the same routing validation used
110
+ everywhere else applies: the Provider Name must be configured, the model must be
111
+ available for the route's capability, and the Provider Assignment must have
112
+ usable credentials. A configured model that fails this validation is reported as
113
+ this policy's configuration error, naming the exact option such as
114
+ `options.models.completions.force`.
115
+
116
+ ## Native routes
117
+
118
+ `/v1/responses` requires a Provider Name backed by OpenAI, and `/v1/messages`
119
+ requires one backed by Anthropic. A configured model that selects an
120
+ incompatible provider type is a configuration error on every request it applies
121
+ to, so the policy reports it as one, naming the option to fix.
122
+
123
+ ## Observability
124
+
125
+ Responses report the model that actually served the request in their `model`
126
+ field, so a client can always see that an override applied. The policy also
127
+ writes a debug-level log entry with `requestedModel` and `forcedModel` when a
128
+ forced model replaces a request's differing selection.
129
+
130
+ ## Write your own override policy
131
+
132
+ Everything this policy does is built on the public
133
+ `AIGatewayModelRouting.set(context, routing)` primitive. Use a custom inbound
134
+ policy instead when the override depends on request data, for example routing by
135
+ header:
136
+
137
+ ```typescript
138
+ import {
139
+ AIGatewayModelRouting,
140
+ type ZuploContext,
141
+ type ZuploRequest,
142
+ } from "@zuplo/runtime";
143
+
144
+ export default async function overrideModel(
145
+ request: ZuploRequest,
146
+ context: ZuploContext
147
+ ) {
148
+ const tier = request.headers.get("x-plan-tier");
149
+ await AIGatewayModelRouting.set(context, {
150
+ completions: tier === "pro" ? "openai/gpt-5" : "openai/gpt-5-mini",
151
+ });
152
+ return request;
153
+ }
154
+ ```
@@ -0,0 +1,5 @@
1
+ AI Gateway Model Override pins the model an AI Gateway route uses. Set `force`
2
+ to send every request to one model no matter what the client selects, or
3
+ `default` to supply a model only when the request omits one. Place it before AI
4
+ Gateway Model Filtering and AI Gateway Fallback Model; a selection made by an
5
+ earlier policy is never overwritten.
@@ -0,0 +1,126 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft-07/schema",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-model-override-inbound.json",
4
+ "type": "object",
5
+ "title": "AI Gateway Model Override",
6
+ "isDeprecated": false,
7
+ "isPaidAddOn": false,
8
+ "isEnterprise": false,
9
+ "isInternal": false,
10
+ "isBeta": true,
11
+ "isHidden": false,
12
+ "requiresAI": true,
13
+ "policyType": "ai-gateway-model-override",
14
+ "products": ["ai-gateway"],
15
+ "description": "Forces one model for every request, or supplies a default model when a request omits one, then stores that selection for the AI Gateway handler.\n\nAn earlier policy's model selection is never overwritten, so a custom routing policy placed before this one stays authoritative.",
16
+ "deprecatedMessage": "",
17
+ "required": ["handler"],
18
+ "properties": {
19
+ "handler": {
20
+ "type": "object",
21
+ "default": {},
22
+ "required": ["export", "module", "options"],
23
+ "properties": {
24
+ "export": {
25
+ "const": "AIGatewayModelOverrideInboundPolicy",
26
+ "description": "The name of the exported type"
27
+ },
28
+ "module": {
29
+ "const": "$import(@zuplo/runtime)",
30
+ "description": "The module containing the policy"
31
+ },
32
+ "options": {
33
+ "type": "object",
34
+ "title": "AIGatewayModelOverrideInboundPolicyOptions",
35
+ "description": "Options for forcing one model or supplying a default model for each AI Gateway capability.",
36
+ "additionalProperties": false,
37
+ "required": ["models"],
38
+ "properties": {
39
+ "models": {
40
+ "type": "object",
41
+ "title": "Models",
42
+ "description": "Override rules grouped by AI Gateway capability.",
43
+ "additionalProperties": false,
44
+ "minProperties": 1,
45
+ "properties": {
46
+ "completions": {
47
+ "title": "Completions Override",
48
+ "description": "Rule for chat completions, Responses, and Anthropic Messages requests.",
49
+ "oneOf": [
50
+ {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": ["force"],
54
+ "properties": {
55
+ "force": {
56
+ "title": "Forced Model",
57
+ "description": "The model every request uses; a request-selected model is ignored.",
58
+ "type": "string",
59
+ "pattern": "^[^/\\s]+/.+$"
60
+ }
61
+ }
62
+ },
63
+ {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "required": ["default"],
67
+ "properties": {
68
+ "default": {
69
+ "title": "Default Model",
70
+ "description": "The model used only when a request does not select one.",
71
+ "type": "string",
72
+ "pattern": "^[^/\\s]+/.+$"
73
+ }
74
+ }
75
+ }
76
+ ]
77
+ },
78
+ "embeddings": {
79
+ "title": "Embeddings Override",
80
+ "description": "Rule for embedding requests.",
81
+ "oneOf": [
82
+ {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["force"],
86
+ "properties": {
87
+ "force": {
88
+ "title": "Forced Model",
89
+ "description": "The model every request uses; a request-selected model is ignored.",
90
+ "type": "string",
91
+ "pattern": "^[^/\\s]+/.+$"
92
+ }
93
+ }
94
+ },
95
+ {
96
+ "type": "object",
97
+ "additionalProperties": false,
98
+ "required": ["default"],
99
+ "properties": {
100
+ "default": {
101
+ "title": "Default Model",
102
+ "description": "The model used only when a request does not select one.",
103
+ "type": "string",
104
+ "pattern": "^[^/\\s]+/.+$"
105
+ }
106
+ }
107
+ }
108
+ ]
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ },
115
+ "examples": [
116
+ {
117
+ "export": "AIGatewayModelOverrideInboundPolicy",
118
+ "module": "$import(@zuplo/runtime)",
119
+ "options": {
120
+ "models": {}
121
+ }
122
+ }
123
+ ]
124
+ }
125
+ }
126
+ }
@@ -22,9 +22,9 @@ chain that should emit traces:
22
22
  ```json
23
23
  {
24
24
  "name": "comet-opik-tracing-v2-inbound",
25
- "policyType": "comet-opik-tracing-v2",
25
+ "policyType": "ai-gateway-opik-tracing",
26
26
  "handler": {
27
- "export": "CometOpikTracingV2InboundPolicy",
27
+ "export": "AIGatewayOpikTracingInboundPolicy",
28
28
  "module": "$import(@zuplo/runtime)",
29
29
  "options": {
30
30
  "apiKey": "$env(COMET_OPIK_API_KEY)",