.NET Aspire Azure OpenAI integration (Preview)

Includes: Hosting integration and Client integration

Azure OpenAI Service provides access to OpenAI's powerful language and embedding models with the security and enterprise promise of Azure. The .NET Aspire Azure OpenAI integration enables you to connect to Azure OpenAI Service or OpenAI's API from your .NET applications.

Hosting integration

The .NET Aspire Azure OpenAI hosting integration models Azure OpenAI resources as AzureOpenAIResource. To access these types and APIs for expressing them within your app host project, install the 📦 Aspire.Hosting.Azure.CognitiveServices NuGet package:

dotnet add package Aspire.Hosting.Azure.CognitiveServices

For more information, see dotnet add package or Manage package dependencies in .NET applications.

Add an Azure OpenAI resource

To add an AzureOpenAIResource to your app host project, call the AddAzureOpenAI method:

var builder = DistributedApplication.CreateBuilder(args);

var openai = builder.AddAzureOpenAI("openai");

builder.AddProject<Projects.ExampleProject>()
       .WithReference(openai);

// After adding all resources, run the app...

The preceding code adds an Azure OpenAI resource named openai to the app host project. The WithReference method passes the connection information to the ExampleProject project.

Important

When you call AddAzureOpenAI, it implicitly calls AddAzureProvisioning(IDistributedApplicationBuilder)—which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see Local provisioning: Configuration.

Add an Azure OpenAI deployment resource

To add an Azure OpenAI deployment resource, call the AddDeployment(IResourceBuilder<AzureOpenAIResource>, AzureOpenAIDeployment) method:

var builder = DistributedApplication.CreateBuilder(args);

var openai = builder.AddAzureOpenAI("openai");
openai.AddDeployment(
    new AzureOpenAIDeployment(
        name: "preview",
        modelName: "gpt-4.5-preview",
        modelVersion: "2025-02-27"));

builder.AddProject<Projects.ExampleProject>()
       .WithReference(openai)
       .WaitFor(openai);

// After adding all resources, run the app...

The preceding code:

  • Adds an Azure OpenAI resource named openai.
  • Adds an Azure OpenAI deployment resource named preview with a model name of gpt-4.5-preview. The model name must correspond to an available model in the Azure OpenAI service.

Generated provisioning Bicep

If you're new to Bicep, it's a domain-specific language for defining Azure resources. With .NET Aspire, you don't need to write Bicep by-hand, instead the provisioning APIs generate Bicep for you. When you publish your app, the generated Bicep provisions an Azure OpenAI resource with standard defaults.

@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param principalType string

param principalId string

resource openai 'Microsoft.CognitiveServices/accounts@2024-10-01' = {
  name: take('openai-${uniqueString(resourceGroup().id)}', 64)
  location: location
  kind: 'OpenAI'
  properties: {
    customSubDomainName: toLower(take(concat('openai', uniqueString(resourceGroup().id)), 24))
    publicNetworkAccess: 'Enabled'
    disableLocalAuth: true
  }
  sku: {
    name: 'S0'
  }
  tags: {
    'aspire-resource-name': 'openai'
  }
}

resource openai_CognitiveServicesOpenAIContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(openai.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a001fd3d-188f-4b5d-821b-7da978bf7442'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a001fd3d-188f-4b5d-821b-7da978bf7442')
    principalType: principalType
  }
  scope: openai
}

resource preview 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
  name: 'preview'
  properties: {
    model: {
      format: 'OpenAI'
      name: 'gpt-4.5-preview'
      version: '2025-02-27'
    }
  }
  sku: {
    name: 'Standard'
    capacity: 8
  }
  parent: openai
}

output connectionString string = 'Endpoint=${openai.properties.endpoint}'

