Skip to the swatches
Infoubat

Sample No. 0201

Connect a Custom Model to the GitHub Copilot SDK with C#

AI & ML Bruno Capuano

A .NET 10 sample routes Copilot SDK inference to Microsoft Foundry, using Entra ID by default or an API key when configured.

Connect a Custom Model to the GitHub Copilot SDK with C#

The GitHub Copilot SDK can keep its agent runtime while sending model requests to a provider you choose. That separation is the useful part of this C# sample: your application retains the SDK’s client, session and agent configuration, while ProviderConfig directs inference to a Microsoft Foundry deployment.

🚀

The example is a .NET 10 console app that makes one model request. It uses Microsoft Foundry through an OpenAI-compatible Responses API endpoint, with Microsoft Entra ID as the default authentication path and an API key as an option. The same general approach can work with other providers supported by the SDK, including OpenAI, Anthropic, Ollama, Foundry Local and OpenAI-compatible endpoints such as vLLM or LiteLLM.

That distinction helps set expectations: bringing your own model provider doesn’t remove the Copilot runtime. The sample still starts the local Copilot CLI process; it changes where the runtime sends the model request. Here, “BYOK” means bringing your own provider and credentials for inference. It doesn’t refer to encryption keys.

A small baseline for model routing

The sample deliberately disables tools, skills, configuration discovery and host Git operations. That keeps the first run focused on a single question: can a Copilot SDK session reach the configured deployment and return an answer? Once that path works, developers can add capabilities individually and more easily identify which component causes a problem.

The complete sample is available in the Generative AI for Beginners .NET repository. Its project references GitHub.Copilot.SDK for the .NET client, Azure.Identity for Azure CLI authentication, and Microsoft configuration packages for loading local User Secrets. The project targets .NET 10.

Diagram of a .NET app routing Copilot SDK requests to Microsoft Foundry

The application keeps the Copilot runtime and model provider as separate components.

Configure the deployment and endpoint

The application reads three values from User Secrets: a deployment name, a resource endpoint and, optionally, an API key. The deployment and endpoint are required. The deployment must support the Responses API because the provider configuration selects WireApi = "responses".

The sample uses the repository’s existing AzureOpenAI settings. In practice, AzureOpenAI:Deployment identifies the model deployment, while AzureOpenAI:Endpoint supplies its resource URL. The optional AzureOpenAI:ApiKey determines whether authentication uses a key or the default Entra ID path.

The provider configuration is the central change:

var provider = new ProviderConfig
{
    Type = "openai",
    BaseUrl = NormalizeEndpoint(endpoint),
    WireApi = "responses",
    ModelId = modelName,
    WireModel = modelName,
    MaxPromptTokens = 8000,
    MaxOutputTokens = 512
};

Type selects the OpenAI-compatible provider format, and BaseUrl points to the compatible API surface. WireApi chooses the Responses API. The runtime uses ModelId as its model identifier and sends WireModel to the provider. They have the same value in this example, but the two fields can differ in other integrations. The sample also sets prompt and output token limits to bound this small request.

There’s a practical caveat for reasoning deployments: the output token limit also counts reasoning tokens. With a limit of 512, a model may use the allowance before producing a visible answer. Teams using such a deployment should raise or remove the override and tune it against their workload.

The endpoint helper accepts either a resource URL or one that already ends with /openai/v1/. It checks that the URL is absolute, uses HTTPS and has a host, then normalizes the path. Validating the endpoint before creating a session makes configuration errors easier to catch than discovering them during a model request.

Choose an authentication path

When no API key is configured, the sample creates an AzureCliCredential and requests a token for the Cognitive Services scope. Its BearerTokenProvider callback lets the SDK request a token when needed, rather than requiring the application to manage a fixed token value itself. For this path, sign in with az login and ensure the identity has the Cognitive Services OpenAI User role on the resource.

If an API key is present, the sample adds it to the provider’s api-key header instead. That branch leaves the rest of the provider configuration intact and doesn’t require Azure CLI sign-in. Local development values can be stored with dotnet user-secrets; deployed applications should use configuration managed for their environment. The console reports the authentication mode but doesn’t print the endpoint or credential.

The Copilot runtime still does the orchestration

After configuring the provider, the app creates a CopilotClient with RuntimeConnection.ForStdio("copilot") and starts it. This launches the local Copilot runtime through the Copilot CLI. The provider controls model inference; the runtime still supplies the process that manages the client and session.

Running the sample therefore requires the .NET 10 SDK and GitHub Copilot CLI. For Entra ID authentication, it also requires Azure CLI. The API-key route doesn’t need Azure CLI. These dependencies matter when assessing setup effort: BYOK changes the inference destination, while the local runtime and its CLI remain part of this application’s setup.

The session sets a concise system message and disables tools, skills and Git operations. It also turns off configuration discovery and skill loading. That pared-back setup makes the model connection easier to inspect, though it doesn’t demonstrate how a larger agent behaves once those capabilities are enabled.

Send one prompt and inspect the response

The sample calls SendAndWaitAsync with a three-minute timeout, checks that the returned content isn’t empty, then prints it. Its default prompt asks what Microsoft Foundry is and how it relates to the Copilot SDK. A different prompt can be passed as a command-line argument, for example:

dotnet run -- "Explain BYOK in one sentence."

To run it, set the endpoint and deployment in User Secrets, then use az login and dotnet run for the default authentication route. The output shows the selected model, authentication mode, question and answer. It omits the endpoint and credentials.

🙂

What to try after the first response

The sample’s main value is a clear working baseline. It shows that the SDK runtime and the model provider can be configured separately, and that Entra ID can supply authentication without storing an API key in the project. The key-based path remains available when a deployment or environment calls for it.

Once the console returns a response, tools, MCP servers, skills, approvals and streaming are natural next areas to explore. Add them incrementally: this sample does not establish how those features interact with every provider or deployment. In particular, compatibility depends on the provider’s API surface and the selected model’s behavior, while token limits may need adjustment for the workload.

For the full implementation, see the BYOK C# sample and the Generative AI for Beginners .NET project. Further references include the GitHub Copilot SDK, Let’s Learn .NET, its event page, the Building Agentic AI Apps with GitHub Copilot SDK course, and Microsoft Foundry.

Source: Bruno Capuano · devblogs.microsoft.com

Pairs well with