@ai-sdk/gateway 4.0.0-beta.11 → 4.0.0-beta.111

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 (48) hide show
  1. package/CHANGELOG.md +762 -4
  2. package/dist/index.d.ts +449 -42
  3. package/dist/index.js +1554 -397
  4. package/dist/index.js.map +1 -1
  5. package/docs/00-ai-gateway.mdx +534 -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 +45 -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 +296 -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 +118 -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-tools.ts +10 -0
  38. package/src/gateway-transcription-model-settings.ts +1 -0
  39. package/src/gateway-transcription-model.ts +155 -0
  40. package/src/gateway-video-model-settings.ts +4 -0
  41. package/src/gateway-video-model.ts +29 -19
  42. package/src/index.ts +30 -5
  43. package/src/tool/exa-search.ts +352 -0
  44. package/src/tool/parallel-search.ts +10 -11
  45. package/src/tool/perplexity-search.ts +10 -11
  46. package/dist/index.d.mts +0 -602
  47. package/dist/index.mjs +0 -1539
  48. 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);
@@ -424,6 +633,93 @@ for await (const part of result.fullStream) {
424
633
  }
425
634
  ```
426
635
 
636
+ #### Exa Search
637
+
638
+ The Exa Search tool enables models to search the web using [Exa's Search API](https://exa.ai/docs/reference/search-api-guide-for-coding-agents). This tool is executed by the AI Gateway and returns token-efficient web excerpts for agent workflows.
639
+
640
+ ```ts
641
+ import { gateway, generateText } from 'ai';
642
+
643
+ const result = await generateText({
644
+ model: 'openai/gpt-5.4-nano',
645
+ prompt:
646
+ 'Find the latest AI regulation updates and summarize the key changes.',
647
+ tools: {
648
+ exa_search: gateway.tools.exaSearch(),
649
+ },
650
+ });
651
+
652
+ console.log(result.text);
653
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
654
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
655
+ ```
656
+
657
+ You can also configure the search with optional parameters:
658
+
659
+ ```ts
660
+ import { gateway, generateText } from 'ai';
661
+
662
+ const result = await generateText({
663
+ model: 'openai/gpt-5.4-nano',
664
+ prompt: 'Find recent AI regulation news from trusted sources.',
665
+ tools: {
666
+ exa_search: gateway.tools.exaSearch({
667
+ type: 'fast',
668
+ numResults: 5,
669
+ category: 'news',
670
+ includeDomains: ['reuters.com', 'bbc.com', 'nytimes.com'],
671
+ contents: {
672
+ highlights: true,
673
+ maxAgeHours: 24,
674
+ },
675
+ }),
676
+ },
677
+ });
678
+
679
+ console.log(result.text);
680
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
681
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
682
+ ```
683
+
684
+ The Exa Search tool supports the following optional configuration options:
685
+
686
+ - **type** _'auto' | 'fast' | 'instant'_
687
+
688
+ Search mode. `'auto'` is the default balance of speed and quality.
689
+
690
+ - **numResults** _number_
691
+
692
+ Maximum number of results to return (1-100, default: 10).
693
+
694
+ - **category** _'company' | 'people' | 'research paper' | 'news' | 'personal site' | 'financial report'_
695
+
696
+ Focus results on a specific content type.
697
+
698
+ - **includeDomains** / **excludeDomains** _string[]_
699
+
700
+ Restrict or exclude search results by domain.
701
+
702
+ - **startPublishedDate** / **endPublishedDate** _string_
703
+
704
+ Filter results by ISO 8601 publication date.
705
+
706
+ - **contents** _object_
707
+
708
+ Control result extraction and freshness:
709
+ - `text` - Return full page text, optionally capped with `maxCharacters`
710
+ - `highlights` - Return token-efficient excerpts
711
+ - `maxAgeHours` - Control cached content freshness
712
+ - `livecrawlTimeout` - Livecrawl timeout in milliseconds
713
+ - `subpages` / `subpageTarget` - Crawl related subpages
714
+ - `extras.links` / `extras.imageLinks` - Extract links from pages
715
+
716
+ The tool works with both `generateText` and `streamText`.
717
+
718
+ This initial Gateway integration supports Exa's plain Search modes and
719
+ token-efficient content controls. Deep synthesis modes and generated summaries
720
+ are intentionally not exposed yet because they have separate pricing from
721
+ standard Search.
722
+
427
723
  #### Parallel Search
428
724
 
429
725
  The Parallel Search tool enables models to search the web using [Parallel AI's Search API](https://docs.parallel.ai/api-reference/search-beta/search). This tool is optimized for LLM consumption, returning relevant excerpts from web pages that can replace multiple keyword searches with a single call.
@@ -432,7 +728,7 @@ The Parallel Search tool enables models to search the web using [Parallel AI's S
432
728
  import { gateway, generateText } from 'ai';
433
729
 
434
730
  const result = await generateText({
435
- model: 'openai/gpt-5-nano',
731
+ model: 'openai/gpt-5.4-nano',
436
732
  prompt: 'Research the latest developments in quantum computing.',
437
733
  tools: {
438
734
  parallel_search: gateway.tools.parallelSearch(),
@@ -450,7 +746,7 @@ You can also configure the search with optional parameters:
450
746
  import { gateway, generateText } from 'ai';
451
747
 
452
748
  const result = await generateText({
453
- model: 'openai/gpt-5-nano',
749
+ model: 'openai/gpt-5.4-nano',
454
750
  prompt: 'Find detailed information about TypeScript 5.0 features.',
455
751
  tools: {
456
752
  parallel_search: gateway.tools.parallelSearch({
@@ -476,7 +772,6 @@ The Parallel Search tool supports the following optional configuration options:
476
772
  - **mode** _'one-shot' | 'agentic'_
477
773
 
478
774
  Mode preset for different use cases:
479
-
480
775
  - `'one-shot'` - Comprehensive results with longer excerpts for single-response answers (default)
481
776
  - `'agentic'` - Concise, token-efficient results optimized for multi-step agentic workflows
482
777
 
@@ -487,7 +782,6 @@ The Parallel Search tool supports the following optional configuration options:
487
782
  - **sourcePolicy** _object_
488
783
 
489
784
  Source policy for controlling which domains to include/exclude:
490
-
491
785
  - `includeDomains` - List of domains to include in search results
492
786
  - `excludeDomains` - List of domains to exclude from search results
493
787
  - `afterDate` - Only include results published after this date (ISO 8601 format)
@@ -495,14 +789,12 @@ The Parallel Search tool supports the following optional configuration options:
495
789
  - **excerpts** _object_
496
790
 
497
791
  Excerpt configuration for controlling result length:
498
-
499
792
  - `maxCharsPerResult` - Maximum characters per result
500
793
  - `maxCharsTotal` - Maximum total characters across all results
501
794
 
502
795
  - **fetchPolicy** _object_
503
796
 
504
797
  Fetch policy for controlling content freshness:
505
-
506
798
  - `maxAgeSeconds` - Maximum age in seconds for cached content (set to 0 for always fresh)
507
799
 
508
800
  The tool works with both `generateText` and `streamText`:
@@ -511,14 +803,14 @@ The tool works with both `generateText` and `streamText`:
511
803
  import { gateway, streamText } from 'ai';
512
804
 
513
805
  const result = streamText({
514
- model: 'openai/gpt-5-nano',
806
+ model: 'openai/gpt-5.4-nano',
515
807
  prompt: 'Research the latest AI safety guidelines.',
516
808
  tools: {
517
809
  parallel_search: gateway.tools.parallelSearch(),
518
810
  },
519
811
  });
520
812
 
521
- for await (const part of result.fullStream) {
813
+ for await (const part of result.stream) {
522
814
  switch (part.type) {
523
815
  case 'text-delta':
524
816
  process.stdout.write(part.text);
@@ -533,22 +825,24 @@ for await (const part of result.fullStream) {
533
825
  }
534
826
  ```
