Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Azure OpenAI SDK for .NET. Client library for Azure OpenAI and OpenAI services. Use for chat completions, embeddings, image generation, audio transcription, and assistants.
.claude/skills/azure-ai-openai-dotnet/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-20 | ✗→✓ | ▲ Improved | — | — |
| case-22 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✓→✓ | = Same ✓ | — | — |
| case-21 | ✓→✓ | = Same ✓ | — | — |
Client library for Azure OpenAI Service providing access to OpenAI models including GPT-4, GPT-4o, embeddings, DALL-E, and Whisper.
bashdotnet add package Azure.AI.OpenAI # For OpenAI (non-Azure) compatibility dotnet add package OpenAI
Current Version: 2.1.0 (stable)
bashAZURE_OPENAI_ENDPOINT=https://<resource-name>.openai.azure.com AZURE_OPENAI_API_KEY=<api-key> # For key-based auth AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o-mini # Your deployment name
AzureOpenAIClient (top-level)
├── GetChatClient(deploymentName) → ChatClient
├── GetEmbeddingClient(deploymentName) → EmbeddingClient
├── GetImageClient(deploymentName) → ImageClient
├── GetAudioClient(deploymentName) → AudioClient
└── GetAssistantClient() → AssistantClientcsharpusing Azure; using Azure.AI.OpenAI; AzureOpenAIClient client = new( new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!), new AzureKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!));
csharpusing Azure.Identity; using Azure.AI.OpenAI; AzureOpenAIClient client = new( new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!), new DefaultAzureCredential());
csharpusing Azure.Identity; using OpenAI; using OpenAI.Chat; using System.ClientModel.Primitives; #pragma warning disable OPENAI001 BearerTokenPolicy tokenPolicy = new( new DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"); ChatClient client = new( model: "gpt-4o-mini", authenticationPolicy: tokenPolicy, options: new OpenAIClientOptions() { Endpoint = new Uri("https://YOUR-RESOURCE.openai.azure.com/openai/v1") });
csharpusing Azure.AI.OpenAI; using OpenAI.Chat; AzureOpenAIClient azureClient = new( new Uri(endpoint), new DefaultAzureCredential()); ChatClient chatClient = azureClient.GetChatClient("gpt-4o-mini"); ChatCompletion completion = chatClient.CompleteChat( [ new SystemChatMessage("You are a helpful assistant."), new UserChatMessage("What is Azure OpenAI?") ]); Console.WriteLine(completion.Content[0].Text);
csharpChatCompletion completion = await chatClient.CompleteChatAsync( [ new SystemChatMessage("You are a helpful assistant."), new UserChatMessage("Explain cloud computing in simple terms.") ]); Console.WriteLine($"Response: {completion.Content[0].Text}"); Console.WriteLine($"Tokens used: {completion.Usage.TotalTokenCount}");
csharpawait foreach (StreamingChatCompletionUpdate update in chatClient.CompleteChatStreamingAsync(messages)) { if (update.ContentUpdate.Count > 0) { Console.Write(update.ContentUpdate[0].Text); } }
csharpChatCompletionOptions options = new() { MaxOutputTokenCount = 1000, Temperature = 0.7f, TopP = 0.95f, FrequencyPenalty = 0, PresencePenalty = 0 }; ChatCompletion completion = await chatClient.CompleteChatAsync(messages, options);
csharpList<ChatMessage> messages = new() { new SystemChatMessage("You are a helpful assistant."), new UserChatMessage("Hi, can you help me?"), new AssistantChatMessage("Of course! What do you need help with?"), new UserChatMessage("What's the capital of France?") }; ChatCompletion completion = await chatClient.CompleteChatAsync(messages); messages.Add(new AssistantChatMessage(completion.Content[0].Text));
csharpusing System.Text.Json; ChatCompletionOptions options = new() { ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat( jsonSchemaFormatName: "math_reasoning", jsonSchema: BinaryData.FromBytes(""" { "type": "object", "properties": { "steps": { "type": "array", "items": { "type": "object", "properties": { "explanation": { "type": "string" }, "output": { "type": "string" } }, "required": ["explanation", "output"], "additionalProperties": false } }, "final_answer": { "type": "string" } }, "required": ["steps", "final_answer"], "additionalProperties": false } """u8.ToArray()), jsonSchemaIsStrict: true) }; ChatCompletion completion = await chatClient.CompleteChatAsync( [new UserChatMessage("How can I solve 8x + 7 = -23?")], options); using JsonDocument json = JsonDocument.Parse(completion.Content[0].Text); Console.WriteLine($"Answer: {json.RootElement.GetProperty("final_answer")}");
csharpChatCompletionOptions options = new() { ReasoningEffortLevel = ChatReasoningEffortLevel.Low, MaxOutputTokenCount = 100000 }; ChatCompletion completion = await chatClient.CompleteChatAsync( [ new DeveloperChatMessage("You are a helpful assistant"), new UserChatMessage("Explain the theory of relativity") ], options);
csharpusing Azure.AI.OpenAI.Chat; #pragma warning disable AOAI001 ChatCompletionOptions options = new(); options.AddDataSource(new AzureSearchChatDataSource() { Endpoint = new Uri(searchEndpoint), IndexName = searchIndex, Authentication = DataSourceAuthentication.FromApiKey(searchKey) }); ChatCompletion completion = await chatClient.CompleteChatAsync( [new UserChatMessage("What health plans are available?")], options); ChatMessageContext context = completion.GetMessageContext(); if (context?.Intent is not null) { Console.WriteLine($"Intent: {context.Intent}"); } foreach (ChatCitation citation in context?.Citations ?? []) { Console.WriteLine($"Citation: {citation.Content}"); }
csharpusing OpenAI.Embeddings; EmbeddingClient embeddingClient = azureClient.GetEmbeddingClient("text-embedding-ada-002"); OpenAIEmbedding embedding = await embeddingClient.GenerateEmbeddingAsync("Hello, world!"); ReadOnlyMemory<float> vector = embedding.ToFloats(); Console.WriteLine($"Embedding dimensions: {vector.Length}");
csharpList<string> inputs = new() { "First document text", "Second document text", "Third document text" }; OpenAIEmbeddingCollection embeddings = await embeddingClient.GenerateEmbeddingsAsync(inputs); foreach (OpenAIEmbedding emb in embeddings) { Console.WriteLine($"Index {emb.Index}: {emb.ToFloats().Length} dimensions"); }
csharpusing OpenAI.Images; ImageClient imageClient = azureClient.GetImageClient("dall-e-3"); GeneratedImage image = await imageClient.GenerateImageAsync( "A futuristic city skyline at sunset", new ImageGenerationOptions { Size = GeneratedImageSize.W1024xH1024, Quality = GeneratedImageQuality.High, Style = GeneratedImageStyle.Vivid }); Console.WriteLine($"Image URL: {image.ImageUri}");
csharpusing OpenAI.Audio; AudioClient audioClient = azureClient.GetAudioClient("whisper"); AudioTranscription transcription = await audioClient.TranscribeAudioAsync( "audio.mp3", new AudioTranscriptionOptions { ResponseFormat = AudioTranscriptionFormat.Verbose, Language = "en" }); Console.WriteLine(transcription.Text);
csharpBinaryData speech = await audioClient.GenerateSpeechAsync( "Hello, welcome to Azure OpenAI!", GeneratedSpeechVoice.Alloy, new SpeechGenerationOptions { SpeedRatio = 1.0f, ResponseFormat = GeneratedSpeechFormat.Mp3 }); await File.WriteAllBytesAsync("output.mp3", speech.ToArray());
csharpChatTool getCurrentWeatherTool = ChatTool.CreateFunctionTool( functionName: "get_current_weather", functionDescription: "Get the current weather in a given location", functionParameters: BinaryData.FromString(""" { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["location"] } """)); ChatCompletionOptions options = new() { Tools = { getCurrentWeatherTool } }; ChatCompletion completion = await chatClient.CompleteChatAsync( [new UserChatMessage("What's the weather in Seattle?")], options); if (completion.FinishReason == ChatFinishReason.ToolCalls) { foreach (ChatToolCall toolCall in completion.ToolCalls) { Console.WriteLine($"Function: {toolCall.FunctionName}"); Console.WriteLine($"Arguments: {toolCall.FunctionArguments}"); } }
| Type | Purpose | |------|---------| | AzureOpenAIClient | Top-level client for Azure OpenAI | | ChatClient | Chat completions | | EmbeddingClient | Text embeddings | | ImageClient | Image generation (DALL-E) | | AudioClient | Audio transcription/TTS | | ChatCompletion | Chat response | | ChatCompletionOptions | Request configuration | | StreamingChatCompletionUpdate | Streaming response chunk | | ChatMessage | Base message type | | SystemChatMessage | System prompt | | UserChatMessage | User input | | AssistantChatMessage | Assistant response | | DeveloperChatMessage | Developer message (reasoning models) | | ChatTool | Function/tool definition | | ChatToolCall | Tool invocation request |
DefaultAzureCredentialCompleteChatStreamingAsync for better UXcompletion.Usage for cost managementcsharpusing Azure; try { ChatCompletion completion = await chatClient.CompleteChatAsync(messages); } catch (RequestFailedException ex) when (ex.Status == 429) { Console.WriteLine("Rate limited. Retry after delay."); await Task.Delay(TimeSpan.FromSeconds(10)); } catch (RequestFailedException ex) when (ex.Status == 400) { Console.WriteLine($"Bad request: {ex.Message}"); } catch (RequestFailedException ex) { Console.WriteLine($"Azure OpenAI error: {ex.Status} - {ex.Message}"); }
| SDK | Purpose | Install | |-----|---------|---------| | Azure.AI.OpenAI | Azure OpenAI client (this SDK) | dotnet add package Azure.AI.OpenAI | | OpenAI | OpenAI compatibility | dotnet add package OpenAI | | Azure.Identity | Authentication | dotnet add package Azure.Identity | | Azure.Search.Documents | AI Search for RAG | dotnet add package Azure.Search.Documents |
| Resource | URL | |----------|-----| | NuGet Package | https://www.nuget.org/packages/Azure.AI.OpenAI | | API Reference | https://learn.microsoft.com/dotnet/api/azure.ai.openai | | Migration Guide (1.0→2.0) | https://learn.microsoft.com/azure/ai-services/openai/how-to/dotnet-migration | | Quickstart | https://learn.microsoft.com/azure/ai-services/openai/quickstart | | GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/openai/Azure.AI.OpenAI |
This skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-20 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.