# GitHub Copilot

[GitHub Copilot](https://github.com/features/copilot) can use your own model
endpoint instead of GitHub's hosted models — the
[Copilot CLI](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/use-byok-models)
through environment variables, and VS Code through its
[Custom Endpoint provider](https://code.visualstudio.com/docs/agent-customization/language-models#_add-a-custom-endpoint-model).
Point that endpoint at the AI Gateway, and every Copilot chat and agent request
is authenticated, metered against a budget, and limited to the models you allow.
Developers keep using Copilot exactly as before, and their requests, tokens, and
spend show up in the Zuplo Portal as they work.

## Before you start

Create a [provider](../managing-providers.mdx) for the models Copilot will use,
such as OpenAI or Anthropic, then get a gateway URL and key in one of two ways:

- **Use your personal API key (recommended).** Each developer calls the
  project's [User App](../user-apps.mdx) with their own key. Open the
  [**My Keys**](https://portal.zuplo.com/+/account/project/ai/home) tab of your
  AI Gateway project, copy the **Gateway URL**, and create a key under **My API
  keys**. Each developer's requests count against their own budget.
- **Use an app.** For a shared setup with one key,
  [create a pool](../managing-pools.mdx) and [an app](../managing-apps.mdx) for
  Copilot, then copy the app's **API URL** and **API Key**.

The rest of this guide calls these your **gateway URL** and **gateway key**.

The gateway names models as `providerName/model`, where `providerName` is the
name you gave the provider. The examples below use `openai` and `anthropic`;
substitute your own provider names.

## Copilot CLI

The CLI reads its provider from four environment variables. Set the base URL to
your gateway URL plus `/v1`, and name a model that supports tool calls, such as
GPT-4.1:

```bash
export COPILOT_PROVIDER_BASE_URL="https://my-gateway-main-2e18f50.zuplo.app/u/741d375d631b429293481d6d0458bb64/v1"
export COPILOT_PROVIDER_API_KEY="<your-gateway-key>"
export COPILOT_PROVIDER_TYPE="openai"
export COPILOT_MODEL="openai/gpt-4.1-mini"
```

Start `copilot` from the same shell. Every request in the session now passes
through the gateway.

For a Claude model, use the `anthropic` provider type with your gateway URL
without `/v1` — the CLI appends `/v1/messages` itself — and pass the key as a
bearer token, which is the header the gateway reads:

```bash
export COPILOT_PROVIDER_BASE_URL="https://my-gateway-main-2e18f50.zuplo.app/u/741d375d631b429293481d6d0458bb64"
export COPILOT_PROVIDER_BEARER_TOKEN="<your-gateway-key>"
export COPILOT_PROVIDER_TYPE="anthropic"
export COPILOT_MODEL="anthropic/claude-sonnet-4-6"
```

The CLI speaks Chat Completions and the Messages API and sets a `temperature` on
every request. GPT-4.1, GPT-4o, Claude Sonnet 4.6, and Claude Haiku 4.5 all
accept that; OpenAI's GPT-5.x reasoning models and Claude Sonnet 5 don't, so use
them from VS Code instead.

## VS Code

Add the gateway as a Custom Endpoint provider, then describe your models in the
configuration file VS Code opens.

<Stepper>

1. Run **Chat: Manage Language Models** from the Command Palette

2. Select **Add Models**, then **Custom Endpoint**

3. Enter a name for the group, such as `Zuplo AI Gateway`, and paste your
   gateway key

4. Select **Chat Completions** as the API type

5. Replace the `models` array in the `chatLanguageModels.json` file that opens
   with the models you want in the picker

</Stepper>

This configuration offers a GPT model and a Claude model through one gateway
URL:

```json
[
  {
    "name": "Zuplo AI Gateway",
    "vendor": "customendpoint",
    "apiKey": "${input:chat.lm.secret.321f64a2}",
    "models": [
      {
        "id": "openai/gpt-5.6",
        "name": "GPT-5.6 (Zuplo)",
        "apiType": "responses",
        "url": "https://my-gateway-main-2e18f50.zuplo.app/u/741d375d631b429293481d6d0458bb64/v1/responses",
        "toolCalling": true,
        "vision": true,
        "maxInputTokens": 128000,
        "maxOutputTokens": 16000,
        "requestHeaders": { "Authorization": "Bearer ${apiKey}" }
      },
      {
        "id": "anthropic/claude-sonnet-5",
        "name": "Claude Sonnet 5 (Zuplo)",
        "apiType": "messages",
        "url": "https://my-gateway-main-2e18f50.zuplo.app/u/741d375d631b429293481d6d0458bb64/v1/messages",
        "toolCalling": true,
        "vision": true,
        "maxInputTokens": 200000,
        "maxOutputTokens": 64000,
        "requestHeaders": { "Authorization": "Bearer ${apiKey}" }
      }
    ]
  }
]
```

Three lines carry the integration:

- **`apiKey`** is a reference to the key you pasted, which VS Code keeps in its
  secret storage and reads at request time. Leave it as written; to change the
  key, use **Chat: Manage Language Models**.
- **`requestHeaders`** sends the key as `Authorization: Bearer <key>`, the
  header the gateway's
  [Authentication policy](../../policies/ai-gateway-auth-inbound.mdx) reads. VS
  Code's default header depends on the API type, so set it on every model.
- **`apiType`** and the `url` path select the API the model speaks: `responses`
  for OpenAI's reasoning models such as GPT-5.x, `messages` for Claude through
  the gateway's native Messages passthrough, and `chat-completions` with a
  `/v1/chat/completions` URL for other chat models. Set it on each model so
  models with different APIs share one entry in the picker.

Save the file and pick a model from the chat model picker.

## What routes through the gateway

Chat and agent requests, on both surfaces. Copilot's inline code completions
stay on GitHub's infrastructure. The
[Model Filtering](../../policies/ai-gateway-model-filtering-inbound.mdx) policy
on the User App or the app decides which models Copilot may use.

## Troubleshooting

Copilot reports gateway errors as a retry failure, such as
`502 token expired or invalid: 401`. The gateway's own response is in the
**GitHub Copilot Chat** channel of VS Code's Output panel, or in the CLI's error
text.

| The gateway responds                                              | Cause                                                                              | Fix                                                                                                   |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `403` `This User App route requires a personal API key`           | A personal key that's missing, wrong, from another project, or sent as `x-api-key` | VS Code: add `requestHeaders`. CLI: use `COPILOT_PROVIDER_BEARER_TOKEN`. Check the key on **My Keys** |
| `401` `Header configured by options.authHeader is missing`        | With an app key: the key was sent as `x-api-key`                                   | VS Code: add `requestHeaders`. CLI: use `COPILOT_PROVIDER_BEARER_TOKEN`                               |
| `401` `Invalid Authorization Scheme`                              | VS Code's `apiKey` was replaced with the key itself, so the key sent was empty     | Re-enter the key with **Chat: Manage Language Models**                                                |
| `404`                                                             | The `url` stops at the gateway URL                                                 | Append `/v1/responses`, `/v1/messages`, or `/v1/chat/completions`                                     |
| `Function tools with reasoning_effort are not supported`          | A GPT-5.x model on Chat Completions                                                | VS Code: `"apiType": "responses"`. CLI: use a GPT-4.1 or Claude model                                 |
| `'temperature' does not support 0` or `temperature is deprecated` | The CLI's temperature setting on a GPT-5.x or Claude Sonnet 5 model                | Use GPT-4.1, GPT-4o, Claude Sonnet 4.6, or Claude Haiku 4.5                                           |