535
827
 
536
- ### Usage Tracking with User and Tags
828
+ ### Custom Reporting
829
+
830
+ Track usage per end-user and categorize requests with tags, then query the data through the reporting API.
537
831
 
538
- Track usage per end-user and categorize requests with tags:
832
+ #### Usage Tracking with User and Tags
539
833
 
540
834
  ```ts
541
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
835
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
542
836
  import { generateText } from 'ai';
543
837
 
544
838
  const { text } = await generateText({
545
- model: 'openai/gpt-5',
839
+ model: 'openai/gpt-5.4',
546
840
  prompt: 'Summarize this document...',
547
841
  providerOptions: {
548
842
  gateway: {
549
843
  user: 'user-abc-123', // Track usage for this specific end-user
550
844
  tags: ['document-summary', 'premium-feature'], // Categorize for reporting
551
- } satisfies GatewayLanguageModelOptions,
845
+ } satisfies GatewayProviderOptions,
552
846
  },
553
847
  });
554
848
  ```
@@ -559,6 +853,77 @@ This allows you to:
559
853
  - Filter and analyze spending by feature or use case using tags
560
854
  - Track which users or features are driving the most AI usage
561
855
 
856
+ #### Querying Spend Reports
857
+
858
+ 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).
859
+
860
+ ```ts
861
+ import { gateway } from 'ai';
862
+
863
+ const report = await gateway.getSpendReport({
864
+ startDate: '2026-03-01',
865
+ endDate: '2026-03-25',
866
+ groupBy: 'model',
867
+ });
868
+
869
+ for (const row of report.results) {
870
+ console.log(`${row.model}: $${row.totalCost.toFixed(4)}`);
871
+ }
872
+ ```
873
+
874
+ The `getSpendReport()` method accepts the following parameters:
875
+
876
+ - **startDate** _string_ - Start date in `YYYY-MM-DD` format (inclusive, required)
877
+ - **endDate** _string_ - End date in `YYYY-MM-DD` format (inclusive, required)
878
+ - **groupBy** _string_ - Aggregation dimension: `'day'` (default), `'user'`, `'model'`, `'tag'`, `'provider'`, or `'credential_type'`
879
+ - **datePart** _string_ - Time granularity when `groupBy` is `'day'`: `'day'` or `'hour'`
880
+ - **userId** _string_ - Filter to a specific user
881
+ - **model** _string_ - Filter to a specific model (e.g. `'anthropic/claude-sonnet-4.5'`)
882
+ - **provider** _string_ - Filter to a specific provider (e.g. `'anthropic'`)
883
+ - **credentialType** _string_ - Filter by `'byok'` or `'system'` credentials
884
+ - **tags** _string[]_ - Filter to requests matching these tags
885
+
886
+ Each row in `results` contains a grouping field (matching your `groupBy` choice) and metrics:
887
+
888
+ - **totalCost** _number_ - Total cost in USD
889
+ - **marketCost** _number_ - Market cost in USD
890
+ - **inputTokens** _number_ - Number of input tokens
891
+ - **outputTokens** _number_ - Number of output tokens
892
+ - **cachedInputTokens** _number_ - Number of cached input tokens
893
+ - **cacheCreationInputTokens** _number_ - Number of cache creation input tokens
894
+ - **reasoningTokens** _number_ - Number of reasoning tokens
895
+ - **requestCount** _number_ - Number of requests
896
+
897
+ You can combine tracking and querying to analyze spend by tags you defined:
898
+
899
+ ```ts
900
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
901
+ import { gateway, streamText } from 'ai';
902
+
903
+ // 1. Make requests with tags
904
+ const result = streamText({
905
+ model: gateway('anthropic/claude-haiku-4.5'),
906
+ prompt: 'Summarize this quarter's results',
907
+ providerOptions: {
908
+ gateway: {
909
+ tags: ['team:finance', 'feature:summaries'],
910
+ } satisfies GatewayProviderOptions,
911
+ },
912
+ });
913
+
914
+ // 2. Later, query spend filtered by those tags
915
+ const report = await gateway.getSpendReport({
916
+ startDate: '2026-03-01',
917
+ endDate: '2026-03-31',
918
+ groupBy: 'tag',
919
+ tags: ['team:finance'],
920
+ });
921
+
922
+ for (const row of report.results) {
923
+ console.log(`${row.tag}: $${row.totalCost.toFixed(4)} (${row.requestCount} requests)`);
924
+ }
925
+ ```
926
+
562
927
  ## Provider Options
