@ai-sdk/gateway 4.0.0-beta.10 → 4.0.0-beta.108

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 (46) hide show
  1. package/CHANGELOG.md +738 -4
  2. package/dist/index.d.ts +314 -42
  3. package/dist/index.js +1369 -397
  4. package/dist/index.js.map +1 -1
  5. package/docs/00-ai-gateway.mdx +447 -61
  6. package/package.json +14 -14
  7. package/src/errors/as-gateway-error.ts +2 -1
  8. package/src/errors/create-gateway-error.ts +17 -3
  9. package/src/errors/gateway-authentication-error.ts +8 -5
  10. package/src/errors/gateway-error.ts +8 -0
  11. package/src/errors/gateway-failed-dependency-error.ts +35 -0
  12. package/src/errors/gateway-forbidden-error.ts +34 -0
  13. package/src/errors/gateway-response-error.ts +1 -1
  14. package/src/errors/index.ts +2 -0
  15. package/src/errors/parse-auth-method.ts +1 -2
  16. package/src/gateway-config.ts +1 -1
  17. package/src/gateway-embedding-model-settings.ts +1 -0
  18. package/src/gateway-embedding-model.ts +62 -15
  19. package/src/gateway-fetch-metadata.ts +51 -38
  20. package/src/gateway-generation-info.ts +149 -0
  21. package/src/gateway-headers.ts +3 -0
  22. package/src/gateway-image-model-settings.ts +8 -1
  23. package/src/gateway-image-model.ts +46 -21
  24. package/src/gateway-language-model-settings.ts +44 -26
  25. package/src/gateway-language-model.ts +72 -42
  26. package/src/gateway-model-entry.ts +15 -3
  27. package/src/gateway-provider-options.ts +50 -78
  28. package/src/gateway-provider.ts +239 -35
  29. package/src/gateway-realtime-auth.ts +126 -0
  30. package/src/gateway-realtime-model-settings.ts +1 -0
  31. package/src/gateway-realtime-model.ts +107 -0
  32. package/src/gateway-reranking-model-settings.ts +7 -0
  33. package/src/gateway-reranking-model.ts +142 -0
  34. package/src/gateway-speech-model-settings.ts +1 -0
  35. package/src/gateway-speech-model.ts +145 -0
  36. package/src/gateway-spend-report.ts +193 -0
  37. package/src/gateway-transcription-model-settings.ts +1 -0
  38. package/src/gateway-transcription-model.ts +155 -0
  39. package/src/gateway-video-model-settings.ts +4 -0
  40. package/src/gateway-video-model.ts +29 -19
  41. package/src/index.ts +30 -5
  42. package/src/tool/parallel-search.ts +10 -11
  43. package/src/tool/perplexity-search.ts +10 -11
  44. package/dist/index.d.mts +0 -602
  45. package/dist/index.mjs +0 -1539
  46. package/dist/index.mjs.map +0 -1
@@ -29,7 +29,7 @@ For most use cases, you can use the AI Gateway directly with a model string:
29
29
  import { generateText } from 'ai';
30
30
 
31
31
  const { text } = await generateText({
32
- model: 'openai/gpt-5',
32
+ model: 'openai/gpt-5.4',
33
33
  prompt: 'Hello world',
34
34
  });
35
35
  ```
@@ -39,7 +39,7 @@ const { text } = await generateText({
39
39
  import { generateText, gateway } from 'ai';
40
40
 
41
41
  const { text } = await generateText({
42
- model: gateway('openai/gpt-5'),
42
+ model: gateway('openai/gpt-5.4'),
43
43
  prompt: 'Hello world',
44
44
  });
45
45
  ```
@@ -61,7 +61,7 @@ import { gateway } from 'ai';
61
61
 
62
62
  You may want to create a custom provider instance when you need to:
63
63
 
64
- - Set custom configuration options (API key, base URL, headers)
64
+ - Set custom configuration options (API key, Vercel access token, base URL, headers)
65
65
  - Use the provider in a [provider registry](/docs/ai-sdk-core/provider-management)
66
66
  - Wrap the provider with [middleware](/docs/ai-sdk-core/middleware)
67
67
  - Use different settings for different parts of your application
@@ -80,12 +80,19 @@ You can use the following optional settings to customize the AI Gateway provider
80
80
 
81
81
  - **baseURL** _string_
82
82
 
83
- Use a different URL prefix for API calls. The default prefix is `https://ai-gateway.vercel.sh/v3/ai`.
83
+ Use a different URL prefix for API calls. The default prefix is `https://ai-gateway.vercel.sh/v4/ai`.
84
84
 
85
85
  - **apiKey** _string_
86
86
 
87
- API key that is being sent using the `Authorization` header. It defaults to
88
- the `AI_GATEWAY_API_KEY` environment variable.
87
+ API key or Vercel access token that is being sent using the `Authorization`
88
+ header. It defaults to the `AI_GATEWAY_API_KEY` environment variable.
89
+ Supports AI Gateway API keys, Vercel personal access tokens, and Vercel app
90
+ access tokens.
91
+
92
+ - **teamIdOrSlug** _string_
93
+
94
+ Vercel team ID or slug used to scope model requests when authenticating with
95
+ multi-team Vercel access tokens.
89
96
 
90
97
  - **headers** _Record<string,string>_
91
98
 
@@ -104,7 +111,7 @@ You can use the following optional settings to customize the AI Gateway provider
104
111
 
105
112
  ## Authentication
106
113
 
107
- The Gateway provider supports two authentication methods:
114
+ The Gateway provider supports the following authentication methods:
108
115
 
109
116
  ### API Key Authentication
110
117
 