The preceding Bicep is a module that provisions an Azure Cognitive Services resource with the following defaults:

  • location: The location of the resource group.
  • principalType: The principal type of the Cognitive Services resource.
  • principalId: The principal ID of the Cognitive Services resource.
  • openai: The Cognitive Services account resource.
    • kind: The kind of the resource, set to OpenAI.
    • properties: The properties of the resource.
      • customSubDomainName: The custom subdomain name for the resource, based on the unique string of the resource group ID.
      • publicNetworkAccess: Set to Enabled.
      • disableLocalAuth: Set to true.
    • sku: The SKU of the resource, set to S0.
  • openai_CognitiveServicesOpenAIContributor: The Cognitive Services resource owner, based on the build-in Azure Cognitive Services OpenAI Contributor role. For more information, see Azure Cognitive Services OpenAI Contributor.
  • preview: The deployment resource, based on the preview name.
    • properties: The properties of the deployment resource.
      • format: The format of the deployment resource, set to OpenAI.
      • modelName: The model name of the deployment resource, set to gpt-4.5-preview.
      • modelVersion: The model version of the deployment resource, set to 2025-02-27.
  • connectionString: The connection string, containing the endpoint of the Cognitive Services resource.

The generated Bicep is a starting point and can be customized to meet your specific requirements.

Customize provisioning infrastructure

All .NET Aspire Azure resources are subclasses of the AzureProvisioningResource type. This enables customization of the generated Bicep by providing a fluent API to configure the Azure resources—using the ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) API:

builder.AddAzureOpenAI("openai")
    .ConfigureInfrastructure(infra =>
    {
        var resources = infra.GetProvisionableResources();
        var account = resources.OfType<CognitiveServicesAccount>().Single();

        account.Sku = new CognitiveServicesSku
        {
            Tier = CognitiveServicesSkuTier.Enterprise,
            Name = "E0"
        };
        account.Tags.Add("ExampleKey", "Example value");
    });

The preceding code:

Connect to an existing Azure OpenAI service

You might have an existing Azure OpenAI service that you want to connect to. You can chain a call to annotate that your AzureOpenAIResource is an existing resource:

var builder = DistributedApplication.CreateBuilder(args);

var existingOpenAIName = builder.AddParameter("existingOpenAIName");
var existingOpenAIResourceGroup = builder.AddParameter("existingOpenAIResourceGroup");

var openai = builder.AddAzureOpenAI("openai")
                    .AsExisting(existingOpenAIName, existingOpenAIResourceGroup);

builder.AddProject<Projects.ExampleProject>()
       .WithReference(openai);

// After adding all resources, run the app...

For more information on treating Azure OpenAI resources as existing resources, see Use existing Azure resources.

Alternatively, instead of representing an Azure OpenAI resource, you can add a connection string to the app host. Which is a weakly-typed approach that's based solely on a string value. To add a connection to an existing Azure OpenAI service, call the AddConnectionString method:

var builder = DistributedApplication.CreateBuilder(args);

var openai = builder.ExecutionContext.IsPublishMode
    ? builder.AddAzureOpenAI("openai")
    : builder.AddConnectionString("openai");

builder.AddProject<Projects.ExampleProject>()
       .WithReference(openai);

// After adding all resources, run the app...

Note

Connection strings are used to represent a wide range of connection information, including database connections, message brokers, endpoint URIs, and other services. In .NET Aspire nomenclature, the term "connection string" is used to represent any kind of connection information.

The connection string is configured in the app host's configuration, typically under User Secrets, under the ConnectionStrings section:

{
  "ConnectionStrings": {
    "openai": "https://{account_name}.openai.azure.com/"
  }
}

For more information, see Add existing Azure resources with connection strings.

Client integration

To get started with the .NET Aspire Azure OpenAI client integration, install the 📦 Aspire.Azure.AI.OpenAI NuGet package in the client-consuming project, that is, the project for the application that uses the Azure OpenAI client.

dotnet add package Aspire.Azure.AI.OpenAI

Add an Azure OpenAI client

In the Program.cs file of your client-consuming project, use the AddAzureOpenAIClient(IHostApplicationBuilder, String, Action<AzureOpenAISettings>, Action<IAzureClientBuilder<AzureOpenAIClient,AzureOpenAIClientOptions>>) method on any IHostApplicationBuilder to register an OpenAIClient for dependency injection (DI). The AzureOpenAIClient is a subclass of OpenAIClient, allowing you to request either type from DI. This ensures code not dependent on Azure-specific features remains generic. The AddAzureOpenAIClient method requires a connection name parameter.

builder.AddAzureOpenAIClient(connectionName: "openai");

Tip

The connectionName parameter must match the name used when adding the Azure OpenAI resource in the app host project. For more information, see Add an Azure OpenAI resource.