563
928
 
564
929
  The AI Gateway provider accepts provider options that control routing behavior and provider-specific configurations.
@@ -568,17 +933,17 @@ The AI Gateway provider accepts provider options that control routing behavior a
568
933
  You can use the `gateway` key in `providerOptions` to control how AI Gateway routes requests:
569
934
 
570
935
  ```ts
571
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
936
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
572
937
  import { generateText } from 'ai';
573
938
 
574
939
  const { text } = await generateText({
575
- model: 'anthropic/claude-sonnet-4',
940
+ model: 'anthropic/claude-sonnet-4.6',
576
941
  prompt: 'Explain quantum computing',
577
942
  providerOptions: {
578
943
  gateway: {
579
944
  order: ['vertex', 'anthropic'], // Try Vertex AI first, then Anthropic
580
945
  only: ['vertex', 'anthropic'], // Only use these providers
581
- } satisfies GatewayLanguageModelOptions,
946
+ } satisfies GatewayProviderOptions,
582
947
  },
583
948
  });
584
949
  ```
@@ -597,11 +962,24 @@ The following gateway provider options are available:
597
962
 
598
963
  Example: `only: ['anthropic', 'vertex']` will only allow routing to Anthropic or Vertex AI.
599
964
 
965
+ - **sort** _'cost' | 'ttft' | 'tps'_
966
+
967
+ 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.
968
+ - `'cost'` — lowest cost first
969
+ - `'ttft'` — lowest time-to-first-token first
970
+ - `'tps'` — highest tokens-per-second first
971
+
972
+ When combined with `order`, the user-specified providers are promoted to the front while remaining providers follow the sorted order.
973
+
974
+ Example: `sort: 'ttft'` will route to the provider with the fastest time-to-first-token.
975
+
976
+ 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.
977
+
600
978
  - **models** _string[]_
