Skip to main content
Skip to content

Server-to-server authentication

Use a short-lived installation access token when a service needs to make Copilot requests on behalf of an organization without a user's credentials. In GitHub Actions, use the built-in GITHUB_TOKEN instead.

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:

  1. Create a GitHub App with the Copilot Requests organization permission set to Read-only.

  2. Install it on the organization that usage should be attributed and billed to.

  3. Generating an installation access token for a GitHub App with the Copilot permission:

    {
      "permissions": {
        "organization_copilot_requests": "read"
      }
    }
    
  4. Pass the resulting ghs_ token to the SDK's gitHubToken, github_token, or equivalent option. For an existing runtime URI, set it as COPILOT_GITHUB_TOKEN on 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.

Code languages navigation

TypeScript
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,
});

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

SymptomCheck
401 UnauthorizedThe token may be expired or invalid. Mint a new installation token.
403 stating that Copilot requests with GitHub App installation access tokens are not enabledConfirm the organization supports GitHub App installation authentication for Copilot.
No GitHub OAuth token or Copilot HMAC key provided or Not authenticatedConfirm the installation token is passed through the SDK's explicit token option. With useLoggedInUser: false, the runtime ignores COPILOT_GITHUB_TOKEN and other environment variable tokens.
403 Forbidden from the Copilot APIConfirm the installation has the organization Copilot Requests permission, then mint a new token.
Requested model is unavailableConfirm the organization's Copilot policy allows the model and the bundled runtime supports it.
Wrong account billedConfirm the installation belongs to the intended organization.

Further reading