GitHub Agentic Workflows

Authentication

This page describes authentication settings for GitHub Agentic Workflows.

Configure one GitHub Actions secret per engine before running your first workflow:

  • Recommended: permissions: copilot-requests: write — uses the GitHub Actions token; no PAT required, billing through your org
  • Alternative: COPILOT_GITHUB_TOKEN — fine-grained PAT with Copilot Requests permission
  • Notes: When copilot-requests: write is set, COPILOT_GITHUB_TOKEN is ignored for inference
  • Required secret: ANTHROPIC_API_KEY
  • Alternative: None
  • Notes: API key from Anthropic Console
  • Required secret: OPENAI_API_KEY
  • Alternative: CODEX_API_KEY
  • Notes: Runtime uses CODEX_API_KEY if present, otherwise falls back to OPENAI_API_KEY
  • Required secret: GEMINI_API_KEY
  • Alternative: None
  • Notes: API key from Google AI Studio

Most workflows will run without any additional secrets or additional authentication beyond this one engine secret.

Some workflows need additional authentication. These can be tokens added as secrets and referenced in your workflow, or GitHub App can be used.

Workflows using the following read operations from GitHub require Additional Authentication for GitHub Tools, via either a secret containing a PAT or GitHub App:

  • Read from multiple repositories
  • Read from projects
  • GitHub tools remote mode

Workflows using the following features of Safe Outputs require additional authentication, via either a secret containing a PAT or GitHub App:

Workflows using custom MCP tools or safe outputs may require additional authentication depending on the operations performed.

How do I add a GitHub Actions secret to my repository?

Section titled “How do I add a GitHub Actions secret to my repository?”

You can add secrets manually in the GitHub UI or use the CLI for a streamlined experience.

Terminal window
gh aw secrets set COPILOT_GITHUB_TOKEN --value "YOUR_COPILOT_PAT"

You can also check existing secrets with:

Terminal window
gh aw secrets bootstrap

If you're working in Codespaces, use the GitHub UI method below to add secrets.

  1. Go to your repository on GitHub
  2. Click on "Settings" → "Secrets and variables" → "Actions"
  3. Click "New repository secret" and add the token name and value
Repository secrets page showing configured tokens

A reference for all GitHub Actions secrets used by GitHub Agentic Workflows for AI engine authentication:

The recommended way to authenticate Copilot inference is to grant the copilot-requests: write permission in your workflow. This uses the built-in GitHub Actions token — no PAT or repository secret is required. Billing is handled centrally through your organization's Copilot subscription.

Setup:

Add copilot-requests: write to the permissions: block of your workflow frontmatter:

permissions:
contents: read
copilot-requests: write

When this permission is present, gh-aw automatically uses the GitHub Actions token for Copilot inference. Any value set for COPILOT_GITHUB_TOKEN or GH_AW_GITHUB_TOKEN is ignored for inference — those tokens are not passed to the Copilot engine.

Why this is preferred:

  • No PAT lifecycle management — tokens are minted per-run and automatically revoked.
  • Billing flows through the organization's Copilot plan, not an individual user's quota.
  • Works seamlessly in forked repos and organization workflows without sharing a personal token.

Use COPILOT_GITHUB_TOKEN when you need to authenticate Copilot inference with a specific user's PAT — for example, in personal repositories or when centralized org billing is not available. When permissions: copilot-requests: write is set in your workflow, this secret is ignored for inference.

If using Copilot as your AI engine, you need a GitHub Actions Secret set to a GitHub Personal Access Token (PAT) to authenticate Copilot CLI.

Setup:

Create a fine-grained PAT (this link pre-fills the token name, description, and Copilot Requests permission). Verify the following settings before generating:

  1. Resource owner is your user account, not an organization.

  2. Under Permissions → Account permissions, Copilot Requests is set to Read.

  3. Click Generate token and copy the token value.

  4. Add the PAT to your GitHub Actions repository secrets as COPILOT_GITHUB_TOKEN, either by CLI or GitHub UI.

    Terminal window
    gh aw secrets set COPILOT_GITHUB_TOKEN --value "<your-github-pat>"

Custom endpoints:

To route Copilot CLI through a custom endpoint (e.g., a corporate proxy or GHE Cloud data residency instance), set GITHUB_COPILOT_BASE_URL in engine.env. See Custom API Endpoints via Environment Variables for details. COPILOT_GITHUB_TOKEN must still be a fine-grained PAT — GitHub Apps and OAuth tokens are not supported for this secret.

Troubleshooting:

If your workflow fails at the Copilot inference step even with the token set, verify that the token owner's account has an active Copilot license. See Copilot License or Inference Access Issues for a local diagnostic step.