601
979
 
602
980
  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
981
 
604
- Example: `models: ['openai/gpt-5-nano', 'gemini-2.0-flash']` will try the fallback models in order if the primary model fails.
982
+ Example: `models: ['openai/gpt-5.4-nano', 'gemini-3-flash-preview']` will try the fallback models in order if the primary model fails.
605
983
 
606
984
  - **user** _string_
607
985
 
@@ -621,15 +999,29 @@ The following gateway provider options are available:
621
999
 
622
1000
  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
1001
 
624
- Examples:
1002
+ 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
1003
 
1004
+ Examples:
626
1005
  - Single provider: `byok: { 'anthropic': [{ apiKey: 'sk-ant-...' }] }`
627
1006
  - Multiple credentials: `byok: { 'vertex': [{ project: 'proj-1', googleCredentials: { privateKey: '...', clientEmail: '...' } }, { project: 'proj-2', googleCredentials: { privateKey: '...', clientEmail: '...' } }] }`
628
1007
  - Multiple providers: `byok: { 'anthropic': [{ apiKey: '...' }], 'bedrock': [{ accessKeyId: '...', secretAccessKey: '...' }] }`
1008
+ - With model mappings: `byok: { 'azure': [{ apiKey: '...', resourceName: '...', modelMappings: [{ gatewayModelSlug: 'openai/gpt-5.4-nano', customModelId: 'my-deployment' }] }] }`
629
1009
 
