GitHub's OAuth scope documentation is written for app developers building products for GitHub users. AI agents have different access patterns — they are autonomous, high-volume, and often need much narrower access than the available scopes suggest. This is what you actually need to know.
The repo scope problem
The repo scope is where most teams start and where most teams stay. The GitHub documentation describes it as granting "full control of private repositories." What most developers do not read carefully is the full list of what that includes: read/write access to code, commit statuses, repository invitations, collaborators, deployment statuses, and repository webhooks. That is a very large blast radius for an agent that needs to read PR descriptions.
The alternative is the fine-grained scope system that GitHub introduced for Personal Access Tokens (fine-grained): instead of repo, you can request contents:read, pull_requests:read, issues:read, etc. For GitHub Apps (the correct authentication mechanism for production agents), the equivalent is the granular permission system in the App's manifest — you define exactly which repository permissions the app needs, and GitHub only issues tokens with those permissions.
The practical implication: for agents using GitHub OAuth App tokens (the older OAuth flow), you are stuck with the coarse scopes. For agents using GitHub App installations (the recommended approach), you have per-permission granularity and you should use it. If you are still using OAuth App tokens for production agent workloads, migrating to GitHub Apps is worth the effort.
GitHub Apps vs OAuth Apps for agent use cases
GitHub provides two different OAuth-compatible authentication mechanisms. OAuth Apps are the classic implementation — a user authorizes the app and it receives a token scoped to the user's permissions. GitHub Apps are the modern implementation — the app is installed on an organization or repository and receives installation tokens scoped to the app's manifest-defined permissions.
For AI agents, GitHub Apps are superior in almost every way. First, installation tokens are short-lived: GitHub App installation tokens expire after one hour by default, which aligns with Alter's TTL-based rotation model. There is no equivalent default expiry for OAuth App tokens. Second, GitHub Apps have granular permissions at the repository level — you can install a GitHub App on a specific set of repositories rather than granting it access to your entire GitHub organization. Third, GitHub Apps have a separate actor identity in the audit log — commits and comments made by a GitHub App appear as "performed via [App Name]" rather than as a user action, which makes agent activity distinguishable in the audit log without additional tooling.
The migration path from OAuth App to GitHub App for existing agent code is typically two to three hours of work: create the GitHub App manifest with the permissions your agent needs, update the authentication flow to use the installation token endpoint instead of the OAuth App token endpoint, and update your token refresh logic to handle the one-hour expiry. The Alter SDK handles the installation token refresh automatically when you register a GitHub App credential.
Scope-by-use-case breakdown
Below is the set of scopes we recommend for common agent use cases, based on the actual API endpoints each use case requires:
Code review agents (read PRs, post review comments, read commit diffs): GitHub App permissions: pull_requests: write (write needed to post review comments), contents: read. Do not request contents: write unless the agent needs to modify code directly. Distinguishing "reads PR diffs" from "can push code" is a critical privilege boundary.
Issue triage agents (read, label, and close issues): issues: write (write needed to add labels and close), metadata: read. If the agent only reads issues and reports on them, use issues: read instead. The difference between read and write is whether the agent can change the state of issues.
Release automation agents (create releases, upload assets): contents: write (for creating tags and release notes), actions: write if the agent triggers workflows. Release agents have the broadest legitimate scope of any CI/CD agent. Make sure the policy ceiling is set to match: max_scope: [contents:write, actions:write] with explicit deny on admin:org and admin:repo_hook.
Dependency management agents (read package manifests, open PRs for updates): contents: write (to push dependency update branches), pull_requests: write (to open PRs). These agents are a common target for supply chain attacks — an attacker who controls a dependency update agent can push malicious code to dependency branches. Restrict this agent's access to specific repositories rather than the entire organization.
Read-only audit agents (scan repositories for secrets, license compliance): contents: read, metadata: read. Audit agents should never have write access. If the audit agent's token is compromised, the attacker should get a read-only view of your repositories, not the ability to push code.
The admin scopes: never for agents
GitHub's admin scopes — admin:org, admin:repo_hook, admin:public_key, admin:enterprise — should never appear in an agent's scope set. These scopes grant the ability to modify organization settings, manage webhooks, and add SSH keys. No AI agent task requires these permissions, and granting them creates a privilege escalation path that bypasses GitHub's organization-level access controls.
If you see an agent or integration guide that recommends admin:org "to make setup easier," that is incorrect advice. The correct approach is to grant the specific sub-permissions needed. For webhook management, use repo_hook:write if the agent actually needs to manage webhooks (rare). For key management, use user:read if the agent needs to verify key ownership. Admin scopes are a developer convenience shortcut that trades security for setup speed.
Repository-level vs organization-level access
GitHub App installations can be scoped to specific repositories rather than all repositories in an organization. For agents that only need to operate on one or a few repositories, this is the correct default. A code review agent that handles your team's main product repository does not need installation access to your infrastructure repositories, your marketing website, or any other repository in the organization.
In the GitHub App installation settings, you can select "Only select repositories" and list the specific repositories the agent needs access to. Alter's dashboard surfaces the installation scope when you register a GitHub App credential — if the scope says "All repositories," the dashboard flags it for review. The principle of least privilege applies at the repository level, not just the permission level.
Token scope verification in practice
GitHub's REST API returns the granted scope in the X-OAuth-Scopes response header on every API call. For agent debugging, you can check this header on any GitHub API response to verify what scope your token actually carries. If you are using an Alter-proxied token and the granted scope is narrower than what you see in the X-OAuth-Scopes header, it means Alter's downscoping layer is active and has reduced the scope before the token reached GitHub.
To verify a token's scope without making an API call, use GitHub's token verification endpoint: GET https://api.github.com/ with the token as a Bearer token in the Authorization header. The response headers include X-OAuth-Scopes and X-Accepted-OAuth-Scopes. For GitHub App installation tokens, use GET /installation/repositories — the response will be limited to the repositories the installation has access to, which serves as an implicit scope verification.
Getting scope verification into your agent's startup check is worth the ten lines of code. An agent that starts and immediately verifies it has the expected scope fails fast with a clear error rather than failing silently on the first API call that requires a permission the token does not have.