---
title: Azure OpenAI
description: Learn how to use Azure OpenAI with AI Gateway and the direct provider.
url: "https://ai-sdk.dev/providers/ai-sdk-providers/azure"
docs_index: /llms.txt
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

The [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) provider contains language model support for the Azure OpenAI chat API.
Start with [AI Gateway](/providers/ai-sdk-providers/ai-gateway) for models in its catalog (recommended), or use `@ai-sdk/azure` to connect directly to Azure OpenAI.

```ts provider="azure" model="openai/gpt-6-astra"
import { generateText } from 'ai';

const { text } = await generateText({
  model: "openai/gpt-6-astra",
  prompt: 'Write a vegetarian lasagna recipe for 4 people.',
  providerOptions: {
    gateway: {
      order: ['azure'],
    },
  },
});

console.log(text);
```

## Using AI Gateway

The AI SDK uses AI Gateway by default for model strings. Gateway provides access to models across providers through a single API key, with usage and cost tracking. Install `ai`:

```bash
pnpm add ai
```

Set an [AI Gateway API key](https://vercel.com/docs/ai-gateway/getting-started) in your environment:

```bash
export AI_GATEWAY_API_KEY=your_api_key_here
```

Vercel deployments can also use [OIDC authentication](/providers/ai-sdk-providers/ai-gateway#oidc-authentication-vercel-deployments).
See the [AI Gateway provider documentation](/providers/ai-sdk-providers/ai-gateway) for configuration and the [model catalog](https://vercel.com/ai-gateway/models) for available models.

The example sets `providerOptions.gateway.order` to `['azure']`. This sends the request to Azure OpenAI first, then falls back to other available providers of the same model if Azure OpenAI is unavailable or the request fails. `order` sets a preference; it does not restrict fallback to Azure OpenAI. See [provider ordering](https://vercel.com/docs/ai-gateway/models-and-providers/provider-filtering-and-ordering).

The dropdown lists models served by Azure OpenAI through Gateway with a corresponding direct-provider example. Provider availability depends on the model and your team's [Provider Allowlist](https://vercel.com/docs/ai-gateway/models-and-providers/provider-filtering-and-ordering).

## Using `@ai-sdk/azure`

For direct access to Azure OpenAI, install `ai` and `@ai-sdk/azure`:

```bash
pnpm add ai @ai-sdk/azure
```

Set your Azure API key and resource name:

```bash
export AZURE_API_KEY=your_api_key_here
export AZURE_RESOURCE_NAME=your_resource_name
```

The direct example uses an Azure deployment name. Replace it with the deployment name configured in your resource.

Use the direct provider for your Azure deployments, Microsoft Entra ID authentication, or Azure-specific APIs. Replace the deployment name in the Azure example with one from your resource.

The following sections document the direct `@ai-sdk/azure` provider, including
its model factories and settings. Gateway model and feature availability can
differ.

## Provider Instance

You can import the default provider instance `azure` from `@ai-sdk/azure`:

```ts
import { azure } from '@ai-sdk/azure';
```

If you need a customized setup, you can import `createAzure` from `@ai-sdk/azure` and create a provider instance with your settings:

```ts
import { createAzure } from '@ai-sdk/azure';

const azure = createAzure({
  resourceName: 'your-resource-name', // Azure resource name
  apiKey: 'your-api-key',
});
```

You can also use a complete [Microsoft Foundry OpenAI v1 base URL](https://learn.microsoft.com/en-us/azure/foundry/openai/api-version-lifecycle#model-support):

```ts
const azure = createAzure({
  baseURL: 'https://your-resource.services.ai.azure.com/openai/v1',
  apiKey: 'your-api-key',
});
```

For Microsoft Entra ID authentication, you can provide a token provider.
Install `@azure/identity` separately if you want to use its credential helpers:

```ts
import { createAzure } from '@ai-sdk/azure';
import {
  DefaultAzureCredential,
  getBearerTokenProvider,
} from '@azure/identity';

const credential = new DefaultAzureCredential();
const scope = 'https://cognitiveservices.azure.com/.default';
const tokenProvider = getBearerTokenProvider(credential, scope);

const azure = createAzure({
  resourceName: 'your-resource-name',
  tokenProvider,
});
```

You can use the following optional settings to customize the OpenAI provider instance:

- **resourceName** *string*

  Azure resource name.
  It defaults to the `AZURE_RESOURCE_NAME` environment variable.

  The resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/v1{path}`.
  It must be a single DNS label (letters, digits, and hyphens).
  You can use `baseURL` instead to specify the URL prefix.

- **apiKey** *string*

  API key that is being sent using the `api-key` header.
  It defaults to the `AZURE_API_KEY` environment variable.

- **tokenProvider** *() => Promise\<string>*

  Microsoft Entra ID token provider that returns an access token to be sent using the `Authorization` header.
  When provided, this is used instead of `apiKey`.

- **apiVersion** *string*

  Sets a custom [api version](https://learn.microsoft.com/en-us/azure/ai-services/openai/api-version-deprecation).
  Defaults to `v1`.
  This setting is applied when the provider constructs the v1 path or uses
  deployment-based URLs. Complete v1 base URLs are used as-is.

- **baseURL** *string*

  Use a different URL prefix for API calls, e.g. to use proxy servers.

  Either this or `resourceName` can be used.
  When a baseURL is provided, the resourceName is ignored.

  For Azure-hosted URLs ending in `.openai.azure.com`,
  `.services.ai.azure.com`, or `.cognitiveservices.azure.com`, you can pass
  either an unversioned OpenAI prefix such as `https://your-resource.services.ai.azure.com/openai`
  or a complete v1 base URL such as `https://your-resource.services.ai.azure.com/openai/v1`.
  The provider appends `/v1` and the configured `api-version` to unversioned
  resource URLs. Complete v1 URLs are used as-is.

  Complete Microsoft Foundry project v1 URLs, such as
  `https://your-resource.services.ai.azure.com/api/projects/your-project/openai/v1`,
  are also used as-is. If `/v1` is omitted from a Foundry project URL, the
  provider appends it without adding an `api-version` query parameter.

  With a non-Azure custom gateway baseURL, the resolved URL is `{baseURL}{path}`;
  the SDK does not append `/v1` or an `api-version` query parameter in this mode.

- **headers** *Record\<string,string>*

  Custom headers to include in the requests.

- **fetch** *(input: RequestInfo, init?: RequestInit) => Promise\<Response>*

  Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation.
  Defaults to the global `fetch` function.
  You can use it as a middleware to intercept requests,
  or to provide a custom fetch implementation for e.g. testing.

- **useDeploymentBasedUrls** *boolean*

  Use deployment-based URLs for API calls. Set to `true` to use the legacy deployment format:
  `{baseURL}/deployments/{deploymentId}{path}?api-version={apiVersion}` instead of
  `{baseURL}/v1{path}?api-version={apiVersion}`.
  Defaults to `false`.

  This option is useful for compatibility with certain Azure OpenAI models or deployments
  that require the legacy endpoint format.

- **speechBaseURL** *string*

  URL prefix for Azure Speech requests (MAI-Transcribe transcription and MAI-Voice
  speech generation), for example a regional endpoint such as `https://eastus.api.cognitive.microsoft.com`.
  Defaults to `https://{resourceName}.cognitiveservices.azure.com`.
  Speech requests do not use `baseURL` or `apiVersion`.

- **maiBaseURL** *string*

  URL prefix for MAI requests (MAI-Image and MAI-Transcribe-2-Streaming).
  Defaults to `https://{resourceName}.services.ai.azure.com/mai/v1`.

- **webSocket** *WebSocketConstructor*

  Custom WebSocket implementation for MAI streaming transcription, for example
  the `WebSocket` export of the `ws` package in Node.js. With a custom
  implementation the API key is sent in the `api-key` header; with the native
  `WebSocket` it is sent as the `api-key` query parameter. Microsoft Entra ID
  (`tokenProvider`) authentication requires a custom implementation; without one,
  streaming fails with an `InvalidArgumentError` before connecting.

## Language Models

The Azure OpenAI provider instance is a function that you can invoke to create a language model:

```ts
const model = azure('your-deployment-name');
```

You need to pass your deployment name as the first argument.

You can optionally pass the underlying model ID in a settings object:

```ts
const model = azure('production-chat', { modelId: 'gpt-5' });
```

The SDK uses the model ID as the model identity, including in telemetry, and
to detect model capabilities such as reasoning support. API requests still use the deployment name.
The model ID returned by Azure in response metadata is preserved.

If omitted, the deployment name is used for model identity and capability detection.
Keep the supplied model ID aligned with the model running in your deployment.

### Reasoning Models

Azure exposes the thinking of `DeepSeek-R1` in the generated text using the `<think>` tag.
You can use the `extractReasoningMiddleware` to extract this reasoning and expose it as a `reasoning` property on the result:

```ts
import { azure } from '@ai-sdk/azure';
import { wrapLanguageModel, extractReasoningMiddleware } from 'ai';

const enhancedModel = wrapLanguageModel({
  model: azure('your-deepseek-r1-deployment-name'),
  middleware: extractReasoningMiddleware({ tagName: 'think' }),
});
```

You can then use that enhanced model in functions like `generateText` and `streamText`.

The Azure provider calls the Responses API by default (unless you specify e.g.
`azure.chat`).

### Example

You can use OpenAI language models to generate text with the `generateText` function:

```ts
import { azure } from '@ai-sdk/azure';
import { generateText } from 'ai';

const { text } = await generateText({
  model: azure('your-deployment-name'),
  prompt: 'Write a vegetarian lasagna recipe for 4 people.',
});
```

OpenAI 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)).

Azure OpenAI sends larger chunks than OpenAI. This can lead to the perception
that the response is slower. See [Troubleshooting: Azure OpenAI Slow To
Stream](/docs/troubleshooting/azure-stream-slow)

### Provider Options

When using OpenAI language models on Azure, you can configure provider-specific options using `providerOptions.openai`. More information on available configuration options are on [the OpenAI provider page](/providers/ai-sdk-providers/openai#language-models).

```ts {12-14,24-26}
import { azure, type OpenAILanguageModelResponsesOptions } from '@ai-sdk/azure';

const messages = [
  {
    role: 'user',
    content: [
      {
        type: 'text',
        text: 'What is the capital of the moon?',
      },
      {
        type: 'file',
        mediaType: 'image',
        data: 'https://example.com/image.png',
        providerOptions: {
          openai: { imageDetail: 'low' },
        },
      },
    ],
  },
];

const { text } = await generateText({
  model: azure('your-deployment-name'),
  providerOptions: {
    openai: {
      reasoningEffort: 'low',
    } satisfies OpenAILanguageModelResponsesOptions,
  },
});
```

### Chat Models

The URL for calling Azure chat models will be constructed as follows:
`https://RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions?api-version=v1`

You can create models that call the Azure OpenAI chat completions API using the `.chat()` factory method:

```ts
const model = azure.chat('your-deployment-name');
```

Azure OpenAI chat models support also some model specific settings that are not part of the [standard call settings](/docs/ai-sdk-core/settings).
You can pass them as an options argument:

```ts
import { azure, type OpenAILanguageModelChatOptions } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure.chat('your-deployment-name'),
  prompt: 'Write a short story about a robot.',
  providerOptions: {
    openai: {
      logitBias: {
        // optional likelihood for specific tokens
        '50256': -100,
      },
      user: 'test-user', // optional unique user identifier
    } satisfies OpenAILanguageModelChatOptions,
  },
});
```

The following optional provider options are available for OpenAI chat models:

- **logitBias** *Record\<number, number>*

  Modifies the likelihood of specified tokens appearing in the completion.

  Accepts a JSON object that maps tokens (specified by their token ID in
  the GPT tokenizer) to an associated bias value from -100 to 100. You
  can use this tokenizer tool to convert text to token IDs. Mathematically,
  the bias is added to the logits generated by the model prior to sampling.
  The exact effect will vary per model, but values between -1 and 1 should
  decrease or increase likelihood of selection; values like -100 or 100
  should result in a ban or exclusive selection of the relevant token.

  As an example, you can pass `{"50256": -100}` to prevent the token from being generated.

- **logprobs** *boolean | number*

  Return the log probabilities of the tokens. Including logprobs will increase
  the response size and can slow down response times. However, it can
  be useful to better understand how the model is behaving.

  Setting to true will return the log probabilities of the tokens that
  were generated.

  Setting to a number will return the log probabilities of the top n
  tokens that were generated.

- **parallelToolCalls** *boolean*

  Whether to enable parallel function calling during tool use. Default to true.

- **user** *string*

  A unique identifier representing your end-user, which can help OpenAI to
  monitor and detect abuse. Learn more.

### DeepSeek Chat Models

You can create Azure-hosted DeepSeek chat models using the `.deepseek()` factory method:

```ts
const model = azure.deepseek('your-deepseek-deployment-name');
```

Use this factory for Azure DeepSeek models that support DeepSeek's chat
reasoning fields, such as `deepseek-v4-pro` and `deepseek-v4-flash`. The
factory maps top-level `reasoning` to DeepSeek `reasoning_effort` request
settings, and parses streamed `reasoning_content` as AI SDK reasoning parts.

```ts
import { azure, type AzureDeepSeekLanguageModelOptions } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = generateText({
  model: azure.deepseek('your-deepseek-deployment-name'),
  prompt: 'How many "r"s are in the word "strawberry"?',
  reasoning: 'high',
});
```

### Responses Models

Azure OpenAI uses responses API as default with the `azure(deploymentName)` factory method.

```ts
const model = azure('your-deployment-name');
```

Further configuration can be done using OpenAI provider options.
You can validate the provider options using the `OpenAILanguageModelResponsesOptions` type.

In the Responses API, use `azure` as the provider name in `providerOptions`
instead of `openai`. The `openai` key is still supported for `providerOptions`
input.

```ts
import { azure, OpenAILanguageModelResponsesOptions } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('your-deployment-name'),
  providerOptions: {
    azure: {
      parallelToolCalls: false,
      store: false,
      user: 'user_123',
      // ...
    } satisfies OpenAILanguageModelResponsesOptions,
  },
  // ...
});
```

The following provider options are available:

- **parallelToolCalls** *boolean*
  Whether to use parallel tool calls. Defaults to `true`.

- **store** *boolean*
  Whether to store the generation. Defaults to `true`.

- **metadata** *Record\<string, string>*
  Additional metadata to store with the generation.

- **previousResponseId** *string*
  The ID of the previous response. You can use it to continue a conversation. Defaults to `undefined`.

- **instructions** *string*
  Instructions for the model.
  They can be used to change the system or developer message when continuing a conversation using the `previousResponseId` option.
  Defaults to `undefined`.

- **user** *string*
  A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Defaults to `undefined`.

- **reasoningEffort** *'low' | 'medium' | 'high'*
  Reasoning effort for reasoning models. Defaults to `medium`. If you use `providerOptions` to set the `reasoningEffort` option, this model setting will be ignored.

- **strictJsonSchema** *boolean*
  Whether to use strict JSON schema validation. Defaults to `false`.

The Azure OpenAI provider also returns provider-specific metadata:

For Responses models (`azure(deploymentName)`), you can type this metadata using `AzureResponsesProviderMetadata`:

```ts
import { azure, type AzureResponsesProviderMetadata } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('your-deployment-name'),
});

const providerMetadata = result.providerMetadata as
  | AzureResponsesProviderMetadata
  | undefined;

const { responseId, logprobs, serviceTier } = providerMetadata?.azure ?? {};

// responseId can be used to continue a conversation (previousResponseId).
console.log(responseId);
```

The following Azure-specific metadata may be returned:

- **responseId** *string | null | undefined*
  The ID of the response. Can be used to continue a conversation.
- **logprobs** *(optional)*
  Log probabilities of output tokens (when enabled).
- **serviceTier** *(optional)*
  Service tier information returned by the API.

The providerMetadata is only returned with the default responses API, and is
not supported when using 'azure.chat' or 'azure.completion'

#### Changing Reasoning Effort Mid-Conversation

Azure Responses models support message-level reasoning effort updates through
`providerOptions.azure.reasoningEffortUpdate`. The `openai` namespace is also
accepted when the message has no `azure` options. Use the
`OpenAIResponsesSystemMessageOptions` type exported from `@ai-sdk/azure` to
validate these options:

```ts
import { azure, type OpenAIResponsesSystemMessageOptions } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  // Use the name of your GPT-6 deployment.
  model: azure.responses('gpt-6-astra'),
  reasoning: 'low',
  allowSystemInMessages: true,
  messages: [
    {
      role: 'system',
      content: '',
      providerOptions: {
        azure: {
          reasoningEffortUpdate: 'high',
        } satisfies OpenAIResponsesSystemMessageOptions,
      },
    },
    { role: 'user', content: 'Analyze the failure modes of this migration.' },
  ],
});
```

Keep the request-level `reasoning` unchanged throughout the conversation and
retain earlier effort updates when resending message history. These updates
also work with `streamText`. See the [OpenAI reasoning effort
guide](/providers/ai-sdk-providers/openai#changing-reasoning-effort-mid-conversation)
for continuation, compaction, and configuration restrictions.

The SDK infers support for effort updates from the optional `modelId` setting
passed to `azure.responses()`, falling back to the deployment name. The ID must identify
a supported GPT-6-or-later model family, such as `gpt-6-astra`. A custom name
such as `production` is not recognized, even when the underlying deployment
runs GPT-6. Pass the underlying model ID, for example
`azure.responses('production', { modelId: 'gpt-6-astra' })`, to enable detection
for a custom deployment name.

#### Web Search Tool

The Azure OpenAI responses API supports web search through the `azure.tools.webSearch` tool.

`azure.tools.webSearchPreview()` is deprecated. Use `azure.tools.webSearch()`
instead. The existing `searchContextSize` and `userLocation` options are
supported by both tools.

```ts
const result = await generateText({
  model: azure('gpt-5'),
  prompt: 'What happened in San Francisco last week?',
  tools: {
    web_search: azure.tools.webSearch({
      // optional configuration:
      searchContextSize: 'high',
      userLocation: {
        type: 'approximate',
        city: 'San Francisco',
        region: 'California',
      },
      filters: {
        allowedDomains: ['sfchronicle.com', 'sfgate.com'],
        blockedDomains: ['example.com'],
      },
    }),
  },
  // Force web search tool (optional):
  toolChoice: { type: 'tool', toolName: 'web_search' },
});

// URL sources directly from `results`
const sources = result.sources;

// Or access sources from tool results
for (const toolResult of result.toolResults) {
  if (toolResult.toolName === 'web_search') {
    console.log('Query:', toolResult.output.action.query);
    console.log('Sources:', toolResult.output.sources);
    // `sources` is an array of object: { type: 'url', url: string }
  }
}
```

The web search tool supports the following configuration options:

- **externalWebAccess** *boolean* - Whether to use external web access for fetching live content. Defaults to `true`.
- **searchContextSize** *'low' | 'medium' | 'high'* - Controls the amount of context used for the search. Higher values provide more comprehensive results but may have higher latency and cost.
- **userLocation** - Optional location information to provide geographically relevant results. Includes `type` (always `'approximate'`), `country`, `city`, `region`, and `timezone`.
- **filters** - Optional filter configuration to restrict search results.
  - **allowedDomains** *string\[]* - Up to 100 allowed domains for the search.
  - **blockedDomains** *string\[]* - Up to 100 blocked domains for the search.

Omit the HTTP or HTTPS prefix from domain filters. Subdomains of configured domains are automatically included or excluded.

For detailed information on configuration options see the [Azure OpenAI Web Search Tool documentation](https://learn.microsoft.com/en-us/azure/foundry/openai/how-to/web-search).

On Microsoft Foundry environment , Live internet access is not supported. The
parameter `externalWebAccess` if passed will be ignored.

#### File Search Tool

The Azure OpenAI provider supports file search through the `azure.tools.fileSearch` tool.

You can force the use of the file search tool by setting the `toolChoice` parameter to `{ type: 'tool', toolName: 'file_search' }`.

```ts
const result = await generateText({
  model: azure('gpt-5'),
  prompt: 'What does the document say about user authentication?',
  tools: {
    file_search: azure.tools.fileSearch({
      // optional configuration:
      vectorStoreIds: ['vs_123', 'vs_456'],
      maxNumResults: 10,
      ranking: {
        ranker: 'auto',
      },
    }),
  },
  // Force file search tool:
  toolChoice: { type: 'tool', toolName: 'file_search' },
});
```

The tool must be named `file_search` when using Azure OpenAI's file search
functionality. This name is required by Azure OpenAI's API specification and
cannot be customized.

The 'file\_search' tool is only supported with the default responses API, and
is not supported when using 'azure.chat' or 'azure.completion'

#### Image Generation Tool

Azure OpenAI's Responses API supports multi-modal image generation as a provider-defined tool.
Availability is restricted to specific models (for example, `gpt-5` variants).

```ts
import { createAzure } from '@ai-sdk/azure';
import { generateText } from 'ai';

const azure = createAzure({
  headers: {
    'x-ms-oai-image-generation-deployment': 'gpt-image-2', // use your own image model deployment
  },
});

const result = await generateText({
  model: azure('gpt-5'),
  prompt:
    'Generate an image of an echidna swimming across the Mozambique channel.',
  tools: {
    image_generation: azure.tools.imageGeneration({ outputFormat: 'png' }),
  },
});

for (const toolResult of result.staticToolResults) {
  if (toolResult.toolName === 'image_generation') {
    const base64Image = toolResult.output.result;
  }
}
```

The tool must be named `image_generation` when using Azure OpenAI's image
generation functionality. This name is required by Azure OpenAI's API
specification and cannot be customized.

The 'image\_generation' tool is only supported with the default responses API,
and is not supported when using 'azure.chat' or 'azure.completion'

To use image\_generation, you must first create an image generation model. You
must add a deployment specification to the header
`x-ms-oai-image-generation-deployment`. Please note that the Responses API
model and the image generation model must be in the same resource.

When you set `store: false`, then previously generated images will not be
accessible by the model. We recommend using the image generation tool without
setting `store: false`.

#### Code Interpreter Tool

The Azure OpenAI provider supports the code interpreter tool through the `azure.tools.codeInterpreter` tool. This allows models to write and execute Python code.

```ts
import { azure } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('gpt-5'),
  prompt: 'Write and run Python code to calculate the factorial of 10',
  tools: {
    code_interpreter: azure.tools.codeInterpreter({
      // optional configuration:
      container: {
        fileIds: ['assistant-123', 'assistant-456'], // optional file IDs to make available
      },
    }),
  },
});
```

The code interpreter tool can be configured with:

- **container**: Either a container ID string or an object with `fileIds` to specify uploaded files that should be available to the code interpreter

The tool must be named `code_interpreter` when using Azure OpenAI's code
interpreter functionality. This name is required by Azure OpenAI's API
specification and cannot be customized.

The 'code\_interpreter' tool is only supported with the default responses API,
and is not supported when using 'azure.chat' or 'azure.completion'

When working with files generated by the Code Interpreter, reference
information can be obtained from both [annotations in Text
Parts](#typed-providermetadata-in-text-parts) and [`providerMetadata` in
Source Document Parts](#typed-providermetadata-in-source-document-parts).

#### PDF support

The Azure OpenAI provider supports reading PDF files.
You can pass PDF files as part of the message content using the `file` type:

```ts
const result = await generateText({
  model: azure('your-deployment-name'),
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'text',
          text: 'What is an embedding model?',
        },
        {
          type: 'file',
          data: fs.readFileSync('./data/ai.pdf'),
          mediaType: 'application/pdf',
          filename: 'ai.pdf', // optional
        },
      ],
    },
  ],
});
```

The model will have access to the contents of the PDF file and
respond to questions about it.
The PDF file should be passed using the `data` field,
and the `mediaType` should be set to `'application/pdf'`.

Reading PDF files are only supported with the default responses API, and is
not supported when using 'azure.chat' or 'azure.completion'

#### Typed providerMetadata in Text Parts

When using the Azure OpenAI Responses API, the SDK attaches Azure OpenAI-specific metadata to output parts via `providerMetadata`.

This metadata can be used on the client side for tasks such as rendering citations or downloading files generated by the Code Interpreter.
To enable type-safe handling of this metadata, the AI SDK exports dedicated TypeScript types.

For text parts, when `part.type === 'text'`, the `providerMetadata` is provided in the form of `AzureResponsesTextProviderMetadata`.

This metadata includes the following fields:

- `itemId`\
  The ID of the output item in the Responses API.
- `annotations` (optional)
  An array of annotation objects generated by the model.
  If no annotations are present, this property itself may be omitted (`undefined`).

  Each element in `annotations` is a discriminated union with a required `type` field. Supported types include, for example:

  - `url_citation`
  - `file_citation`
  - `container_file_citation`
  - `file_path`

  These annotations directly correspond to the annotation objects defined by the Responses API and can be used for inline reference rendering or output analysis.
  For details, see the official OpenAI documentation:
  [Responses API – output text annotations](https://platform.openai.com/docs/api-reference/responses/object?lang=javascript#responses-object-output-output_message-content-output_text-annotations).

```ts
import { azure, type AzureResponsesTextProviderMetadata } from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('gpt-4.1-mini'),
  prompt:
    'Create a program that generates five random numbers between 1 and 100 with two decimal places, and show me the execution results. Also save the result to a file.',
  tools: {
    code_interpreter: azure.tools.codeInterpreter(),
    web_search: azure.tools.webSearch({}),
    file_search: azure.tools.fileSearch({ vectorStoreIds: ['vs_1234'] }), // requires a configured vector store
  },
});

for (const part of result.content) {
  if (part.type === 'text') {
    const providerMetadata = part.providerMetadata as
      | AzureResponsesTextProviderMetadata
      | undefined;
    if (!providerMetadata) continue;
    const { itemId: _itemId, annotations } = providerMetadata.azure;

    if (!annotations) continue;
    for (const annotation of annotations) {
      switch (annotation.type) {
        case 'url_citation':
          // url_citation is returned from web_search and provides:
          // properties: type, url, title, start_index and end_index
          break;
        case 'file_citation':
          // file_citation is returned from file_search and provides:
          // properties: type, file_id, filename and index
          break;
        case 'container_file_citation':
          // container_file_citation is returned from code_interpreter and provides:
          // properties: type, container_id, file_id, filename, start_index and end_index
          break;
        case 'file_path':
          // file_path provides:
          // properties: type, file_id and index
          break;
        default: {
          const _exhaustiveCheck: never = annotation;
          throw new Error(
            `Unhandled annotation: ${JSON.stringify(_exhaustiveCheck)}`,
          );
        }
      }
    }
  }
}
```

When implementing file downloads for files generated by the Code Interpreter,
the `container_id` and `file_id` available in `providerMetadata` can be used
to retrieve the file content. For details, see the [Retrieve container file
content](https://platform.openai.com/docs/api-reference/container-files/retrieveContainerFileContent)
API.

#### Typed providerMetadata in Reasoning Parts

When using the Azure OpenAI Responses API, reasoning output parts can include provider metadata.
To handle this metadata in a type-safe way, use `AzureResponsesReasoningProviderMetadata`.

For reasoning parts, when `part.type === 'reasoning'`, the `providerMetadata` is provided in the form of `AzureResponsesReasoningProviderMetadata`.

This metadata includes the following fields:

- `itemId`\
  The ID of the reasoning item in the Responses API.
- `reasoningEncryptedContent` (optional)\
  Encrypted reasoning content (only returned when requested via `include: ['reasoning.encrypted_content']`).

```ts
import {
  azure,
  type AzureResponsesReasoningProviderMetadata,
  type OpenAILanguageModelResponsesOptions,
} from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('your-deployment-name'),
  prompt: 'How many "r"s are in the word "strawberry"?',
  providerOptions: {
    azure: {
      store: false,
      include: ['reasoning.encrypted_content'],
    } satisfies OpenAILanguageModelResponsesOptions,
  },
});

for (const part of result.content) {
  if (part.type === 'reasoning') {
    const providerMetadata = part.providerMetadata as
      | AzureResponsesReasoningProviderMetadata
      | undefined;

    const { itemId, reasoningEncryptedContent } = providerMetadata?.azure ?? {};
    console.log(itemId, reasoningEncryptedContent);
  }
}
```

#### Typed providerMetadata in Source Document Parts

For source document parts, when `part.type === 'source'` and `sourceType === 'document'`, the `providerMetadata` is provided as `AzureResponsesSourceDocumentProviderMetadata`.

This metadata is also a discriminated union with a required `type` field. Supported types include:

- `file_citation`
- `container_file_citation`
- `file_path`

Each type includes the identifiers required to work with the referenced resource, such as `fileId` and `containerId`.

```ts
import {
  azure,
  type AzureResponsesSourceDocumentProviderMetadata,
} from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure('gpt-4.1-mini'),
  prompt:
    'Create a program that generates five random numbers between 1 and 100 with two decimal places, and show me the execution results. Also save the result to a file.',
  tools: {
    code_interpreter: azure.tools.codeInterpreter(),
    web_search: azure.tools.webSearch({}),
    file_search: azure.tools.fileSearch({ vectorStoreIds: ['vs_1234'] }), // requires a configured vector store
  },
});

for (const part of result.content) {
  if (part.type === 'source') {
    if (part.sourceType === 'document') {
      const providerMetadata = part.providerMetadata as
        | AzureResponsesSourceDocumentProviderMetadata
        | undefined;
      if (!providerMetadata) continue;
      const annotation = providerMetadata.azure;
      switch (annotation.type) {
        case 'file_citation':
          // file_citation is returned from file_search and provides:
          // properties: type, fileId and index
          // The filename can be accessed via part.filename.
          break;
        case 'container_file_citation':
          // container_file_citation is returned from code_interpreter and provides:
          // properties: type, containerId and fileId
          // The filename can be accessed via part.filename.
          break;
        case 'file_path':
          // file_path provides:
          // properties: type, fileId and index
          break;
        default: {
          const _exhaustiveCheck: never = annotation;
          throw new Error(
            `Unhandled annotation: ${JSON.stringify(_exhaustiveCheck)}`,
          );
        }
      }
    }
  }
}
```

Annotations in text parts follow the OpenAI Responses API specification and
therefore use snake\_case properties (e.g. `file_id`, `container_id`). In
contrast, `providerMetadata` for source document parts is normalized by the
SDK to camelCase (e.g. `fileId`, `containerId`). Fields that depend on the
original text content, such as `start_index` and `end_index`, are omitted, as
are fields like `filename` that are directly available on the source object.

### Completion Models

You can create models that call the completions API using the `.completion()` factory method.
The first argument is the model id.
Currently only `gpt-35-turbo-instruct` is supported.

```ts
const model = azure.completion('your-gpt-35-turbo-instruct-deployment');
```

OpenAI completion models support also some model specific settings that are not part of the [standard call settings](/docs/ai-sdk-core/settings).
You can pass them as an options argument:

```ts
import {
  azure,
  type OpenAILanguageModelCompletionOptions,
} from '@ai-sdk/azure';
import { generateText } from 'ai';

const result = await generateText({
  model: azure.completion('your-gpt-35-turbo-instruct-deployment'),
  prompt: 'Write a haiku about coding.',
  providerOptions: {
    openai: {
      echo: true, // optional, echo the prompt in addition to the completion
      logitBias: {
        // optional likelihood for specific tokens
        '50256': -100,
      },
      suffix: 'some text', // optional suffix that comes after a completion of inserted text
      user: 'test-user', // optional unique user identifier
    } satisfies OpenAILanguageModelCompletionOptions,
  },
});
```

The following optional provider options are available for Azure OpenAI completion models:

- **echo**: *boolean*

  Echo back the prompt in addition to the completion.

- **logitBias** *Record\<number, number>*

  Modifies the likelihood of specified tokens appearing in the completion.

  Accepts a JSON object that maps tokens (specified by their token ID in
  the GPT tokenizer) to an associated bias value from -100 to 100. You
  can use this tokenizer tool to convert text to token IDs. Mathematically,
  the bias is added to the logits generated by the model prior to sampling.
  The exact effect will vary per model, but values between -1 and 1 should
  decrease or increase likelihood of selection; values like -100 or 100
  should result in a ban or exclusive selection of the relevant token.

  As an example, you can pass `{"50256": -100}` to prevent the \<|endoftext|>
  token from being generated.

- **logprobs** *boolean | number*

  Return the log probabilities of the tokens. Including logprobs will increase
  the response size and can slow down response times. However, it can
  be useful to better understand how the model is behaving.

  Setting to true will return the log probabilities of the tokens that
  were generated.

  Setting to a number will return the log probabilities of the top n
  tokens that were generated.

- **suffix** *string*

  The suffix that comes after a completion of inserted text.

- **user** *string*

  A unique identifier representing your end-user, which can help OpenAI to
  monitor and detect abuse. Learn more.

## Embedding Models

You can create models that call the Azure OpenAI embeddings API
using the `.embedding()` factory method.

```ts
const model = azure.embedding('your-embedding-deployment');
```

Azure OpenAI embedding models support several additional settings.
You can pass them as an options argument:

```ts
import { azure, type OpenAIEmbeddingModelOptions } from '@ai-sdk/azure';
import { embed } from 'ai';

const { embedding } = await embed({
  model: azure.embedding('your-embedding-deployment'),
  value: 'sunny day at the beach',
  providerOptions: {
    openai: {
      dimensions: 512, // optional, number of dimensions for the embedding
      user: 'test-user', // optional unique user identifier
    } satisfies OpenAIEmbeddingModelOptions,
  },
});
```

The following optional provider options are available for Azure OpenAI embedding models:

- **dimensions**: *number*

  The number of dimensions the resulting output embeddings should have.
  Only supported in text-embedding-3 and later models.

- **user** *string*

  A unique identifier representing your end-user, which can help OpenAI to
  monitor and detect abuse. Learn more.

## Image Models

You can create models that call the Azure OpenAI image generation API using the `.image()` factory method. The first argument is your deployment name.
MAI-Image models use the [MAI image API](#mai-image) instead.

```ts
const model = azure.image('your-dalle-deployment-name');
```

Azure OpenAI image models support several additional settings. You can pass them as `providerOptions.openai` when generating the image:

```ts
import { azure } from '@ai-sdk/azure';
import type { OpenAIImageModelGenerationOptions } from '@ai-sdk/openai';
import { generateImage } from 'ai';

await generateImage({
  model: azure.image('your-dalle-deployment-name'),
  prompt: 'A photorealistic image of a cat astronaut floating in space',
  size: '1024x1024', // '1024x1024', '1792x1024', or '1024x1792' for DALL-E 3
  providerOptions: {
    openai: {
      user: 'test-user', // optional unique user identifier
    } satisfies OpenAIImageModelGenerationOptions,
  },
});
```

### Example

You can use Azure OpenAI image models to generate images with the `generateImage` function:

```ts
import { azure } from '@ai-sdk/azure';
import { generateImage } from 'ai';

const { image } = await generateImage({
  model: azure.image('your-dalle-deployment-name'),
  prompt: 'A photorealistic image of a cat astronaut floating in space',
  size: '1024x1024', // '1024x1024', '1792x1024', or '1024x1792' for DALL-E 3
});

// image contains the URL or base64 data of the generated image
console.log(image);
```

### Model Capabilities

Azure OpenAI supports DALL-E 2 and DALL-E 3 models through deployments. The capabilities depend on which model version your deployment is using:

| Model Version | Sizes                           |
| ------------- | ------------------------------- |
| DALL-E 3      | 1024x1024, 1792x1024, 1024x1792 |
| DALL-E 2      | 256x256, 512x512, 1024x1024     |

Azure deployment names are user-defined and do not identify the backing model.
Consequently, `supportsFileInputs` and `supportsMaskInputs` are `undefined`
(unknown) for Azure image model instances. If your application knows the
capabilities of a deployment, you can advertise them with the
`overrideSupportsFileInputs` and `overrideSupportsMaskInputs` options of
[`wrapImageModel`](/docs/reference/ai-sdk-core/wrap-image-model).

DALL-E models do not support the `aspectRatio` parameter. Use the `size`
parameter instead.

When creating your Azure OpenAI deployment, make sure to set the DALL-E model
version you want to use.

### MAI-Image

MAI-Image models (`MAI-Image-2.6`, `MAI-Image-2.6-Flash`, `MAI-Image-2.5`,
`MAI-Image-2.5-Flash`, `MAI-Image-2.5-Pro`) use the MAI image API at
`https://{resourceName}.services.ai.azure.com/mai/v1` (override with
`maiBaseURL`). Deployments named after the model are detected automatically,
case-insensitively. For other deployment names, set
`providerOptions.azure.api` to `'mai'`.

```ts
import { azure, type AzureImageModelOptions } from '@ai-sdk/azure';
import { generateImage } from 'ai';

const { image, usage } = await generateImage({
  model: azure.image('MAI-Image-2.6'),
  prompt: 'A watercolor of three flowers on a blue background',
  size: '1536x1024',
  providerOptions: {
    azure: {
      webGrounding: true,
    } satisfies AzureImageModelOptions,
  },
});
```

Pass reference images to edit or combine them (up to five JPEG or PNG
images). Masks are not supported.

```ts
const { image } = await generateImage({
  model: azure.image('MAI-Image-2.6-Flash'),
  prompt: {
    text: 'Put the product from the first image into the scene from the second',
    images: [productImage, sceneImage],
  },
});
```

Each request returns one PNG image; `generateImage` sends one request per image.
`size` is sent as `width` and `height`. Each side must be at least 768 pixels,
and the total pixel count at most 2,359,296 for MAI-Image-2.6 models and
1,048,576 for MAI-Image-2.5 models. Without `size`, `aspectRatio` is mapped to
dimensions of about one megapixel; without either, the model returns 1024x1024.
`seed` is not supported. Token usage is returned in `usage`, with the input
text and image token split in `providerMetadata.azure.images`.

The following provider options are available:

- **api** *'mai' | 'openai'*

  API to use. Defaults to `'mai'` for MAI-Image models, `'openai'` otherwise.

- **autoAspectRatio** *boolean*

  Let the model choose the output aspect ratio from the prompt and reference
  images. MAI-Image-2.6 models only.

- **webGrounding** *boolean*

  Ground generation in Bing web search results. MAI-Image-2.6 models only.

## Transcription Models

You can create models that call the Azure OpenAI or Azure Speech transcription API using the `.transcription()` factory method.

The first argument is the model id e.g. `whisper-1`.

```ts
const model = azure.transcription('whisper-1');
```

### MAI-Transcribe

MAI-Transcribe models are multilingual speech-to-text models from Microsoft AI, served through Azure.
The following model IDs use the Azure Speech API. They are matched case-insensitively
and sent to Azure under their Azure model names:

| Model ID             | Azure model          | Notes                                |
| -------------------- | -------------------- | ------------------------------------ |
| `mai-transcribe-2`   | `MAI-Transcribe-2`   | Supports every option below.         |
| `mai-transcribe-1.5` | `MAI-Transcribe-1.5` | Supports `locales` and `phraseList`. |

`mai-transcribe-2-streaming` uses the MAI realtime API; see
[MAI-Transcribe-2-Streaming](#mai-transcribe-2-streaming). All other IDs use the
OpenAI API by default, including custom deployment names.

```ts
import { azure, type AzureTranscriptionModelOptions } from '@ai-sdk/azure';
import { transcribe } from 'ai';
import { readFile } from 'fs/promises';

const result = await transcribe({
  model: azure.transcription('mai-transcribe-2'),
  audio: await readFile('audio.wav'),
  providerOptions: {
    azure: {
      timestamps: 'word',
      diarization: { enabled: true },
      transcribeStyle: 'clean',
    } satisfies AzureTranscriptionModelOptions,
  },
});
```

MAI-Transcribe models require a Microsoft Foundry (Speech) resource in a region where they are available:
`centralindia`, `eastus`, `northeurope`, `southeastasia`, `westus`, or `westus2`
(see [Speech service regions](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/regions?tabs=llmspeech)).
Resources in other regions reject the request.
Set `AZURE_RESOURCE_NAME` and `AZURE_API_KEY` to that resource's name and key,
or pass `resourceName` and `apiKey` to `createAzure`. `tokenProvider`, custom headers,
and custom fetch are also supported. Keys are sent as `Ocp-Apim-Subscription-Key`.

Speech requests use `https://{resourceName}.cognitiveservices.azure.com/speechtotext/transcriptions:transcribe`
with API version `2025-10-15`. Use `speechBaseURL` to supply a different Speech URL prefix
(without `/speechtotext/transcriptions:transcribe`), for example a regional endpoint:

```ts
import { createAzure } from '@ai-sdk/azure';

const azure = createAzure({
  speechBaseURL: 'https://eastus.api.cognitive.microsoft.com',
  apiKey: process.env.AZURE_SPEECH_API_KEY,
});
```

Speech requests do not use `baseURL`, `apiVersion`, or `useDeploymentBasedUrls`;
those settings only apply to Azure OpenAI models.

The following options are available through `providerOptions.azure`:

- **api** *'openai' | 'speech'*
  Overrides model-based API selection for this request.
  Set `openai` for an OpenAI deployment named after one of the model IDs above, or `speech` to
  send another model ID to Speech. Other Speech model IDs are sent unchanged.

- **timestamps** *'word' | 'segment' | 'none'*
  Timing granularity. For MAI-Transcribe-2 the AI SDK defaults to `segment` so that results
  include timed segments (Azure's own default is `none`). `segment` returns one segment
  per sentence or speaker turn, `word` additionally returns word timing in provider
  metadata, and `none` returns a single segment that spans the whole audio.
  MAI-Transcribe-1.5 only supports `none`, so the AI SDK does not send a default for it.

- **transcribeStyle** *'verbatim' | 'clean'*
  `verbatim` keeps fillers and false starts, `clean` removes them. Defaults to `verbatim`.
  `clean` requires MAI-Transcribe-2.

- **locales** *string\[]*
  Exactly one language code, such as `['en']`. This is a strong hint; omit it for
  automatic language detection and code switching.

- **diarization** *object*
  Set `enabled` to `true` to identify speakers. Speaker IDs are returned in
  provider metadata. Requires MAI-Transcribe-2. `maxSpeakers` is not supported.

- **phraseList** *object*
  Set `phrases` to a list of names and domain terms to bias recognition toward them.

Explicit `api` takes precedence over the model ID. Existing OpenAI transcription
options remain under `providerOptions.openai`. Speech-only Azure options produce
warnings when used with the OpenAI API. Unknown `providerOptions.azure` keys
(for example `diarization.maxSpeakers`) are rejected before the request is sent.
Options that a model does not support, such as `timestamps: 'word'` with
MAI-Transcribe-1.5, are sent unchanged, and Azure rejects the request with an
error that names the option.

Results include transcript text, timed segments, duration, and an ISO-639-1
language code when the reported phrase locales identify one language. Mixed-language
results, and languages without an ISO-639-1 code such as Filipino (`fil`) or
Cantonese (`yue`), leave `language` undefined. Speaker IDs, exact locales, and word
timing are preserved in `providerMetadata.azure.phrases`; use the exported
`AzureTranscriptionProviderMetadata` type to access them. Phrase timing is in
milliseconds in metadata and seconds in normalized `segments`.

MAI-Transcribe models are file transcription models: they accept WAV, MP3, or FLAC files
shorter than 2 hours and smaller than 250 MB, and do not support streaming
transcription; use [MAI-Transcribe-2-Streaming](#mai-transcribe-2-streaming) to stream.
The models are in public preview. See
[Azure's MAI-Transcribe guide](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/mai-transcribe)
for supported languages and diarization limits.

AI Gateway forwards these provider options, including `azure.api`.

### MAI-Transcribe-2-Streaming

MAI-Transcribe-2-Streaming is a low-latency streaming speech-to-text model from Microsoft AI.
`azure.transcription('mai-transcribe-2-streaming')` streams audio to the MAI realtime API
(`wss://{resourceName}.services.ai.azure.com/mai/v1/realtime`) with
[`experimental_streamTranscribe`](/docs/ai-sdk-core/transcription#streaming-transcription).
The model ID is sent to Azure as the Foundry deployment name, so deploy the model
as `mai-transcribe-2-streaming`, or set `api: 'mai'` for other deployment names.

```ts
import {
  createAzure,
  type AzureOpenAIProviderSettings,
  type AzureTranscriptionModelOptions,
} from '@ai-sdk/azure';
import { experimental_streamTranscribe as streamTranscribe } from 'ai';
import { WebSocket } from 'ws';

const azure = createAzure({
  // `ws`'s WebSocket type differs from the DOM-style WebSocketConstructor.
  webSocket: WebSocket as unknown as AzureOpenAIProviderSettings['webSocket'],
});

const result = streamTranscribe({
  model: azure.transcription('mai-transcribe-2-streaming'),
  audio, // ReadableStream of 16-bit mono PCM chunks
  inputAudioFormat: { type: 'audio/pcm', rate: 24000 },
  providerOptions: {
    azure: { language: 'en' } satisfies AzureTranscriptionModelOptions,
  },
});

for await (const part of result.fullStream) {
  if (part.type === 'transcript-delta') {
    process.stdout.write(part.delta);
  }
}
```

The model requires a Microsoft Foundry resource with a MAI-Transcribe-2-Streaming
deployment in a supported region, such as `centralus`.
Input audio must be 16-bit mono PCM (`audio/pcm`) at 16000 or 24000 Hz; the default is 24000 Hz.

The stream emits `transcript-delta` parts for finalized text and `transcript-partial`
parts for the provisional text that follows the latest delta. MAI does not detect
pauses on the server, so the stream commits once when the input audio ends and then
emits a `transcript-final` part and the finished transcript. `durationInSeconds` is
computed from the streamed audio.

The following options are available through `providerOptions.azure`:

- **api** *'openai' | 'speech' | 'mai'*
  Set `mai` to stream with a deployment that has a different name.

- **language** *string*
  Language hint such as `en`. Omit for automatic language detection.

File transcription options such as `timestamps` produce warnings when streaming.
MAI-Transcribe-2-Streaming does not support file transcription.

### OpenAI transcription

If you encounter a "DeploymentNotFound" error with transcription models,
try enabling deployment-based URLs:

```ts
const azure = createAzure({
  useDeploymentBasedUrls: true,
  apiVersion: '2025-04-01-preview',
});
```

This uses the legacy endpoint format which may be required for certain Azure OpenAI deployments.
When using useDeploymentBasedUrls, the default api-version is not valid. You must set it to `2025-04-01-preview` or an earlier value.

You can also pass additional provider-specific options using the `providerOptions` argument. For example, supplying the input language in ISO-639-1 (e.g. `en`) format will improve accuracy and latency.

```ts {6}
import { transcribe } from 'ai';
import { azure, type OpenAITranscriptionModelOptions } from '@ai-sdk/azure';
import { readFile } from 'fs/promises';

const result = await transcribe({
  model: azure.transcription('whisper-1'),
  audio: await readFile('audio.mp3'),
  providerOptions: {
    openai: {
      language: 'en',
    } satisfies OpenAITranscriptionModelOptions,
  },
});
```

The following provider options are available:

- **timestampGranularities** *string\[]*
  The granularity of the timestamps in the transcription.
  Defaults to `['segment']`.
  Possible values are `['word']`, `['segment']`, and `['word', 'segment']`.
  Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency.

- **language** *string*
  The language of the input audio. Supplying the input language in ISO-639-1 format (e.g. 'en') will improve accuracy and latency.
  Optional.

- **prompt** *string*
  An optional text to guide the model's style or continue a previous audio segment. The prompt should match the audio language.
  Optional.

- **temperature** *number*
  The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.
  Defaults to 0.
  Optional.

- **include** *string\[]*
  Additional information to include in the transcription response.

### Model Capabilities

| Model                        | Transcription | Duration | Segments | Language |
| ---------------------------- | ------------- | -------- | -------- | -------- |
| `whisper-1`                  | ✓             | ✓        | ✓        | ✓        |
| `gpt-4o-mini-transcribe`     | ✓             | ✗        | ✗        | ✗        |
| `gpt-4o-transcribe`          | ✓             | ✗        | ✗        | ✗        |
| `mai-transcribe-2`           | ✓             | ✓        | ✓        | ✓        |
| `mai-transcribe-1.5`         | ✓             | ✓        | ✓        | ✓        |
| `mai-transcribe-2-streaming` | ✓ (streaming) | ✓        | ✗        | ✗        |

## Speech Models

You can create models that call the Azure OpenAI speech API or Azure Speech text to speech using the `.speech()` factory method.

The first argument is your deployment name for the text-to-speech model (e.g., `tts-1`),
or a [MAI-Voice](#mai-voice) model ID.

```ts
const model = azure.speech('your-tts-deployment-name');
```

### Example

```ts
import { azure } from '@ai-sdk/azure';
import { generateSpeech } from 'ai';

const result = await generateSpeech({
  model: azure.speech('your-tts-deployment-name'),
  text: 'Hello, world!',
  voice: 'alloy', // OpenAI voice ID
});
```

You can also pass additional provider-specific options using the `providerOptions` argument:

```ts
import { azure, type OpenAISpeechModelOptions } from '@ai-sdk/azure';
import { generateSpeech } from 'ai';

const result = await generateSpeech({
  model: azure.speech('your-tts-deployment-name'),
  text: 'Hello, world!',
  voice: 'alloy',
  providerOptions: {
    openai: {
      speed: 1.2,
    } satisfies OpenAISpeechModelOptions,
  },
});
```

The following provider options are available:

- **instructions** *string*
  Control the voice of your generated audio with additional instructions e.g. "Speak in a slow and steady tone".
  Does not work with `tts-1` or `tts-1-hd`.
  Optional.

- **speed** *number*
  The speed of the generated audio.
  Select a value from 0.25 to 4.0.
  Defaults to 1.0.
  Optional.

### Model Capabilities

Azure OpenAI supports TTS models through deployments. The capabilities depend on which model version your deployment is using:

| Model Version     | Instructions |
| ----------------- | ------------ |
| `tts-1`           | ✗            |
| `tts-1-hd`        | ✗            |
| `gpt-4o-mini-tts` | ✓            |

### MAI-Voice

MAI-Voice models are multilingual text-to-speech models from Microsoft AI, served through Azure.
The following model IDs use the Azure Speech API:

| Model ID              | Notes                                         |
| --------------------- | --------------------------------------------- |
| `mai-voice-2.1-flash` | Low latency, for voice agents and assistants. |
| `mai-voice-2.1`       | Highest fidelity, for long-form narration.    |
| `mai-voice-2-flash`   | Low latency, for voice agents and assistants. |
| `mai-voice-2`         | Highest fidelity, for long-form narration.    |

All other IDs use the OpenAI API by default, including custom deployment names.

```ts
import { azure, type AzureSpeechModelOptions } from '@ai-sdk/azure';
import { generateSpeech } from 'ai';

const result = await generateSpeech({
  model: azure.speech('mai-voice-2-flash'),
  text: 'Thanks for calling! Your order shipped this morning.',
  voice: 'en-US-Ethan',
  providerOptions: {
    azure: { style: 'excited' } satisfies AzureSpeechModelOptions,
  },
});
```

MAI-Voice models require a Microsoft Foundry (Speech) resource in a region where they are available
(see [Speech service regions](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/regions)).
They use the same settings as [MAI-Transcribe](#mai-transcribe): `resourceName` (or `AZURE_RESOURCE_NAME`),
`apiKey` (or `AZURE_API_KEY`), `tokenProvider`, and `speechBaseURL`.

- **voice** is a prebuilt voice ID that includes its locale, such as `en-US-Harper`
  (the default), `de-DE-Mia`, or `es-MX-Valeria`. The voice locale selects the language.
  Full Azure voice names such as `es-MX-Valeria:MAI-Voice-2` are also accepted. Available
  voices vary by model; see
  [Azure's MAI-Voice guide](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/mai-voices).
- **language** picks a default voice when `voice` is not set (see the table below). Other
  languages and `auto` use `en-US-Harper` with a warning. When `voice` is set, its locale
  selects the language, and a conflicting `language` produces a warning.
- **outputFormat** accepts `mp3` (default, 24 kHz), `wav`, `pcm` (headerless 24 kHz, 16-bit, mono), `opus` (Ogg),
  or any Azure `X-Microsoft-OutputFormat` value such as `audio-48khz-192kbitrate-mono-mp3`.
  Other values fall back to `mp3` with a warning. Azure labels raw formats such as `pcm` as `audio/basic`.
- **speed** is a rate multiplier, for example `0.5` for half speed or `2` for double speed.
- `instructions` is not supported and produces a warning.

| Language | Default voice   | Language | Default voice |
| -------- | --------------- | -------- | ------------- |
| `de`     | `de-DE-Mia`     | `nl`     | `nl-NL-Fleur` |
| `en`     | `en-US-Harper`  | `pt`     | `pt-BR-Luana` |
| `es`     | `es-MX-Valeria` | `ro`     | `ro-RO-Elena` |
| `fr`     | `fr-FR-Soleil`  | `ru`     | `ru-RU-Masha` |
| `hi`     | `hi-IN-Kavya`   | `th`     | `th-TH-Krit`  |
| `hu`     | `hu-HU-Lilla`   | `tr`     | `tr-TR-Elif`  |
| `it`     | `it-IT-Rosa`    | `zh`     | `zh-CN-Mei`   |
| `ko`     | `ko-KR-Haena`   |          |               |

The following options are available through `providerOptions.azure`:

- **api** *'openai' | 'speech'*
  Overrides model-based API selection for this request.
  Set `openai` for an OpenAI deployment named after one of the model IDs above, or `speech` to
  send another model ID to Speech.

- **style** *string*
  Speaking style, such as `excited` or `whispering`. Supported styles vary by voice and model.

- **styleDegree** *number*
  Style intensity from 0.01 to 2. Azure defaults to 1. Requires `style`.

Text is always spoken as plain text; SSML input is not supported.
The models are in public preview. AI Gateway forwards these provider options, including `azure.api`.

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)