@@ -124,15 +131,37 @@ const gateway = createGateway({
124
131
  });
125
132
  ```
126
133
 
134
+ ### Vercel Access Token Authentication for Model Requests
135
+
136
+ For dynamic runtime authentication of model requests, pass a Vercel personal
137
+ access token or Vercel app access token to a custom Gateway provider instance:
138
+
139
+ ```ts
140
+ import { createGateway } from 'ai';
141
+
142
+ const gateway = createGateway({
143
+ apiKey: 'your_vercel_access_token_here',
144
+ teamIdOrSlug: 'your-team', // required for multi-team tokens
145
+ });
146
+ ```
147
+
148
+ `apiKey` takes precedence over `AI_GATEWAY_API_KEY` and OIDC.
149
+
150
+ <Note>
151
+ Vercel access tokens with `teamIdOrSlug` are supported for model requests.
152
+ Gateway helper methods such as `getCredits`, `getSpendReport`, and
153
+ `getGenerationInfo` require an AI Gateway API key or OIDC authentication.
154
+ </Note>
155
+
127
156
  ### OIDC Authentication (Vercel Deployments)
128
157
 
129
- When deployed to Vercel, the AI Gateway provider supports authenticating using [OIDC (OpenID Connect)
130
- tokens](https://vercel.com/docs/oidc) without API Keys.
158
+ When deployed to Vercel, the AI Gateway provider supports authenticating model
159
+ requests using [OIDC (OpenID Connect) tokens](https://vercel.com/docs/oidc)
160
+ without API Keys.
131
161
 
132
162
  #### How OIDC Authentication Works
133
163
 
134
164
  1. **In Production/Preview Deployments**:
135
-
136
165
  - OIDC authentication is automatically handled
137
166
  - No manual configuration needed
138
167
  - Tokens are automatically obtained and refreshed
@@ -147,8 +176,8 @@ tokens](https://vercel.com/docs/oidc) without API Keys.
147
176
  - You'll need to run `vercel env pull` again to refresh the token before it expires
148
177
 
149
178
  <Note>
150
- If an API Key is present (either passed directly or via environment), it will
151
- always be used, even if invalid.
179
+ If an API key or Vercel access token is present (either passed directly or via
180
+ environment), it will always be used instead of OIDC, even if invalid.
152
181
  </Note>
153
182
 
154
183
  Read more about using OIDC tokens in the [Vercel AI Gateway docs](https://vercel.com/docs/ai-gateway#using-the-ai-gateway-with-a-vercel-oidc-token).
@@ -159,6 +188,8 @@ You can connect your own provider credentials to use with Vercel AI Gateway. Thi
159
188
 
160
189
  To set up BYOK, add your provider credentials in your Vercel team's AI Gateway settings. Once configured, AI Gateway automatically uses your credentials. No code changes are needed.
161
190
 
191
+ For providers like Azure where you can use custom deployment names, you can configure model mappings to map gateway model slugs to your deployment names. See [model mappings](https://vercel.com/docs/ai-gateway/byok#model-mappings) for details.
192
+
162
193
  Learn more in the [BYOK documentation](https://vercel.com/docs/ai-gateway/byok).
163
194
 
164
195
  ## Language Models
@@ -169,13 +200,111 @@ You can create language models using a provider instance. The first argument is
169
200
  import { generateText } from 'ai';
170
201
 
171
202
  const { text } = await generateText({
172
- model: 'openai/gpt-5',
203
+ model: 'openai/gpt-5.4',
173
204
  prompt: 'Explain quantum computing in simple terms',
174
205
  });
175
206
  ```
176
207
 
177
208
  AI Gateway language models can also be used in the `streamText` function and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output) (see [AI SDK Core](/docs/ai-sdk-core)).
178
209
 