After adding the OpenAIClient, you can retrieve the client instance using dependency injection:

public class ExampleService(OpenAIClient client)
{
    // Use client...
}

For more information, see:

Add Azure OpenAI client with registered IChatClient

If you're interested in using the IChatClient interface, with the OpenAI client, simply chain either of the following APIs to the AddAzureOpenAIClient method:

For example, consider the following C# code that adds an IChatClient to the DI container:

builder.AddAzureOpenAIClient(connectionName: "openai")
       .AddChatClient("deploymentName");

Similarly, you can add a keyed IChatClient with the following C# code:

builder.AddAzureOpenAIClient(connectionName: "openai")
       .AddKeyedChatClient("serviceKey", "deploymentName");

For more information on the IChatClient and its corresponding library, see Artificial intelligence in .NET (Preview).

Configure Azure OpenAI client settings

The .NET Aspire Azure OpenAI library provides a set of settings to configure the Azure OpenAI client. The AddAzureOpenAIClient method exposes an optional configureSettings parameter of type Action<AzureOpenAISettings>?. To configure settings inline, consider the following example:

builder.AddAzureOpenAIClient(
    connectionName: "openai",
    configureSettings: settings =>
    {
        settings.DisableTracing = true;

        var uriString = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
            ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");

        settings.Endpoint = new Uri(uriString);
    });

The preceding code sets the AzureOpenAISettings.DisableTracing property to true, and sets the AzureOpenAISettings.Endpoint property to the Azure OpenAI endpoint.

Configure Azure OpenAI client builder options

To configure the AzureOpenAIClientOptions for the client, you can use the AddAzureOpenAIClient method. This method takes an optional configureClientBuilder parameter of type Action<IAzureClientBuilder<OpenAIClient, AzureOpenAIClientOptions>>?. Consider the following example:

builder.AddAzureOpenAIClient(
    connectionName: "openai",
    configureClientBuilder: clientBuilder =>
    {
        clientBuilder.ConfigureOptions(options =>
        {
            options.UserAgentApplicationId = "CLIENT_ID";
        });
    });

The client builder is an instance of the IAzureClientBuilder<TClient,TOptions> type, which provides a fluent API to configure the client options. The preceding code sets the AzureOpenAIClientOptions.UserAgentApplicationId property to CLIENT_ID. For more information, see ConfigureOptions(ChatClientBuilder, Action<ChatOptions>).

Add Azure OpenAI client from configuration

Additionally, the package provides the AddOpenAIClientFromConfiguration(IHostApplicationBuilder, String) extension method to register an OpenAIClient or AzureOpenAIClient instance based on the provided connection string. This method follows these rules:

  • If the Endpoint attribute is empty or missing, an OpenAIClient instance is registered using the provided key, for example, Key={key};.
  • If the IsAzure attribute is true, an AzureOpenAIClient is registered; otherwise, an OpenAIClient is registered, for example, Endpoint={azure_endpoint};Key={key};IsAzure=true registers an AzureOpenAIClient, while Endpoint=https://localhost:18889;Key={key} registers an OpenAIClient.
  • If the Endpoint attribute contains ".azure.", an AzureOpenAIClient is registered; otherwise, an OpenAIClient is registered, for example, Endpoint=https://{account}.azure.com;Key={key};.

Consider the following example:

builder.AddOpenAIClientFromConfiguration("openai");

Tip

A valid connection string must contain at least an Endpoint or a Key.

Consider the following example connection strings and whether they register an OpenAIClient or AzureOpenAIClient:

Example connection string Registered client type
Endpoint=https://{account_name}.openai.azure.com/;Key={account_key} AzureOpenAIClient
Endpoint=https://{account_name}.openai.azure.com/;Key={account_key};IsAzure=false OpenAIClient
Endpoint=https://{account_name}.openai.azure.com/;Key={account_key};IsAzure=true AzureOpenAIClient
Endpoint=https://localhost:18889;Key={account_key} OpenAIClient

Add keyed Azure OpenAI clients

There might be situations where you want to register multiple OpenAIClient instances with different connection names. To register keyed Azure OpenAI clients, call the AddKeyedAzureOpenAIClient method:

builder.AddKeyedAzureOpenAIClient(name: "chat");
builder.AddKeyedAzureOpenAIClient(name: "code");

