A diagram shows a terminal connecting through an AI agent to cloud model inference, secured by a token or API key.
Microsoft's .NET Blog has published a short C# walkthrough on pointing the GitHub Copilot SDK at your own model deployment. Bruno Capuano's sample is a small .NET 10 console app that sends one question to a Microsoft Foundry or Azure OpenAI deployment instead of GitHub-hosted models. It isn't a new SDK release. It's a worked example, and it clears up a common source of confusion: what "bring your own key" actually changes.

A diagram shows a terminal connecting through an AI agent to cloud model inference, secured by a token or API key. The key idea: runtime and inference are separate​

The Copilot SDK supplies the agent runtime, which covers the client, the session, the system message and the agent configuration. ProviderConfig only changes where model inference goes and how it authenticates.

"BYOK" here means bringing your own model endpoint and credentials. It does not mean customer-managed encryption keys or storage encryption.

BYOK also doesn't remove Copilot from the picture. The sample still launches the local Copilot CLI runtime through RuntimeConnection.ForStdio("copilot"), and that process does the orchestration. Only the destination of the model request changes.

GitHub's own documentation backs up the broader provider scope. It lists OpenAI and OpenAI-compatible endpoints, Microsoft Foundry and Azure OpenAI, Anthropic, Ollama, Foundry Local, and services such as vLLM and LiteLLM. It also says BYOK usage is tracked by your provider and doesn't count against Copilot premium-request quotas.

What you need before you start​

The sample is built around these pieces:

  • The .NET 10 SDK, so dotnet --version reports version 10.
  • The GitHub Copilot CLI, so copilot --version works.
  • The Azure CLI, but only for the default Entra ID path. The API-key path doesn't need it.
  • A model deployment that supports the Responses API, because the provider is configured with WireApi = "responses".
  • Pinned packages: GitHub.Copilot.SDK 1.0.11, Azure.Identity 1.21.0, and the Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.UserSecrets packages at 10.0.3.

Configuration comes from .NET User Secrets. The app requires AzureOpenAI:Deployment and AzureOpenAI:Endpoint. AzureOpenAI:ApiKey is optional.

How the provider is configured​

The core configuration sets these values:

  • Type = "openai", which selects the OpenAI-compatible provider shape.
  • BaseUrl, set to the normalized endpoint.
  • WireApi = "responses".
  • ModelId and WireModel, both set to the deployment name. They are separate properties because the runtime-facing model identifier and the provider-facing model name don't always match.
  • MaxPromptTokens = 8000 and MaxOutputTokens = 512, which keep the demo bounded.

Reasoning-model caveat: the output cap includes reasoning tokens as well as the visible answer. A 512-token limit can run out before any answer appears. If you use a reasoning deployment, raise or remove that override.

Endpoint helper: it accepts either a resource URL or one already ending in /openai/v1. It trims whitespace and requires an absolute HTTPS URL. Anything else throws an ArgumentException. If the URL doesn't already end in /openai/v1, the helper rebuilds it from the host plus /openai/v1/. It doesn't preserve any other path you supplied. That matters if your endpoint has a custom path.

Authentication: Entra ID first, API key as fallback​

Entra ID (default). If no key is configured, the sample creates an AzureCliCredential. It requests a token for the [url]https://cognitiveservices.azure.com/.default[/url] scope and returns it from a BearerTokenProvider callback. The SDK calls that callback when it needs a token, so your app doesn't manage a single token value.

The signed-in identity needs the Cognitive Services OpenAI User role on the resource. Then you run az login. The callback is marked experimental in the SDK, so the code suppresses the GHCP001 warning.

API key. If AzureOpenAI:ApiKey is set, the sample sends it in an api-key header and skips az login. You set it with dotnet user-secrets set. The console prints only the authentication mode. It never prints the endpoint or the credential.