210
+ ## Reranking Models
211
+
212
+ You can create reranking models using the `rerankingModel` method on the provider instance:
213
+
214
+ ```ts
215
+ import { rerank } from 'ai';
216
+ import { gateway } from '@ai-sdk/gateway';
217
+
218
+ const { ranking } = await rerank({
219
+ model: gateway.rerankingModel('cohere/rerank-v3.5'),
220
+ query: 'What is the capital of France?',
221
+ documents: [
222
+ 'Paris is the capital of France.',
223
+ 'Berlin is the capital of Germany.',
224
+ 'Madrid is the capital of Spain.',
225
+ ],
226
+ topN: 2,
227
+ });
228
+
229
+ console.log(ranking);
230
+ // [
231
+ // { originalIndex: 0, score: 0.89, document: 'Paris is the capital of France.' },
232
+ // { originalIndex: 2, score: 0.15, document: 'Madrid is the capital of Spain.' },
233
+ // ]
234
+ ```
235
+
236
+ Reranking models are useful for improving search results in retrieval-augmented generation (RAG) pipelines by re-scoring candidate documents after an initial retrieval step.
237
+
238
+ ## Realtime Models
239
+
240
+ <Note type="warning">
241
+ Realtime support is experimental and the API may change in patch releases.
242
+ </Note>
243
+
244
+ You can create realtime models for bidirectional audio/text WebSocket sessions using the `experimental_realtime` method on the provider instance. The first argument is the model ID in the format `creator/model-name`:
245
+
246
+ ```ts
247
+ import { gateway } from '@ai-sdk/gateway';
248
+
249
+ const model = gateway.experimental_realtime('openai/gpt-realtime-2');
250
+ ```
251
+
252
+ The Gateway normalizes realtime the same way it normalizes every other modality: your client speaks the [normalized AI SDK realtime protocol](/docs/ai-sdk-core/realtime) and the Gateway translates to and from the upstream provider server-side. This means the same client code works regardless of which provider backs the model.
253
+
254
+ Gateway realtime v0 is server-side only. Calling `gateway.experimental_realtime()` in a browser throws an error. `getToken()` returns the Gateway auth token resolved by the provider (`apiKey`, `AI_GATEWAY_API_KEY`, or Vercel OIDC token), so do not expose it to browser clients.
255
+
256
+ ```ts
257
+ import { gateway } from '@ai-sdk/gateway';
258
+
259
+ // Server-side only. Do not return this token to browser clients.
260
+ const token = await gateway.experimental_realtime.getToken({
261
+ model: 'openai/gpt-realtime-2',
262
+ });
263
+ ```
264
+
265
+ <Note>
266
+ Gateway realtime v0 does not mint a provider-style short-lived client secret.
267
+ Gateway-minted ephemeral secrets are planned as future work; browser support
268
+ should wait for that flow.
269
+ </Note>
270
+
271
+ <Note>
272
+ The Gateway WebSocket route transports auth via the versioned
273
+ `Sec-WebSocket-Protocol` subprotocol and the model id via the `?ai-model-id=`
274
+ query - the WebSocket transport of the `Authorization` and `ai-model-id`
275
+ headers the HTTP routes use. Subprotocol values must fit the WebSocket token
276
+ grammar, and the complete `Sec-WebSocket-Protocol` header should stay compact
277
+ (under an 8 KiB safe header budget).
278
+ </Note>
279
+
280
+ ### Provider Options
281
+
282
+ Gateway [provider options](#gateway-provider-options) — `tags`, `user`, `byok`, compliance flags, and so on — are set under `providerOptions.gateway` in the **session configuration**, mirroring how they ride the request body on the non-realtime routes. Include them in the session configuration you send to the Gateway, and the Gateway applies them server-side:
283
+
284
+ ```ts
285
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
286
+
287
+ const gatewayOptions: GatewayProviderOptions = {
288
+ tags: ['cooking-coach', 'v2'],
289
+ user: 'user-123',
290
+ };
291
+
292
+ const sessionConfig = {
293
+ instructions: 'You are a concise voice assistant.',
294
+ providerOptions: { gateway: gatewayOptions },
295
+ };
296
+ ```
297
+
298
+ The `GatewayProviderOptions` type is exported from `@ai-sdk/gateway` for stable client-facing fields. The type also accepts service-owned option keys so the Gateway service can add or change server-side options without requiring an SDK release for every schema change. Runtime validation is owned by the Gateway service.
299
+
300
+ <Note>
301
+ Provider options are sent in the first `session.update` frame (after the
302
+ socket opens), so connect-time options such as `byok` and quota selection
303
+ require a Gateway that resolves them from that frame. Routing knobs like
304
+ `order` / `only` do not apply to realtime, where the Gateway selects the
305
+ WebSocket-capable provider.
306
+ </Note>
307
+
179
308
  ## Available Models
180
309
 
181
310
  The AI Gateway supports models from OpenAI, Anthropic, Google, Meta, xAI, Mistral, DeepSeek, Amazon Bedrock, Cohere, Perplexity, Alibaba, and other providers.
@@ -215,7 +344,7 @@ availableModels.models.forEach(model => {
215
344
 
216
345
  // Use any discovered model with plain string
217
346
  const { text } = await generateText({
218
- model: availableModels.models[0].id, // e.g., 'openai/gpt-4o'
347
+ model: availableModels.models[0].id, // e.g., 'openai/gpt-5.4'
219
348
  prompt: 'Hello world',
220
349
  });
221
350
  ```
@@ -238,6 +367,86 @@ The `getCredits()` method returns your team's credit information based on the au
238
367
  - **balance** _number_ - Your team's current available credit balance
239
368
  - **total_used** _number_ - Total credits consumed by your team
240
369
 
370
+ ## Generation Lookup
371
+
372
+ Look up detailed information about a specific generation by its ID, including cost, token usage, latency, and provider details. Generation IDs are available in `providerMetadata.gateway.generationId` on both `generateText` and `streamText` responses.
373
+
374
+ When streaming, the generation ID is injected on the first content chunk, so you can capture it early in the stream without waiting for completion. This is especially useful in cases where a network interruption or mid-stream error could prevent you from receiving the final response — since the gateway records the final status server-side, you can use the generation ID to look up the results (including cost, token usage, and finish reason) later via `getGenerationInfo()`.
375
+
376
+ ```ts
377
+ import { gateway, generateText } from 'ai';
378
+
379
+ // Make a request
380
+ const result = await generateText({
381
+ model: gateway('anthropic/claude-sonnet-4'),
382
+ prompt: 'Explain quantum entanglement briefly',
383
+ });
384
+
385
+ // Get the generation ID from provider metadata
386
+ const generationId = result.providerMetadata?.gateway?.generationId;
387
+
388
+ // Look up detailed generation info
389
+ const generation = await gateway.getGenerationInfo({ id: generationId });
390
+
391
+ console.log(`Model: ${generation.model}`);
392
+ console.log(`Cost: $${generation.totalCost.toFixed(6)}`);
393
+ console.log(`Latency: ${generation.latency}ms`);
394
+ console.log(`Prompt tokens: ${generation.promptTokens}`);
395
+ console.log(`Completion tokens: ${generation.completionTokens}`);
396
+ ```
397
+
398
+ With `streamText`, you can capture the generation ID from the first chunk via `stream`:
399
+
400
+ ```ts
401
+ import { gateway, streamText } from 'ai';
402
+
403
+ const result = streamText({
404
+ model: gateway('anthropic/claude-sonnet-4'),
405
+ prompt: 'Explain quantum entanglement briefly',
406
+ });
407
+
408
+ let generationId: string | undefined;
409
+
410
+ for await (const part of result.stream) {
411
+ if (!generationId && part.providerMetadata?.gateway?.generationId) {
412
+ generationId = part.providerMetadata.gateway.generationId as string;
413
+ console.log(`Generation ID (early): ${generationId}`);
414
+ }
415
+ }
416
+
417
+ // Look up cost and usage after the stream completes
418
+ if (generationId) {
419
+ const generation = await gateway.getGenerationInfo({ id: generationId });
420
+ console.log(`Cost: $${generation.totalCost.toFixed(6)}`);
421
+ console.log(`Finish reason: ${generation.finishReason}`);
422
+ }
423
+ ```
424
+
425
+ The `getGenerationInfo()` method accepts:
426
+
427
+ - **id** _string_ - The generation ID to look up (format: `gen_<ulid>`, required)
428
+
429
+ It returns a `GatewayGenerationInfo` object with the following fields:
430
+
431
+ - **id** _string_ - The generation ID
432
+ - **totalCost** _number_ - Total cost in USD
433
+ - **upstreamInferenceCost** _number_ - Upstream inference cost in USD (relevant for BYOK)
434
+ - **usage** _number_ - Usage cost in USD (same as totalCost)
435
+ - **createdAt** _string_ - ISO 8601 timestamp when the generation was created
436
+ - **model** _string_ - Model identifier used
437
+ - **isByok** _boolean_ - Whether Bring Your Own Key credentials were used
438
+ - **providerName** _string_ - The provider that served this generation
439
+ - **streamed** _boolean_ - Whether streaming was used
440
+ - **finishReason** _string_ - Finish reason (e.g. `'stop'`)
441
+ - **latency** _number_ - Time to first token in milliseconds
442
+ - **generationTime** _number_ - Total generation time in milliseconds
443
+ - **promptTokens** _number_ - Number of prompt tokens
444
+ - **completionTokens** _number_ - Number of completion tokens
445
+ - **reasoningTokens** _number_ - Reasoning tokens used (if applicable)
446
+ - **cachedTokens** _number_ - Cached tokens used (if applicable)
447
+ - **cacheCreationTokens** _number_ - Cache creation input tokens
448
+ - **billableWebSearchCalls** _number_ - Number of billable web search calls
449
+
241
450
  ## Examples
242
451
 
243
452
  ### Basic Text Generation
@@ -246,7 +455,7 @@ The `getCredits()` method returns your team's credit information based on the au
246
455
  import { generateText } from 'ai';
247
456
 
248
457
  const { text } = await generateText({
249
- model: 'anthropic/claude-sonnet-4',
458
+ model: 'anthropic/claude-sonnet-4.6',
250
459
  prompt: 'Write a haiku about programming',
251
460
  });
252
461
 
@@ -259,7 +468,7 @@ console.log(text);
259
468
  import { streamText } from 'ai';
260
469
 
261
470
  const { textStream } = await streamText({
262
- model: 'openai/gpt-5',
471
+ model: 'openai/gpt-5.4',
263
472
  prompt: 'Explain the benefits of serverless architecture',
264
473
  });
265
474
 
@@ -297,13 +506,13 @@ const { text } = await generateText({
297
506
  Some providers offer tools that are executed by the provider itself, such as [OpenAI's web search tool](/providers/ai-sdk-providers/openai#web-search-tool). To use these tools through AI Gateway, import the provider to access the tool definitions:
298
507
 
299
508
  ```ts
300
- import { generateText, stepCountIs } from 'ai';
509
+ import { generateText, isStepCount } from 'ai';
301
510
  import { openai } from '@ai-sdk/openai';
302
511
 
303
512
  const result = await generateText({
304
- model: 'openai/gpt-5-mini',
513
+ model: 'openai/gpt-5.4-mini',
305
514
  prompt: 'What is the Vercel AI Gateway?',
306
- stopWhen: stepCountIs(10),
515
+ stopWhen: isStepCount(10),
307
516
  tools: {
308
517
  web_search: openai.tools.webSearch({}),
309
518
  },
@@ -330,7 +539,7 @@ The Perplexity Search tool enables models to search the web using [Perplexity's
330
539
  import { gateway, generateText } from 'ai';
331
540
 
332
541
  const result = await generateText({
333
- model: 'openai/gpt-5-nano',
542
+ model: 'openai/gpt-5.4-nano',
334
543
  prompt: 'Search for news about AI regulations in January 2025.',
335
544
  tools: {
336
545
  perplexity_search: gateway.tools.perplexitySearch(),
@@ -348,7 +557,7 @@ You can also configure the search with optional parameters:
348
557
  import { gateway, generateText } from 'ai';
349
558
 
350
559
  const result = await generateText({
351
- model: 'openai/gpt-5-nano',
560
+ model: 'openai/gpt-5.4-nano',
352
561
  prompt:
353
562
  'Search for news about AI regulations from the first week of January 2025.',
354
563
  tools: {
@@ -402,14 +611,14 @@ The tool works with both `generateText` and `streamText`:
402
611
  import { gateway, streamText } from 'ai';
403
612
 
404
613
  const result = streamText({
405
- model: 'openai/gpt-5-nano',
614
+ model: 'openai/gpt-5.4-nano',
406
615
  prompt: 'Search for the latest news about AI regulations.',
407
616
  tools: {
408
617
  perplexity_search: gateway.tools.perplexitySearch(),
409
618
  },
410
619
  });
411
620
 
412
- for await (const part of result.fullStream) {
621
+ for await (const part of result.stream) {
413
622
  switch (part.type) {
414
623
  case 'text-delta':
415
624
  process.stdout.write(part.text);
@@ -432,7 +641,7 @@ The Parallel Search tool enables models to search the web using [Parallel AI's S
432
641
  import { gateway, generateText } from 'ai';
433
642
 
434
643
  const result = await generateText({
435
- model: 'openai/gpt-5-nano',
644
+ model: 'openai/gpt-5.4-nano',
436
645
  prompt: 'Research the latest developments in quantum computing.',
437
646
  tools: {
438
647
  parallel_search: gateway.tools.parallelSearch(),
@@ -450,7 +659,7 @@ You can also configure the search with optional parameters:
450
659
  import { gateway, generateText } from 'ai';
451
660
 
452
661
  const result = await generateText({
453
- model: 'openai/gpt-5-nano',
662
+ model: 'openai/gpt-5.4-nano',
454
663
  prompt: 'Find detailed information about TypeScript 5.0 features.',
455
664
  tools: {
456
665
  parallel_search: gateway.tools.parallelSearch({
@@ -476,7 +685,6 @@ The Parallel Search tool supports the following optional configuration options:
476
685
  - **mode** _'one-shot' | 'agentic'_
477
686
 
478
687
  Mode preset for different use cases:
479
-
480
688
  - `'one-shot'` - Comprehensive results with longer excerpts for single-response answers (default)
481
689
  - `'agentic'` - Concise, token-efficient results optimized for multi-step agentic workflows
482
690
 
@@ -487,7 +695,6 @@ The Parallel Search tool supports the following optional configuration options:
487
695
  - **sourcePolicy** _object_
488
696
 
489
697
  Source policy for controlling which domains to include/exclude:
490
-
491
698
  - `includeDomains` - List of domains to include in search results
492
699
  - `excludeDomains` - List of domains to exclude from search results
493
700
  - `afterDate` - Only include results published after this date (ISO 8601 format)
@@ -495,14 +702,12 @@ The Parallel Search tool supports the following optional configuration options:
495
702
  - **excerpts** _object_
496
703
 
497
704
  Excerpt configuration for controlling result length:
498
-
499
705
  - `maxCharsPerResult` - Maximum characters per result
500
706
  - `maxCharsTotal` - Maximum total characters across all results
501
707
 
502
708
  - **fetchPolicy** _object_
503
709
 
504
710
  Fetch policy for controlling content freshness:
505
-
506
711
  - `maxAgeSeconds` - Maximum age in seconds for cached content (set to 0 for always fresh)
507
712
 
508
713
  The tool works with both `generateText` and `streamText`:
@@ -511,14 +716,14 @@ The tool works with both `generateText` and `streamText`:
511
716
  import { gateway, streamText } from 'ai';
512
717
 
513
718
  const result = streamText({
514
- model: 'openai/gpt-5-nano',
719
+ model: 'openai/gpt-5.4-nano',
515
720
  prompt: 'Research the latest AI safety guidelines.',
516
721
  tools: {
517
722
  parallel_search: gateway.tools.parallelSearch(),
518
723
  },
519
724
  });
520
725
 
521
- for await (const part of result.fullStream) {
726
+ for await (const part of result.stream) {
522
727
  switch (part.type) {
523
728
  case 'text-delta':
524
729
  process.stdout.write(part.text);
@@ -533,22 +738,24 @@ for await (const part of result.fullStream) {
533
738
  }
534
739
  ```
535
740
 
536
- ### Usage Tracking with User and Tags
741
+ ### Custom Reporting
742
+
743
+ Track usage per end-user and categorize requests with tags, then query the data through the reporting API.
537
744
 
538
- Track usage per end-user and categorize requests with tags:
745
+ #### Usage Tracking with User and Tags
539
746
 
540
747
  ```ts
541
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
748
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
542
749
  import { generateText } from 'ai';
543
750
 
544
751
  const { text } = await generateText({
545
- model: 'openai/gpt-5',
752
+ model: 'openai/gpt-5.4',
546
753
  prompt: 'Summarize this document...',
547
754
  providerOptions: {
548
755
  gateway: {
549
756
  user: 'user-abc-123', // Track usage for this specific end-user
550
757
  tags: ['document-summary', 'premium-feature'], // Categorize for reporting
551
- } satisfies GatewayLanguageModelOptions,
758
+ } satisfies GatewayProviderOptions,
552
759
  },
553
760
  });
554
761
  ```
@@ -559,6 +766,77 @@ This allows you to:
559
766
  - Filter and analyze spending by feature or use case using tags
560
767
  - Track which users or features are driving the most AI usage
561
768
 
769
+ #### Querying Spend Reports
770
+
771
+ Use the `getSpendReport()` method to query usage data programmatically. The reporting API is only available for Vercel Pro and Enterprise plans. For pricing, see the [Custom Reporting docs](https://vercel.com/docs/ai-gateway/capabilities/custom-reporting).
772
+
773
+ ```ts
774
+ import { gateway } from 'ai';
775
+
776
+ const report = await gateway.getSpendReport({
777
+ startDate: '2026-03-01',
778
+ endDate: '2026-03-25',
779
+ groupBy: 'model',
780
+ });
781
+
782
+ for (const row of report.results) {
783
+ console.log(`${row.model}: $${row.totalCost.toFixed(4)}`);
784
+ }
785
+ ```
786
+
787
+ The `getSpendReport()` method accepts the following parameters:
788
+
789
+ - **startDate** _string_ - Start date in `YYYY-MM-DD` format (inclusive, required)
790
+ - **endDate** _string_ - End date in `YYYY-MM-DD` format (inclusive, required)
791
+ - **groupBy** _string_ - Aggregation dimension: `'day'` (default), `'user'`, `'model'`, `'tag'`, `'provider'`, or `'credential_type'`
792
+ - **datePart** _string_ - Time granularity when `groupBy` is `'day'`: `'day'` or `'hour'`
793
+ - **userId** _string_ - Filter to a specific user
794
+ - **model** _string_ - Filter to a specific model (e.g. `'anthropic/claude-sonnet-4.5'`)
795
+ - **provider** _string_ - Filter to a specific provider (e.g. `'anthropic'`)
796
+ - **credentialType** _string_ - Filter by `'byok'` or `'system'` credentials
797
+ - **tags** _string[]_ - Filter to requests matching these tags
798
+
799
+ Each row in `results` contains a grouping field (matching your `groupBy` choice) and metrics:
800
+
801
+ - **totalCost** _number_ - Total cost in USD
802
+ - **marketCost** _number_ - Market cost in USD
803
+ - **inputTokens** _number_ - Number of input tokens
804
+ - **outputTokens** _number_ - Number of output tokens
805
+ - **cachedInputTokens** _number_ - Number of cached input tokens
806
+ - **cacheCreationInputTokens** _number_ - Number of cache creation input tokens
807
+ - **reasoningTokens** _number_ - Number of reasoning tokens
808
+ - **requestCount** _number_ - Number of requests
809
+
810
+ You can combine tracking and querying to analyze spend by tags you defined:
811
+
812
+ ```ts
813
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
814
+ import { gateway, streamText } from 'ai';
815
+
816
+ // 1. Make requests with tags
817
+ const result = streamText({
818
+ model: gateway('anthropic/claude-haiku-4.5'),
819
+ prompt: 'Summarize this quarter's results',
820
+ providerOptions: {
821
+ gateway: {
822
+ tags: ['team:finance', 'feature:summaries'],
823
+ } satisfies GatewayProviderOptions,
824
+ },
825
+ });
826
+
827
+ // 2. Later, query spend filtered by those tags
828
+ const report = await gateway.getSpendReport({
829
+ startDate: '2026-03-01',
830
+ endDate: '2026-03-31',
831
+ groupBy: 'tag',
832
+ tags: ['team:finance'],
833
+ });
834
+
835
+ for (const row of report.results) {
836
+ console.log(`${row.tag}: $${row.totalCost.toFixed(4)} (${row.requestCount} requests)`);
837
+ }
838
+ ```
839
+
562
840
  ## Provider Options
563
841
 
564
842
  The AI Gateway provider accepts provider options that control routing behavior and provider-specific configurations.
@@ -568,17 +846,17 @@ The AI Gateway provider accepts provider options that control routing behavior a
568
846
  You can use the `gateway` key in `providerOptions` to control how AI Gateway routes requests:
569
847
 
570
848
  ```ts
571
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
849
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
572
850
  import { generateText } from 'ai';
573
851
 
574
852
  const { text } = await generateText({
575
- model: 'anthropic/claude-sonnet-4',
853
+ model: 'anthropic/claude-sonnet-4.6',
576
854
  prompt: 'Explain quantum computing',
577
855
  providerOptions: {
578
856
  gateway: {
579
857
  order: ['vertex', 'anthropic'], // Try Vertex AI first, then Anthropic
580
858
  only: ['vertex', 'anthropic'], // Only use these providers
581
- } satisfies GatewayLanguageModelOptions,
859
+ } satisfies GatewayProviderOptions,
582
860
  },
583
861
  });
584
862
  ```
@@ -597,11 +875,24 @@ The following gateway provider options are available:
597
875
 
598
876
  Example: `only: ['anthropic', 'vertex']` will only allow routing to Anthropic or Vertex AI.
599
877
 
878
+ - **sort** _'cost' | 'ttft' | 'tps'_
879
+
880
+ Sorts available providers by a performance or cost metric before routing. The gateway will try the best-scoring provider first and fall back through the rest in sorted order. If unspecified, providers are ordered using the gateway's default system ranking.
881
+ - `'cost'` — lowest cost first
882
+ - `'ttft'` — lowest time-to-first-token first
883
+ - `'tps'` — highest tokens-per-second first
884
+
885
+ When combined with `order`, the user-specified providers are promoted to the front while remaining providers follow the sorted order.
886
+
887
+ Example: `sort: 'ttft'` will route to the provider with the fastest time-to-first-token.
888
+
889
+ When `sort` is active, the response's `providerMetadata.gateway.routing.sort` object contains the sort option used, the resulting execution order, per-provider metric values, and any providers that were deprioritized.
890
+
600
891
  - **models** _string[]_
601
892
 
602
893
  Specifies fallback models to use when the primary model fails or is unavailable. The gateway will try the primary model first (specified in the `model` parameter), then try each model in this array in order until one succeeds.
603
894
 
604
- Example: `models: ['openai/gpt-5-nano', 'gemini-2.0-flash']` will try the fallback models in order if the primary model fails.
895
+ Example: `models: ['openai/gpt-5.4-nano', 'gemini-3-flash-preview']` will try the fallback models in order if the primary model fails.
605
896
 
606
897
  - **user** _string_
607
898
 
@@ -621,15 +912,29 @@ The following gateway provider options are available:
621
912
 
622
913
  Each provider can have multiple credentials (tried in order). The structure is a record where keys are provider slugs and values are arrays of credential objects.
623
914
 
624
- Examples:
915
+ Each credential can optionally include a `modelMappings` array to map AI Gateway model slugs to your deployment names (for example, custom Azure deployment names). If a BYOK request fails, the gateway falls back to system credentials using the default model name.
625
916
 
917
+ Examples:
626
918
  - Single provider: `byok: { 'anthropic': [{ apiKey: 'sk-ant-...' }] }`
627
919
  - Multiple credentials: `byok: { 'vertex': [{ project: 'proj-1', googleCredentials: { privateKey: '...', clientEmail: '...' } }, { project: 'proj-2', googleCredentials: { privateKey: '...', clientEmail: '...' } }] }`
628
920
  - Multiple providers: `byok: { 'anthropic': [{ apiKey: '...' }], 'bedrock': [{ accessKeyId: '...', secretAccessKey: '...' }] }`
921
+ - With model mappings: `byok: { 'azure': [{ apiKey: '...', resourceName: '...', modelMappings: [{ gatewayModelSlug: 'openai/gpt-5.4-nano', customModelId: 'my-deployment' }] }] }`
629
922
 
630
923
  - **zeroDataRetention** _boolean_
631
924
 
632
- Restricts routing requests to providers that have zero data retention policies.
925
+ Restricts routing to providers with zero data retention agreements with Vercel for AI Gateway. BYOK credentials are skipped by default, since your provider agreements differ from Vercel's. When this filter is on, AI Gateway routes only to providers Vercel has ZDR agreements with for the model. If you have BYOK keys marked as ZDR, those keys are tried first, then AI Gateway falls back to its system credentials. You are responsible for the accuracy of that marking. Applies to both account-wide and request-level ZDR. The request fails if no ZDR-eligible credentials are available. Request-level ZDR is only available for Vercel Pro and Enterprise plans.
926
+
927
+ - **disallowPromptTraining** _boolean_
928
+
929
+ Restricts routing to providers that have agreements with Vercel for AI Gateway to not use prompts for model training. When using BYOK credentials, this filter is not applied. If BYOK credentials fail and the request falls back to system credentials, only providers that do not train on prompt data will be used. If there are no providers available for the model that disallow prompt training, the request will fail.
930
+
931
+ - **hipaaCompliant** _boolean_
932
+
933
+ Restricts routing to models and tools from providers that have signed a BAA with Vercel for the use of AI Gateway (requires Vercel HIPAA BAA add on). BYOK credentials are skipped when `hipaaCompliant` is set to `true` to ensure that requests are only routed to providers that support HIPAA compliance.
934
+
935
+ - **quotaEntityId** _string_
936
+
937
+ The unique identifier for the entity against which quota is tracked. Used for quota management and enforcement purposes.
633
938
 
634
939
  - **providerTimeouts** _object_
635
940
 
@@ -639,20 +944,46 @@ The following gateway provider options are available:
639
944
 
640
945
  For full details, see [Provider Timeouts](https://vercel.com/docs/ai-gateway/models-and-providers/provider-timeouts).
641
946
 
947
+ - **serviceTier** _'flex' | 'priority'_
948
+
949
+ Unified service tier intent. The gateway translates it into whichever
950
+ per-provider option each provider expects, and overrides any tier
951
+ also set in the per-provider options. Leave unset for provider
952
+ default. See the [OpenAI](/providers/ai-sdk-providers/openai),
953
+ [Google Generative AI](/providers/ai-sdk-providers/google-generative-ai),
954
+ and [Google Vertex AI](/providers/ai-sdk-providers/google-vertex)
955
+ provider docs for tier semantics, model availability, and graceful
956
+ downgrade behavior on each provider.
957
+
958
+ ```ts
959
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
960
+ import { generateText } from 'ai';
961
+
962
+ const { text } = await generateText({
963
+ model: 'openai/gpt-5-mini',
964
+ prompt: 'Hello',
965
+ providerOptions: {
966
+ gateway: {
967
+ serviceTier: 'priority',
968
+ } satisfies GatewayProviderOptions,
969
+ },
970
+ });
971
+ ```
972
+
642
973
  You can combine these options to have fine-grained control over routing and tracking:
643
974
 
644
975
  ```ts
645
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
976
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
646
977
  import { generateText } from 'ai';
647
978
 
648
979
  const { text } = await generateText({
649
- model: 'anthropic/claude-sonnet-4',
980
+ model: 'anthropic/claude-sonnet-4.6',
650
981
  prompt: 'Write a haiku about programming',
651
982
  providerOptions: {
652
983
  gateway: {
653
984
  order: ['vertex'], // Prefer Vertex AI
654
985
  only: ['anthropic', 'vertex'], // Only allow these providers
655
- } satisfies GatewayLanguageModelOptions,
986
+ } satisfies GatewayProviderOptions,
656
987
  },
657
988
  });
658
989
  ```
@@ -662,43 +993,98 @@ const { text } = await generateText({
662
993
  The `models` option enables automatic fallback to alternative models when the primary model fails:
663
994
 
664
995
  ```ts
665
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
996
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
666
997
  import { generateText } from 'ai';
667
998
 
668
999
  const { text } = await generateText({
669
- model: 'openai/gpt-4o', // Primary model
1000
+ model: 'openai/gpt-5.4', // Primary model
670
1001
  prompt: 'Write a TypeScript haiku',
671
1002
  providerOptions: {
672
1003
  gateway: {
673
- models: ['openai/gpt-5-nano', 'gemini-2.0-flash'], // Fallback models
674
- } satisfies GatewayLanguageModelOptions,
1004
+ models: ['openai/gpt-5.4-nano', 'gemini-3-flash-preview'], // Fallback models
1005
+ } satisfies GatewayProviderOptions,
675
1006
  },
676
1007
  });
677
1008
 
678
1009
  // This will:
679
- // 1. Try openai/gpt-4o first
680
- // 2. If it fails, try openai/gpt-5-nano
681
- // 3. If that fails, try gemini-2.0-flash
1010
+ // 1. Try openai/gpt-5.4 first
1011
+ // 2. If it fails, try openai/gpt-5.4-nano
1012
+ // 3. If that fails, try gemini-3-flash-preview
682
1013
  // 4. Return the result from the first model that succeeds
683
1014
  ```
684
1015
 
685
1016
  #### Zero Data Retention Example
686
1017
 
687
- Set `zeroDataRetention` to true to ensure requests are only routed to providers
688
- that have zero data retention policies. When `zeroDataRetention` is `false` or not
689
- specified, there is no enforcement of restricting routing.
1018
+ Set `zeroDataRetention` to true to route requests to providers with zero data retention agreements with Vercel for AI Gateway. BYOK credentials are skipped by default, since your provider agreements differ from Vercel's. When this filter is on, AI Gateway routes only to providers Vercel has ZDR agreements with for the model. If you have BYOK keys marked as ZDR, those keys are tried first, then AI Gateway falls back to its system credentials. You are responsible for the accuracy of that marking. Applies to both account-wide and request-level ZDR. The request fails if no ZDR-eligible credentials are available. When `zeroDataRetention` is `false` or not specified, there is no enforcement of restricting routing. Request-level ZDR is only available for Vercel Pro and Enterprise plans.
690
1019
 
691
1020
  ```ts
692
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1021
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
693
1022
  import { generateText } from 'ai';
694
1023
 
695
1024
  const { text } = await generateText({
696
- model: 'anthropic/claude-sonnet-4.5',
1025
+ model: 'anthropic/claude-sonnet-4.6',
697
1026
  prompt: 'Analyze this sensitive document...',
698
1027
  providerOptions: {
699
1028
  gateway: {
700
1029
  zeroDataRetention: true,
701
- } satisfies GatewayLanguageModelOptions,
1030
+ } satisfies GatewayProviderOptions,
1031
+ },
1032
+ });
1033
+ ```
1034
+
1035
+ #### Disallow Prompt Training Example
1036
+
1037
+ Set `disallowPromptTraining` to true to route requests to providers that have agreements with Vercel for AI Gateway to not use prompts for model training. When using BYOK credentials, this filter is not applied. If BYOK credentials fail and the request falls back to system credentials, only providers that do not train on prompt data will be used. If there are no providers available for the model that disallow prompt training, the request will fail. When `disallowPromptTraining` is `false` or not specified, there is no enforcement of restricting routing.
1038
+
1039
+ ```ts
1040
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1041
+ import { generateText } from 'ai';
1042
+
1043
+ const { text } = await generateText({
1044
+ model: 'anthropic/claude-sonnet-4.6',
1045
+ prompt: 'Analyze this proprietary business data...',
1046
+ providerOptions: {
1047
+ gateway: {
1048
+ disallowPromptTraining: true,
1049
+ } satisfies GatewayProviderOptions,
1050
+ },
1051
+ });
1052
+ ```
1053
+
1054
+ #### HIPAA Compliance Example
1055
+
1056
+ Set `hipaaCompliant` to true to route requests only to models or tools by providers that have signed a BAA with Vercel for the use of AI Gateway. If the model or tool does not have a HIPAA-compliant provider, the request will fail. When `hipaaCompliant` is `false` or not specified, there is no enforcement of restricting routing. BYOK credentials are skipped when `hipaaCompliant` is set to `true` to ensure that requests are only routed to providers that support HIPAA compliance.
1057
+
1058
+ ```ts
1059
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1060
+ import { generateText } from 'ai';
1061
+
1062
+ const { text } = await generateText({
1063
+ model: 'anthropic/claude-sonnet-4.6',
1064
+ prompt: 'Analyze this patient data...',
1065
+ providerOptions: {
1066
+ gateway: {
1067
+ hipaaCompliant: true,
1068
+ } satisfies GatewayProviderOptions,
1069
+ },
1070
+ });
1071
+ ```
1072
+
1073
+ #### Quota Entity ID Example
1074
+
1075
+ Set `quotaEntityId` to track and enforce quota against a specific entity. This is useful for multi-tenant applications where you need to manage quota at the entity level (e.g., per organization or team).
1076
+
1077
+ ```ts
1078
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1079
+ import { generateText } from 'ai';
1080
+
1081
+ const { text } = await generateText({
1082
+ model: 'anthropic/claude-sonnet-4.6',
1083
+ prompt: 'Summarize this report...',
1084
+ providerOptions: {
1085
+ gateway: {
1086
+ quotaEntityId: 'org-123',
1087
+ } satisfies GatewayProviderOptions,
702
1088
  },
703
1089
  });
704
1090
  ```
@@ -709,16 +1095,16 @@ When using provider-specific options through AI Gateway, use the actual provider
709
1095
 
710
1096
  ```ts
711
1097
  import type { AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
712
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1098
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
713
1099
  import { generateText } from 'ai';
714
1100
 
715
1101
  const { text } = await generateText({
716
- model: 'anthropic/claude-sonnet-4',
1102
+ model: 'anthropic/claude-sonnet-4.6',
717
1103
  prompt: 'Explain quantum computing',
718
1104
  providerOptions: {
719
1105
  gateway: {
720
1106
  order: ['vertex', 'anthropic'],
721
- } satisfies GatewayLanguageModelOptions,
1107
+ } satisfies GatewayProviderOptions,
722
1108
  anthropic: {
723
1109
  thinking: { type: 'enabled', budgetTokens: 12000 },
724
1110
  } satisfies AnthropicLanguageModelOptions,