Important

When using keyed services, ensure that your Azure OpenAI resource configures two named connections, one for chat and one for code.

Then you can retrieve the client instances using dependency injection. For example, to retrieve the clients from a service:

public class ExampleService(
    [KeyedService("chat")] OpenAIClient chatClient,
    [KeyedService("code")] OpenAIClient codeClient)
{
    // Use clients...
}

For more information, see Keyed services in .NET.

Add keyed Azure OpenAI clients from configuration

The same functionality and rules exist for keyed Azure OpenAI clients as for the nonkeyed clients. You can use the AddKeyedOpenAIClientFromConfiguration(IHostApplicationBuilder, String) extension method to register an OpenAIClient or AzureOpenAIClient instance based on the provided connection string.

Consider the following example:

builder.AddKeyedOpenAIClientFromConfiguration("openai");

This method follows the same rules as detailed in the Add Azure OpenAI client from configuration.

Configuration

The .NET Aspire Azure OpenAI library provides multiple options to configure the Azure OpenAI connection based on the requirements and conventions of your project. Either a Endpoint or a ConnectionString is required to be supplied.

Use a connection string

When using a connection string from the ConnectionStrings configuration section, you can provide the name of the connection string when calling builder.AddAzureOpenAIClient:

builder.AddAzureOpenAIClient("openai");

The connection string is retrieved from the ConnectionStrings configuration section, and there are two supported formats:

Account endpoint

The recommended approach is to use an Endpoint, which works with the AzureOpenAISettings.Credential property to establish a connection. If no credential is configured, the DefaultAzureCredential is used.

{
  "ConnectionStrings": {
    "openai": "https://{account_name}.openai.azure.com/"
  }
}

For more information, see Use Azure OpenAI without keys.

Connection string

Alternatively, a custom connection string can be used:

{
  "ConnectionStrings": {
    "openai": "Endpoint=https://{account_name}.openai.azure.com/;Key={account_key};"
  }
}

In order to connect to the non-Azure OpenAI service, drop the Endpoint property and only set the Key property to set the API key.

Use configuration providers

The .NET Aspire Azure OpenAI integration supports Microsoft.Extensions.Configuration. It loads the AzureOpenAISettings from configuration by using the Aspire:Azure:AI:OpenAI key. Example appsettings.json that configures some of the options:

{
  "Aspire": {
    "Azure": {
      "AI": {
        "OpenAI": {
          "DisableTracing": false
        }
      }
    }
  }
}

For the complete Azure OpenAI client integration JSON schema, see Aspire.Azure.AI.OpenAI/ConfigurationSchema.json.

Use inline delegates

You can pass the Action<AzureOpenAISettings> configureSettings delegate to set up some or all the options inline, for example to disable tracing from code:

builder.AddAzureOpenAIClient(
    "openai",
    static settings => settings.DisableTracing = true);

You can also set up the OpenAIClientOptions using the optional Action<IAzureClientBuilder<OpenAIClient, OpenAIClientOptions>> configureClientBuilder parameter of the AddAzureOpenAIClient method. For example, to set the client ID for this client:

builder.AddAzureOpenAIClient(
    "openai",
    configureClientBuilder: builder => builder.ConfigureOptions(
        options => options.Diagnostics.ApplicationId = "CLIENT_ID"));

Observability and telemetry

.NET Aspire integrations automatically set up Logging, Tracing, and Metrics configurations, which are sometimes known as the pillars of observability. For more information about integration observability and telemetry, see .NET Aspire integrations overview. Depending on the backing service, some integrations may only support some of these features. For example, some integrations support logging and tracing, but not metrics. Telemetry features can also be disabled using the techniques presented in the Configuration section.

Logging

The .NET Aspire Azure OpenAI integration uses the following log categories:

  • Azure
  • Azure.Core
  • Azure.Identity

Tracing

The .NET Aspire Azure OpenAI integration emits tracing activities using OpenTelemetry for operations performed with the OpenAIClient.

Important

Tracing is currently experimental with this integration. To opt-in to it, set either the OPENAI_EXPERIMENTAL_ENABLE_OPEN_TELEMETRY environment variable to true or 1, or call AppContext.SetSwitch("OpenAI.Experimental.EnableOpenTelemetry", true)) during app startup.

See also