# BYOK (Bring Your Own Key) BYOK allows you to use the Copilot SDK with your own API keys from model providers, bypassing GitHub Copilot authentication. This is useful for enterprise deployments, custom model hosting, or when you want direct billing with your model provider. ## Supported Providers | Provider | Type Value | Notes | |----------|------------|-------| | OpenAI | `"openai"` | OpenAI API and OpenAI-compatible endpoints | | Azure OpenAI / Azure AI Foundry | `"azure"` | Azure-hosted models | | Anthropic | `"anthropic"` | Claude models | | Ollama | `"openai"` | Local models via OpenAI-compatible API | | Other OpenAI-compatible | `"openai"` | vLLM, LiteLLM, etc. | ## Quick Start: Azure AI Foundry Azure AI Foundry (formerly Azure OpenAI) is a common BYOK deployment target for enterprises. Here's a complete example:
Python ```python import asyncio import os from copilot import CopilotClient FOUNDRY_MODEL_URL = "https://your-resource.openai.azure.com/openai/v1/" # Set FOUNDRY_API_KEY environment variable async def main(): client = CopilotClient() await client.start() session = await client.create_session({ "model": "gpt-5.2-codex", # Your deployment name "provider": { "type": "openai", "base_url": FOUNDRY_MODEL_URL, "wire_api": "responses", # Use "completions" for older models "api_key": os.environ["FOUNDRY_API_KEY"], }, }) done = asyncio.Event() def on_event(event): if event.type.value == "assistant.message": print(event.data.content) elif event.type.value == "session.idle": done.set() session.on(on_event) await session.send({"prompt": "What is 2+2?"}) await done.wait() await session.destroy() await client.stop() asyncio.run(main()) ```
Node.js / TypeScript ```typescript import { CopilotClient } from "@github/copilot-sdk"; const FOUNDRY_MODEL_URL = "https://your-resource.openai.azure.com/openai/v1/"; const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5.2-codex", // Your deployment name provider: { type: "openai", baseUrl: FOUNDRY_MODEL_URL, wireApi: "responses", // Use "completions" for older models apiKey: process.env.FOUNDRY_API_KEY, }, }); session.on("assistant.message", (event) => { console.log(event.data.content); }); await session.sendAndWait({ prompt: "What is 2+2?" }); await client.stop(); ```
Go ```go package main import ( "context" "fmt" "os" copilot "github.com/github/copilot-sdk/go" ) func main() { ctx := context.Background() client := copilot.NewClient(nil) if err := client.Start(ctx); err != nil { panic(err) } defer client.Stop() session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5.2-codex", // Your deployment name Provider: &copilot.ProviderConfig{ Type: "openai", BaseURL: "https://your-resource.openai.azure.com/openai/v1/", WireApi: "responses", // Use "completions" for older models APIKey: os.Getenv("FOUNDRY_API_KEY"), }, }) if err != nil { panic(err) } response, err := session.SendAndWait(ctx, copilot.MessageOptions{ Prompt: "What is 2+2?", }) if err != nil { panic(err) } fmt.Println(*response.Data.Content) } ```
.NET ```csharp using GitHub.Copilot.SDK; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5.2-codex", // Your deployment name Provider = new ProviderConfig { Type = "openai", BaseUrl = "https://your-resource.openai.azure.com/openai/v1/", WireApi = "responses", // Use "completions" for older models ApiKey = Environment.GetEnvironmentVariable("FOUNDRY_API_KEY"), }, }); var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2+2?", }); Console.WriteLine(response?.Data.Content); ```
## Provider Configuration Reference ### ProviderConfig Fields | Field | Type | Description | |-------|------|-------------| | `type` | `"openai"` \| `"azure"` \| `"anthropic"` | Provider type (default: `"openai"`) | | `baseUrl` / `base_url` | string | **Required.** API endpoint URL | | `apiKey` / `api_key` | string | API key (optional for local providers like Ollama) | | `bearerToken` / `bearer_token` | string | Bearer token auth (takes precedence over apiKey) | | `wireApi` / `wire_api` | `"completions"` \| `"responses"` | API format (default: `"completions"`) | | `azure.apiVersion` / `azure.api_version` | string | Azure API version (default: `"2024-10-21"`) | ### Wire API Format The `wireApi` setting determines which OpenAI API format to use: - **`"completions"`** (default) - Chat Completions API (`/chat/completions`). Use for most models. - **`"responses"`** - Responses API. Use for GPT-5 series models that support the newer responses format. ### Type-Specific Notes **OpenAI (`type: "openai"`)** - Works with OpenAI API and any OpenAI-compatible endpoint - `baseUrl` should include the full path (e.g., `https://api.openai.com/v1`) **Azure (`type: "azure"`)** - Use for native Azure OpenAI endpoints - `baseUrl` should be just the host (e.g., `https://my-resource.openai.azure.com`) - Do NOT include `/openai/v1` in the URL—the SDK handles path construction **Anthropic (`type: "anthropic"`)** - For direct Anthropic API access - Uses Claude-specific API format ## Example Configurations ### OpenAI Direct ```typescript provider: { type: "openai", baseUrl: "https://api.openai.com/v1", apiKey: process.env.OPENAI_API_KEY, } ``` ### Azure OpenAI (Native Azure Endpoint) Use `type: "azure"` for endpoints at `*.openai.azure.com`: ```typescript provider: { type: "azure", baseUrl: "https://my-resource.openai.azure.com", // Just the host apiKey: process.env.AZURE_OPENAI_KEY, azure: { apiVersion: "2024-10-21", }, } ``` ### Azure AI Foundry (OpenAI-Compatible Endpoint) For Azure AI Foundry deployments with `/openai/v1/` endpoints, use `type: "openai"`: ```typescript provider: { type: "openai", baseUrl: "https://your-resource.openai.azure.com/openai/v1/", apiKey: process.env.FOUNDRY_API_KEY, wireApi: "responses", // For GPT-5 series models } ``` ### Ollama (Local) ```typescript provider: { type: "openai", baseUrl: "http://localhost:11434/v1", // No apiKey needed for local Ollama } ``` ### Anthropic ```typescript provider: { type: "anthropic", baseUrl: "https://api.anthropic.com", apiKey: process.env.ANTHROPIC_API_KEY, } ``` ### Bearer Token Authentication Some providers require bearer token authentication instead of API keys: ```typescript provider: { type: "openai", baseUrl: "https://my-custom-endpoint.example.com/v1", bearerToken: process.env.MY_BEARER_TOKEN, // Sets Authorization header } ``` ## Limitations When using BYOK, be aware of these limitations: ### Identity Limitations BYOK authentication is **key-based only**. The following identity providers are NOT supported: - ❌ **Microsoft Entra ID (Azure AD)** - No support for Entra managed identities or service principals - ❌ **Third-party identity providers** - No OIDC, SAML, or other federated identity - ❌ **Managed identities** - Azure Managed Identity is not supported You must use an API key or bearer token that you manage yourself. ### Feature Limitations Some Copilot features may behave differently with BYOK: - **Model availability** - Only models supported by your provider are available - **Rate limiting** - Subject to your provider's rate limits, not Copilot's - **Usage tracking** - Usage is tracked by your provider, not GitHub Copilot - **Premium requests** - Do not count against Copilot premium request quotas ### Provider-Specific Limitations | Provider | Limitations | |----------|-------------| | Azure AI Foundry | No Entra ID auth; must use API keys | | Ollama | No API key; local only; model support varies | | OpenAI | Subject to OpenAI rate limits and quotas | ## Troubleshooting ### "Model not specified" Error When using BYOK, the `model` parameter is **required**: ```typescript // ❌ Error: Model required with custom provider const session = await client.createSession({ provider: { type: "openai", baseUrl: "..." }, }); // ✅ Correct: Model specified const session = await client.createSession({ model: "gpt-4", // Required! provider: { type: "openai", baseUrl: "..." }, }); ``` ### Azure Endpoint Type Confusion For Azure OpenAI endpoints (`*.openai.azure.com`), use the correct type: ```typescript // ❌ Wrong: Using "openai" type with native Azure endpoint provider: { type: "openai", // This won't work correctly baseUrl: "https://my-resource.openai.azure.com", } // ✅ Correct: Using "azure" type provider: { type: "azure", baseUrl: "https://my-resource.openai.azure.com", } ``` However, if your Azure AI Foundry deployment provides an OpenAI-compatible endpoint path (e.g., `/openai/v1/`), use `type: "openai"`: ```typescript // ✅ Correct: OpenAI-compatible Azure AI Foundry endpoint provider: { type: "openai", baseUrl: "https://your-resource.openai.azure.com/openai/v1/", } ``` ### Connection Refused (Ollama) Ensure Ollama is running and accessible: ```bash # Check Ollama is running curl http://localhost:11434/v1/models # Start Ollama if not running ollama serve ``` ### Authentication Failed 1. Verify your API key is correct and not expired 2. Check the `baseUrl` matches your provider's expected format 3. For bearer tokens, ensure the full token is provided (not just a prefix) ## Next Steps - [Authentication Overview](./index.md) - Learn about all authentication methods - [Getting Started Guide](../getting-started.md) - Build your first Copilot-powered app