AI-powered features are becoming part of everyday application development. Developers can use language models to explain code, generate content, answer questions, and automate tasks that previously required manual work.
However, building these features into a C# application requires more than sending a prompt to an AI model. Applications also need to manage authentication, model configuration, conversation state, error handling, and access to external resources.
The GitHub Copilot SDK provides a way to integrate Copilot's agent capabilities into applications. Azure OpenAI provides access to hosted AI models through Azure-managed resources. These technologies serve different purposes, and their integration depends on the supported authentication methods, model providers, and APIs available in the versions being used.
In this article, we will examine how to approach this integration, what to verify before implementation, and how to structure a C# application for secure and maintainable AI functionality.
Understand the GitHub Copilot SDK and Azure OpenAI
Before writing code, it is important to understand the responsibilities of each component.
The GitHub Copilot SDK is designed to let applications use Copilot's agent capabilities programmatically. Depending on the SDK version and configuration, these capabilities can include conversations, tool execution, and interactions with supported model providers.
Azure OpenAI provides access to supported AI models through an Azure resource. Developers configure deployments, authentication, networking, and access controls through their Azure environment.
The main integration question is whether the selected Copilot SDK version supports Azure OpenAI as a model provider or allows the required provider configuration through a documented extension point.
Do not assume that the Copilot SDK automatically accepts an Azure OpenAI endpoint and API key. Its provider configuration and authentication requirements must be verified against the exact SDK version.
Requirement | GitHub Copilot SDK | Azure OpenAI |
|---|
Primary purpose | Integrate Copilot agent capabilities into applications | Provide hosted AI model access |
Model configuration | Depends on supported SDK providers and configuration | Uses an Azure resource and model deployment |
Authentication | Depends on the SDK's supported authentication flow | Supports documented Azure authentication mechanisms |
Tool execution | Depends on the available agent and tool APIs | Model API capabilities depend on the deployed model and endpoint |
Operational management | Requires appropriate Copilot configuration and access | Requires Azure resource, deployment, and access management |
If the SDK version you choose does not support Azure OpenAI directly, use a documented integration mechanism or call Azure OpenAI through its supported API independently. These are different implementation approaches and should not be presented as interchangeable.
Prepare the Development Environment
Start by confirming that your development environment supports the selected SDK and Azure services.
You will need:
- A supported .NET SDK.
- A GitHub account and the Copilot access required by the SDK.
- The GitHub Copilot SDK package and its documented prerequisites.
- An Azure subscription with access to an Azure OpenAI resource.
- A deployed model and the required permissions to invoke it.
- A development environment capable of storing credentials securely.
Create a new console application:
dotnet new console -n CopilotAzureDemo
cd CopilotAzureDemo
The console application will provide a simple environment for testing the integration before introducing it into an ASP.NET Core API or a larger application.
Install the Required SDK Package
Install the official GitHub Copilot SDK package using the package name and instructions provided by its current documentation.
For example, the installation process may use a command in this general form:
dotnet add package <Copilot-SDK-Package>
Replace the placeholder with the actual package identifier. Do not copy a placeholder directly into a terminal.
After installation, inspect the package documentation and sample applications. Confirm the available classes, initialization methods, authentication requirements, and supported model providers before implementing the integration.
This verification matters because SDK APIs can change between releases, and a configuration example for one language or SDK version may not apply to the C# package you are using.
Configure Azure OpenAI
Create or select an Azure OpenAI resource and deploy a model supported by your application requirements.
You will need the following configuration values:
- Azure OpenAI endpoint.
- Model deployment name.
- Authentication method.
- API version or client configuration required by the selected API.
Store these values in configuration rather than embedding them directly in application code.
For local development, environment variables provide a straightforward option.
In PowerShell, configure the endpoint and deployment name:
$env:AZURE_OPENAI_ENDPOINT = "https://your-resource.openai.azure.com/"
$env:AZURE_OPENAI_DEPLOYMENT = "your-model-deployment"
These values are examples. Replace them with your actual Azure resource endpoint and deployment name.
Avoid placing API keys directly in shell scripts that are committed to source control. For production workloads, prefer Microsoft Entra ID authentication with an appropriately scoped identity when supported by the selected client and endpoint.
Choose an Authentication Method
Azure OpenAI integrations commonly use either API keys or Microsoft Entra ID authentication, depending on the endpoint and client configuration.
API keys are relatively simple to configure, but they require secure storage, rotation, and access controls.
Microsoft Entra ID can provide identity-based access management without requiring an application to maintain a long-lived Azure OpenAI API key.
For a local development environment, an authenticated Azure developer identity may be appropriate when the required permissions are configured.
In production, use a managed identity where supported by the hosting environment and API configuration. Grant only the permissions necessary to invoke the intended model deployment.
The authentication method used for Azure OpenAI is separate from the authentication required by the GitHub Copilot SDK. Configuring one does not automatically authenticate the other.
Determine the Supported Integration Approach
There are two practical ways to design the application.
The first approach is to use the Copilot SDK directly with a provider that the selected SDK version officially supports. If Azure OpenAI is supported by that version, configure it according to the documented provider interface.
The second approach is to use the Copilot SDK for Copilot-specific agent capabilities while calling Azure OpenAI separately for model requests.
The second approach does not automatically combine Azure OpenAI requests with Copilot SDK conversation state or tool execution. If those capabilities are required, the application must implement the appropriate coordination layer.
For example, the application might define a small service interface:
public interface IAiAssistant
{
Task<string> GetResponseAsync(
string prompt,
CancellationToken cancellationToken);
}
This interface separates the rest of the application from the specific AI implementation.
You could implement it using a supported Copilot SDK integration or an Azure OpenAI client. The application can then change its implementation without requiring every controller or business service to know the details of model communication.
This abstraction is especially useful when the application needs to support multiple providers or when provider-specific capabilities differ.
Call Azure OpenAI from a C# Application
If the selected Copilot SDK version does not provide a supported Azure OpenAI provider integration, you can still call Azure OpenAI directly from C#.
The following example demonstrates the general structure of an HTTP request to an Azure OpenAI chat completions endpoint. It is an independent Azure OpenAI integration, not a Copilot SDK call.
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var endpoint = Environment.GetEnvironmentVariable(
"AZURE_OPENAI_ENDPOINT");
var deployment = Environment.GetEnvironmentVariable(
"AZURE_OPENAI_DEPLOYMENT");
var apiKey = Environment.GetEnvironmentVariable(
"AZURE_OPENAI_API_KEY");
if (string.IsNullOrWhiteSpace(endpoint) ||
string.IsNullOrWhiteSpace(deployment) ||
string.IsNullOrWhiteSpace(apiKey))
{
throw new InvalidOperationException(
"Azure OpenAI configuration is incomplete.");
}
using var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(60)
};
client.DefaultRequestHeaders.Add(
"api-key",
apiKey);
var requestBody = new
{
messages = new[]
{
new
{
role = "system",
content = "You are a helpful C# programming assistant."
},
new
{
role = "user",
content = "Explain dependency injection in C#."
}
}
};
var json = JsonSerializer.Serialize(requestBody);
var url =
$"{endpoint.TrimEnd('/')}/openai/deployments/" +
$"{Uri.EscapeDataString(deployment)}/chat/completions" +
"?api-version=<supported-api-version>";
using var content = new StringContent(
json,
Encoding.UTF8,
"application/json");
using var response = await client.PostAsync(
url,
content);
var responseBody = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine(responseBody);
Before running this example, replace the API version placeholder with a version supported by your Azure OpenAI resource and selected endpoint.
The example uses an API key to keep the HTTP request straightforward. A production application using Microsoft Entra ID should instead obtain and attach an appropriate bearer token through a supported authentication library.
The request includes system and user messages. The system message describes the assistant's role, while the user message contains the question.
The application serializes the request as JSON, sends it to the selected deployment, and reads the response.
For a production implementation, deserialize the response into a defined model instead of returning raw JSON. Also consider connection reuse through IHttpClientFactory, cancellation, bounded retries, response-size limits, and structured error handling.
Handle Errors and Rate Limits
AI services can return errors because of authentication failures, invalid deployment names, unsupported API versions, request limits, temporary service failures, or malformed requests.
A production client should distinguish between these conditions.
Error condition | Recommended response |
|---|
Authentication failure | Verify the credential, identity, and assigned permissions |
Invalid deployment | Confirm the deployment name and resource configuration |
Unsupported API version | Select a documented version supported by the endpoint |
Rate limit exceeded | Apply bounded retries and respect server-provided retry guidance |
Temporary server failure | Retry only when appropriate and within a defined limit |
Request timeout | Check service latency and request complexity |
Invalid request | Correct the request payload instead of repeatedly retrying |
Do not automatically retry every failure. Authentication and validation errors generally require configuration or request changes, while some temporary failures may be suitable for a bounded retry policy.
Also avoid logging API keys, bearer tokens, sensitive prompts, or complete model responses when they may contain confidential information.
Add AI Functionality to an ASP.NET Core API
Once the model call works in a small application, you can expose the functionality through an ASP.NET Core endpoint.
For example, the application could define an API that accepts a programming question and returns an AI-generated explanation.
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient<AzureAiService>();
var app = builder.Build();
app.MapPost(
"/api/assistant",
async (
AssistantRequest request,
AzureAiService ai,
CancellationToken cancellationToken) =>
{
if (string.IsNullOrWhiteSpace(request.Question))
{
return Results.BadRequest(
new { error = "A question is required." });
}
var answer = await ai.GetResponseAsync(
request.Question,
cancellationToken);
return Results.Ok(new AssistantResponse(answer));
});
app.Run();
public sealed record AssistantRequest(string Question);
public sealed record AssistantResponse(string Answer);
This example illustrates the endpoint structure, but it requires an AzureAiService implementation with the GetResponseAsync method. That service should contain the Azure OpenAI client configuration, request serialization, authentication, and response parsing.
In production, add request-size limits, authentication, authorization, rate limiting, and appropriate error handling. An unauthenticated AI endpoint can be abused to generate excessive model usage and unexpected costs.
If the application also uses Copilot SDK features, keep those responsibilities behind separate services unless there is a clear reason to combine them.
Best Practices for Production
Keep Credentials Out of Source Control
Use a secret store, managed identity, or another supported secure credential mechanism. Never commit API keys or access tokens.
Set Usage Limits
Configure request limits and monitor model consumption. Validate user input and avoid allowing clients to submit arbitrarily large prompts.
Separate Provider-Specific Code
Use interfaces and dependency injection to isolate model communication. This makes testing easier and reduces the impact of provider-specific changes.
Monitor Latency and Failures
Record request duration, status codes, and usage information where available. Avoid recording sensitive content unnecessarily.
Test Authentication and Failure Scenarios
Test expired credentials, missing configuration, rate limits, timeouts, and unavailable services. A successful response from the model is only one part of the application's behavior.
Common Mistakes to Avoid
One common mistake is assuming that Azure OpenAI can be configured as a Copilot SDK provider without checking whether the selected SDK version supports it.
Another is confusing GitHub authentication with Azure authentication. These are separate access-control systems with different credentials and permissions.
Hard-coding API keys is also dangerous because credentials can leak through source control, build logs, or diagnostic output.
Finally, avoid treating model output as trusted application data. Validate generated content before using it in database operations, executing commands, or making security-sensitive decisions.
Advantages and Limitations
Combining Copilot capabilities with Azure OpenAI can provide flexibility when an application needs both agent-oriented workflows and Azure-hosted model access.
Azure OpenAI offers centralized resource management and integration with Azure identity and security controls. A provider abstraction can also make an application easier to maintain.
However, the integration depends on the supported SDK capabilities and authentication model. Running two separate integrations can increase implementation complexity, and model access introduces latency, usage costs, and output variability.
The architecture should therefore be based on the actual capabilities required by the application rather than assuming that every SDK and model provider can be connected directly.
Summary
Using Azure OpenAI with the GitHub Copilot SDK in a C# application begins with verifying the supported integration model. The Copilot SDK and Azure OpenAI have different responsibilities, and their authentication and configuration requirements must be handled separately.
Prepare the development environment, configure the Azure resource securely, and confirm whether the selected SDK supports Azure OpenAI directly. If it does not, use a documented extension point or implement a separate Azure OpenAI client.
Finally, isolate AI communication behind a service interface, handle errors and rate limits, protect credentials, and validate generated output before using it in business-critical operations.
This approach provides a maintainable foundation for integrating AI into C# applications without relying on unsupported provider configurations.
Join the conversation! Your thoughts help the community grow.