GH_AW_GITHUB_TOKEN is an optional "magic" GitHub Actions secret used as the default fallback token for GitHub operations outside engine inference.

Use it when your workflow needs authenticated GitHub access beyond the default GITHUB_TOKEN, for example:

  • Safe outputs that write to other repositories
  • Safe outputs that trigger CI on pull requests
  • Safe outputs or tools that need broader repo/API access than the default token provides
  • Fallback when github-app.ignore-if-missing: true is used and app secrets are unavailable

Fallback chain:

custom github-tokensecrets.GH_AW_GITHUB_TOKENsecrets.GITHUB_TOKEN

How to create it:

  1. Create a fine-grained PAT owned by a user account.

  2. Scope repository access to the minimum set of repositories needed.

  3. Grant only the minimum required permissions for your configured operations (for example, Issues: write for issue outputs, Pull requests: write for PR outputs, Contents: write for commit/branch writes, Actions: write for workflow dispatch/rerun operations).

  4. Store it as a repository secret:

    Terminal window
    gh aw secrets set GH_AW_GITHUB_TOKEN --value "<your-github-pat>"

GH_AW_GITHUB_TOKEN does not replace COPILOT_GITHUB_TOKEN for Copilot inference authentication.


If using the Claude by Anthropic engine, you need to set a GitHub Actions secret ANTHROPIC_API_KEY to be an API key from Anthropic.

Setup:

  1. Create an API key at https://console.anthropic.com/settings/keys

  2. Add it to your repository secrets, either by CLI or GitHub UI:

    Terminal window
    gh aw secrets set ANTHROPIC_API_KEY --value "YOUR_ANTHROPIC_API_KEY"

Custom endpoints:

To route Claude through a custom Anthropic-compatible endpoint (e.g., an internal proxy or Azure-hosted model), set ANTHROPIC_BASE_URL in engine.env and store any additional credentials as secrets. See Custom API Endpoints via Environment Variables for an example.

CLAUDE_CODE_OAUTH_TOKEN:

CLAUDE_CODE_OAUTH_TOKEN is not supported by GitHub Agentic Workflows. The only supported authentication method for the Claude engine is ANTHROPIC_API_KEY. Provider-based OAuth authentication (such as billing through a Claude Teams or Claude Max subscription) is not supported. If you have set CLAUDE_CODE_OAUTH_TOKEN as a repository secret, it will be ignored — configure ANTHROPIC_API_KEY instead.

See also AI Engines for additional configuration needed when using Claude with GitHub MCP.


If using the Codex by OpenAI engine, you need to set a GitHub Actions secret OPENAI_API_KEY with an API key from OpenAI.

Setup:

  1. Create an API key at https://platform.openai.com/api-keys

  2. Add it to your repository secrets, either by CLI or GitHub UI:

    Terminal window
    gh aw secrets set OPENAI_API_KEY --value "YOUR_OPENAI_API_KEY"

CODEX_API_KEY alternative:

Both CODEX_API_KEY and OPENAI_API_KEY are accepted. The runtime tries CODEX_API_KEY first. If you have already stored the key under CODEX_API_KEY, there is no need to add OPENAI_API_KEY as well.

Azure OpenAI and custom endpoints:

To use Azure OpenAI or an internal LLM router instead of the default OpenAI endpoint, set OPENAI_BASE_URL in engine.env and store the corresponding key as a GitHub Actions secret referenced from engine.env:

engine:
id: codex
model: gpt-4o
env:
OPENAI_BASE_URL: "https://my-azure-endpoint.openai.azure.com/openai/deployments/gpt-4o"
OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
network:
allowed:
- github.com
- my-azure-endpoint.openai.azure.com

AZURE_OPENAI_API_KEY is a GitHub Actions repository secret you configure separately with gh aw secrets set AZURE_OPENAI_API_KEY --value "<key>". Do not embed raw key values directly in the frontmatter.

See also AI Engines for additional configuration needed when using Codex with GitHub MCP.


If using the Gemini by Google engine, you need to set a GitHub Actions secret GEMINI_API_KEY with an API key from Google AI Studio.

Setup:

  1. Create an API key at https://aistudio.google.com/api-keys

  2. Add it to your repository secrets, either by CLI or GitHub UI:

    Terminal window
    gh aw secrets set GEMINI_API_KEY --value "YOUR_GEMINI_API_KEY"

See also AI Engines for additional configuration needed when using Gemini with GitHub MCP.


Common authentication errors and how to resolve them:

403 Forbidden or inference failure with copilot-requests: write

The GitHub Actions token does not have Copilot inference access for this organization. Confirm that your organization has an active Copilot subscription with centralized billing and that the workflow's permissions: block includes copilot-requests: write. If centralized billing is not available, fall back to COPILOT_GITHUB_TOKEN.