GitHub's documentation describes how bearerTokenProvider fits into the SDK. One GitHub doc page says the SDK doesn't natively support Entra ID authentication and suggests a short-lived bearer token instead. Newer material describes a callback-based approach. GitHub's Azure managed identity guide uses a token provider callback so the runtime can request fresh tokens on demand. It leaves token caching and refresh timing to the Azure Identity SDK.

The timeline explains the difference. A Microsoft Agent Framework issue says SDK 1.0.11 adds ProviderConfig.bearer_token_provider and the BearerTokenProvider type. The SDK changelog shows the callback field was renamed from getBearerToken to bearerTokenProvider in v1.0.5.

There is a documentation inconsistency, though. The SDK's GitHub README FAQ still says BYOK uses key-based authentication only and that Entra ID and managed identities aren't supported. That wording looks older than the callback feature, and Microsoft's sample relies on the callback. I'd treat the README note as stale. Since the callback is flagged experimental, pin your SDK version and check the release notes before upgrading.

One more detail from the GitHub docs: the sample's scope is cognitiveservices.azure.com. GitHub's managed-identity guide uses the [Microsoft Foundry](https://ai.azure.com/.default) scope in its Python example. The Microsoft sample uses the first. If you get a 401 with a valid login, check which scope your resource expects.

The session is deliberately bare​

The sample creates a session with these settings:

  • ClientName is github-copilot-sdk-byok.
  • The system message is replaced, not appended to, with an instruction to answer in English, concisely and factually.
  • AvailableTools and Tools are empty.
  • Configuration discovery, skills and host Git operations are all disabled.

The post doesn't say these features are impossible with BYOK. It only says they're out of scope for a first run. The point is to prove the model answers, then add tools, MCP servers, skills, approvals and streaming one at a time. When something breaks, you'll know which piece did it.

The request itself uses SendAndWaitAsync with a three-minute timeout. It throws if the response content is empty. The default question asks what Microsoft Foundry is and how it relates to the Copilot SDK. You can pass your own with dotnet run -- "Explain BYOK in one sentence."

Running it​

  1. Set the endpoint, for example https://<resource>.services.ai.azure.com, with dotnet user-secrets set.
  2. Set the deployment name the same way.
  3. Run az login for the Entra path, or set the API key instead.
  4. Run dotnet run.

A successful run prints the model name, the authentication mode (AzureCliCredential or the key path), the question and then the answer.

Troubleshooting​

These checks come from the walkthrough and GitHub's BYOK documentation:

  • Empty or failed response on a reasoning model: raise MaxOutputTokens.
  • Authorization errors on the Entra path: confirm the Cognitive Services OpenAI User role and a fresh az login.
  • Endpoint rejected: the URL must be HTTPS.
  • Native Azure endpoint confusion: GitHub's BYOK documentation separates the /openai/v1/ route from native Azure endpoints. The GitHub BYOK page says to use type "openai" for /openai/v1/ and "azure" for native endpoints. The blog sample targets the first. It isn't a drop-in recipe for every provider or API shape.
  • Model required: GitHub's docs say the model parameter is mandatory when you use a custom provider.

Why it matters​

For teams on Azure, this answers a practical question. Can you use Copilot's agent plumbing while keeping inference, billing, rate limits and identity inside your own tenant? For simple cases, yes. The Entra path also avoids a long-lived key that could leak or be committed by accident.

The caveats are real. The auth callback is experimental. The sample is Responses-API-specific, and model availability depends on your provider. It also isn't a production design. It has no tool approvals, no streaming and no managed-identity setup for deployed hosts. For hosted scenarios, GitHub's managed identity guide is the better next step.

 

References

  1. Bring Your Own Model to the GitHub Copilot SDK with C# .NET Blog 2026-10-19T16:00:00+00:00
  2. BYOK (bring your own key) - GitHub Docs docs.github.com
  3. Using Azure Managed Identity with Copilot SDK - GitHub Enterprise Cloud Docs docs.github.com