GitHub Actions
For workflows in an organization-owned repository, grant the built-in token permission to make Copilot requests:
permissions:
contents: read
copilot-requests: write
jobs:
copilot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: your-application
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The organization's Allow use of Copilot CLI billed to the organization policy must be enabled. This approach needs no GitHub App or stored authentication secret. For details, see Using Copilot CLI in GitHub Actions with GITHUB_TOKEN.
Other services and CI systems
For services outside GitHub Actions:
-
Create a GitHub App with the Copilot Requests organization permission set to Read-only.
-
Install it on the organization that usage should be attributed and billed to.
-
Generating an installation access token for a GitHub App with the Copilot permission:
{ "permissions": { "organization_copilot_requests": "read" } } -
Pass the resulting
ghs_token to the SDK'sgitHubToken,github_token, or equivalent option. For an existing runtime URI, set it asCOPILOT_GITHUB_TOKENon the runtime process instead.
The organization must be enabled for Copilot requests from GitHub App installations. Installation tokens expire after one hour.
Note
No signed-in user is required. useLoggedInUser: false turns off automatic credential discovery, including environment variable tokens such as COPILOT_GITHUB_TOKEN, so pass the installation token through the SDK's explicit token option.
Configure the runtime
The following examples assume the minted token is in INSTALLATION_TOKEN. They pass it only to the child runtime and disable fallback to stored user credentials.
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";
const token = process.env.INSTALLATION_TOKEN;
if (!token) throw new Error("INSTALLATION_TOKEN is required");
const client = new CopilotClient({
connection: RuntimeConnection.forStdio(),
gitHubToken: token,
useLoggedInUser: false,
});
import os
from copilot import CopilotClient, RuntimeConnection
client = CopilotClient(
connection=RuntimeConnection.for_stdio(),
github_token=os.environ["INSTALLATION_TOKEN"],
use_logged_in_user=False,
)
package main
import (
"log"
"os"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
token, ok := os.LookupEnv("INSTALLATION_TOKEN")
if !ok {
log.Fatal("INSTALLATION_TOKEN is required")
}
client := copilot.NewClient(&copilot.ClientOptions{
Connection: copilot.StdioConnection{},
GitHubToken: token,
UseLoggedInUser: copilot.Bool(false),
})
_ = client
}
use github_copilot_sdk::{ClientOptions, Transport};
fn main() {
let token = std::env::var("INSTALLATION_TOKEN").expect("INSTALLATION_TOKEN is required");
let options = ClientOptions::new()
.with_transport(Transport::Stdio)
.with_github_token(token)
.with_use_logged_in_user(false);
drop(options);
}
using GitHub.Copilot;
var token = Environment.GetEnvironmentVariable("INSTALLATION_TOKEN")
?? throw new InvalidOperationException("INSTALLATION_TOKEN is required");
await using var client = new CopilotClient(new CopilotClientOptions
{
Connection = RuntimeConnection.ForStdio(),
GitHubToken = token,
UseLoggedInUser = false,
});
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.CopilotClientOptions;
import java.util.Objects;
var token = Objects.requireNonNull(
System.getenv("INSTALLATION_TOKEN"), "INSTALLATION_TOKEN is required");
try (var client = new CopilotClient(new CopilotClientOptions()
.setGitHubToken(token)
.setUseLoggedInUser(false))) {
// Use the client.
}
For in-process FFI, use the same token option; environment variable tokens in the host process are ignored when useLoggedInUser is false. For an existing runtime URI, set COPILOT_GITHUB_TOKEN on that runtime process.
Refresh tokens
Mint a new installation token before the current token expires. For a child process, restart the SDK client with the new token. For an in-process or existing runtime, restart the host runtime with the new token.
Billing
Usage is attributed and billed to the organization that owns the GitHub App installation.
Troubleshooting
| Symptom | Check |
|---|---|
401 Unauthorized | The token may be expired or invalid. Mint a new installation token. |
403 stating that Copilot requests with GitHub App installation access tokens are not enabled | Confirm the organization supports GitHub App installation authentication for Copilot. |
No GitHub OAuth token or Copilot HMAC key provided or Not authenticated | Confirm the installation token is passed through the SDK's explicit token option. With useLoggedInUser: false, the runtime ignores COPILOT_GITHUB_ and other environment variable tokens. |
403 Forbidden from the Copilot API | Confirm the installation has the organization Copilot Requests permission, then mint a new token. |
| Requested model is unavailable | Confirm the organization's Copilot policy allows the model and the bundled runtime supports it. |
| Wrong account billed | Confirm the installation belongs to the intended organization. |
Further reading
- Authentication: other authentication methods and priority
- Generating an installation access token for a GitHub App: GitHub App token creation