403 "Resource not accessible by personal access token" (Copilot)

The PAT is missing the required permission. Use a fine-grained PAT with Account permissions → Copilot Requests: Read. The resource owner must be your personal account, not an organization. See COPILOT_GITHUB_TOKEN for the setup link.

401 Unauthorized or 403 Forbidden (Claude)

The ANTHROPIC_API_KEY secret is missing, expired, or invalid. Verify the key is active in the Anthropic Console. Re-set the secret with gh aw secrets set ANTHROPIC_API_KEY --value "<key>". Also check that you have not accidentally set CLAUDE_CODE_OAUTH_TOKEN instead — it is not supported.

401 Unauthorized or 403 Forbidden (Codex)

The OPENAI_API_KEY (or CODEX_API_KEY) secret is missing, expired, or has insufficient quota. Verify the key at https://platform.openai.com/api-keys. If using a custom endpoint, confirm OPENAI_BASE_URL points to a reachable host and that the host is listed under network.allowed.

401 Unauthorized (Gemini)

The GEMINI_API_KEY secret is missing or invalid. Generate a new key at https://aistudio.google.com/api-keys.

Copilot license or inference access errors

If the token is correctly configured but Copilot fails at the inference step, the PAT owner's account may lack an active Copilot subscription. See Copilot License or Inference Access Issues for a local diagnostic command.

Error loading models: 400 Bad Request (Copilot on GHES)

Copilot is not licensed at the enterprise level or the API proxy is routing incorrectly. See Copilot Engine Prerequisites on GHES for the full checklist.


For enhanced security with short-lived tokens, you may configure a GitHub App instead of using PATs.

This does not apply to COPILOT_GITHUB_TOKEN, which must currently be a PAT. A single GitHub App can be used for all other GitHub authentication needs in GitHub Agentic Workflows, including tool authentication and safe outputs.

After creating your app, configure it in your workflow:

permissions:
contents: read
issues: read
tools:
github:
toolsets: [repos, issues, pull_requests]
github-app:
client-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: "my-org" # Optional: defaults to current repo owner
repositories: ["repo1", "repo2"] # Optional: defaults to current repo only

Make sure you set up repository variables and secrets:

Terminal window
gh variable set APP_ID --body "123456"
gh aw secrets set APP_PRIVATE_KEY --value "$(cat path/to/private-key.pem)"

At workflow start, a token is automatically minted with permissions matching your job's permissions: field. The token is passed to the GitHub MCP server and automatically revoked at workflow end (even on failure).

You can also use GitHub App tokens for safe outputs operations:

safe-outputs:
github-app:
client-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: "my-org" # optional: installation owner
repositories: ["repo1", "repo2"] # optional: scope to specific repos
create-issue:

When you configure github-app: for safe outputs, tokens are minted with permissions specific to the safe output operations being performed, rather than the broader job-level permissions. This provides enhanced security by ensuring that tokens have the minimum necessary permissions for their specific use case.

For both tool authentication and safe outputs, you can scope the GitHub App token to specific repositories for enhanced security. This limits the token's access to only the repositories it needs to interact with.

  • Omit repositories field - Current repository only (default)
  • repositories: ["*"] - Org-wide access (all repos in the installation)
  • repositories: ["repo1", "repo2"] - Specific repositories only

When owner is omitted, gh-aw derives the installation owner from the workflow's effective checkout target. For literal owner/repo repositories, the owner is emitted directly at compile time; for expression-based repositories, a generated pre-step extracts the owner at runtime before token minting. For workflow_call workflows with no explicit checkout.repository, derivation falls back to ${{ needs.activation.outputs.target_repo }}.

This lets multi-org workflows mint App tokens against the effective target without setting owner: explicitly. An explicit owner: always takes precedence. Owner derivation applies under checkout[*].github-app, top-level safe-outputs.github-app, and tools.github.github-app.

Gracefully Skip Minting When Keys Are Missing (ignore-if-missing:)

Section titled “Gracefully Skip Minting When Keys Are Missing (ignore-if-missing:)”

By default, jobs fail when client-id or private-key resolve to empty strings at runtime — for example, on fork pull requests where App secrets are unavailable. Set ignore-if-missing: true to skip the token mint step instead and fall back to the standard non-App token chain (secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN):

safe-outputs:
github-app:
client-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
ignore-if-missing: true
create-issue:

The same field is accepted under tools.github.github-app: and applies consistently to all token mint paths (safe outputs, activation, pre-activation, and checkout). Default behavior (fail when keys are empty) is unchanged when the field is omitted or false.