630
1010
  - **zeroDataRetention** _boolean_
631
1011
 
632
- Restricts routing requests to providers that have zero data retention policies.
1012
+ 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.
1013
+
1014
+ - **disallowPromptTraining** _boolean_
1015
+
1016
+ 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.
1017
+
1018
+ - **hipaaCompliant** _boolean_
1019
+
1020
+ 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.
1021
+
1022
+ - **quotaEntityId** _string_
1023
+
1024
+ The unique identifier for the entity against which quota is tracked. Used for quota management and enforcement purposes.
633
1025
 
634
1026
  - **providerTimeouts** _object_
635
1027
 
@@ -639,20 +1031,46 @@ The following gateway provider options are available:
639
1031
 
640
1032
  For full details, see [Provider Timeouts](https://vercel.com/docs/ai-gateway/models-and-providers/provider-timeouts).
641
1033
 
1034
+ - **serviceTier** _'flex' | 'priority'_
1035
+
1036
+ Unified service tier intent. The gateway translates it into whichever
1037
+ per-provider option each provider expects, and overrides any tier
1038
+ also set in the per-provider options. Leave unset for provider
1039
+ default. See the [OpenAI](/providers/ai-sdk-providers/openai),
1040
+ [Google Generative AI](/providers/ai-sdk-providers/google-generative-ai),
1041
+ and [Google Vertex AI](/providers/ai-sdk-providers/google-vertex)
1042
+ provider docs for tier semantics, model availability, and graceful
1043
+ downgrade behavior on each provider.
1044
+
1045
+ ```ts
1046
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1047
+ import { generateText } from 'ai';
1048
+
1049
+ const { text } = await generateText({
1050
+ model: 'openai/gpt-5-mini',
1051
+ prompt: 'Hello',
1052
+ providerOptions: {
1053
+ gateway: {
1054
+ serviceTier: 'priority',
1055
+ } satisfies GatewayProviderOptions,
1056
+ },
1057
+ });
1058
+ ```
1059
+
642
1060
  You can combine these options to have fine-grained control over routing and tracking:
643
1061
 
644
1062
  ```ts
645
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1063
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
646
1064
  import { generateText } from 'ai';
647
1065
 
648
1066
  const { text } = await generateText({
649
- model: 'anthropic/claude-sonnet-4',
1067
+ model: 'anthropic/claude-sonnet-4.6',
650
1068
  prompt: 'Write a haiku about programming',
651
1069
  providerOptions: {
652
1070
  gateway: {
653
1071
  order: ['vertex'], // Prefer Vertex AI
654
1072
  only: ['anthropic', 'vertex'], // Only allow these providers
655
- } satisfies GatewayLanguageModelOptions,
1073
+ } satisfies GatewayProviderOptions,
656
1074
  },
657
1075
  });
658
1076
  ```
@@ -662,43 +1080,98 @@ const { text } = await generateText({
662
1080
  The `models` option enables automatic fallback to alternative models when the primary model fails:
663
1081
 
664
1082
  ```ts
665
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1083
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
666
1084
  import { generateText } from 'ai';
667
1085
 
668
1086
  const { text } = await generateText({
669
- model: 'openai/gpt-4o', // Primary model
1087
+ model: 'openai/gpt-5.4', // Primary model
670
1088
  prompt: 'Write a TypeScript haiku',
671
1089
  providerOptions: {
672
1090
  gateway: {
673
- models: ['openai/gpt-5-nano', 'gemini-2.0-flash'], // Fallback models
674
- } satisfies GatewayLanguageModelOptions,
1091
+ models: ['openai/gpt-5.4-nano', 'gemini-3-flash-preview'], // Fallback models
1092
+ } satisfies GatewayProviderOptions,
675
1093
  },
676
1094
  });
677
1095
 
678
1096
  // 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
1097
+ // 1. Try openai/gpt-5.4 first
1098
+ // 2. If it fails, try openai/gpt-5.4-nano
1099
+ // 3. If that fails, try gemini-3-flash-preview
682
1100
  // 4. Return the result from the first model that succeeds
683
1101
  ```
684
1102
 
685
1103
  #### Zero Data Retention Example
686
1104
 
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.
1105
+ 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
1106
 
691
1107
  ```ts
692
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1108
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
693
1109
  import { generateText } from 'ai';
694
1110
 
695
1111
  const { text } = await generateText({
696
- model: 'anthropic/claude-sonnet-4.5',
1112
+ model: 'anthropic/claude-sonnet-4.6',
697
1113
  prompt: 'Analyze this sensitive document...',
698
1114
  providerOptions: {
699
1115
  gateway: {
700
1116
  zeroDataRetention: true,
701
- } satisfies GatewayLanguageModelOptions,
1117
+ } satisfies GatewayProviderOptions,
1118
+ },
1119
+ });
1120
+ ```
1121
+
1122
+ #### Disallow Prompt Training Example
1123
+
1124
+ 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.
1125
+
1126
+ ```ts
1127
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1128
+ import { generateText } from 'ai';
1129
+
1130
+ const { text } = await generateText({
1131
+ model: 'anthropic/claude-sonnet-4.6',
1132
+ prompt: 'Analyze this proprietary business data...',
1133
+ providerOptions: {
1134
+ gateway: {
1135
+ disallowPromptTraining: true,
1136
+ } satisfies GatewayProviderOptions,
1137
+ },
1138
+ });
1139
+ ```
1140
+
1141
+ #### HIPAA Compliance Example
1142
+
1143
+ 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.
1144
+
1145
+ ```ts
1146
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1147
+ import { generateText } from 'ai';
1148
+
1149
+ const { text } = await generateText({
1150
+ model: 'anthropic/claude-sonnet-4.6',
1151
+ prompt: 'Analyze this patient data...',
1152
+ providerOptions: {
1153
+ gateway: {
1154
+ hipaaCompliant: true,
1155
+ } satisfies GatewayProviderOptions,
1156
+ },
1157
+ });
1158
+ ```
1159
+
1160
+ #### Quota Entity ID Example
1161
+
1162
+ 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).
1163
+
1164
+ ```ts
1165
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
1166
+ import { generateText } from 'ai';
1167
+
1168
+ const { text } = await generateText({
1169
+ model: 'anthropic/claude-sonnet-4.6',
1170
+ prompt: 'Summarize this report...',
1171
+ providerOptions: {
1172
+ gateway: {
1173
+ quotaEntityId: 'org-123',
1174
+ } satisfies GatewayProviderOptions,
702
1175
  },
703
1176
  });
704
1177
  ```
@@ -709,16 +1182,16 @@ When using provider-specific options through AI Gateway, use the actual provider
709
1182
 
710
1183
  ```ts
711
1184
  import type { AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
712
- import type { GatewayLanguageModelOptions } from '@ai-sdk/gateway';
1185
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
713
1186
  import { generateText } from 'ai';
714
1187
 
715
1188
  const { text } = await generateText({
716
- model: 'anthropic/claude-sonnet-4',
1189
+ model: 'anthropic/claude-sonnet-4.6',
717
1190
  prompt: 'Explain quantum computing',
718
1191
  providerOptions: {
719
1192
  gateway: {
720
1193
  order: ['vertex', 'anthropic'],
721
- } satisfies GatewayLanguageModelOptions,
1194
+ } satisfies GatewayProviderOptions,
722
1195
  anthropic: {
723
1196
  thinking: { type: 'enabled', budgetTokens: 12000 },
724
1197
  } satisfies AnthropicLanguageModelOptions,