ai-code-review.yml
Multi-agent PR review. Picks one of the configured AI agents at random and dispatches that agent’s own review workflow for the PR, falling through to the next candidate when one can’t be dispatched or fails during execution (gha#362, gha#444).
It sits above whichever per-agent review workflows a repo has installed — claude-code-review.yml, gemini-code-review.yml, antigravity-code-review.yml, cursor-code-review.yml, and opencode-code-review.yml — rather than reviewing anything itself, so those stubs have to exist in the caller repo and be named to match the *-review-workflow-file inputs below.
What the fallback covers
The fallback covers an agent that is unavailable at dispatch time (no API key or token secret configured for it, or its review workflow file missing or disabled in the caller repo) as well as an agent run that fails or is cancelled during execution (gha#362, gha#444).
When a dispatched agent run fails, ai-code-review.yml detects the failure and falls through to try the next candidate agent in the list. The overall job has a timeout-minutes: 60 budget covering all candidate attempts. When configuring a custom agents list or raising watch-timeout, ensure the combined worst-case wait fits within this 60-minute bound so the fallback loop finishes its candidate progression cleanly.
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
agents |
string | 'claude, gemini' |
Comma-separated agents to select from (claude, gemini, antigravity, cursor, opencode). Unrecognized names are warned about and skipped. |
pr-number |
string | '' |
Pull request number to review. Required on workflow_dispatch; taken from the event on pull_request. |
claude-review-workflow-file |
string | 'claude-code-review.yml' |
Caller-repo workflow file dispatched for a Claude review. |
gemini-review-workflow-file |
string | 'gemini-code-review.yml' |
Caller-repo workflow file dispatched for a Gemini review. |
antigravity-review-workflow-file |
string | 'antigravity-code-review.yml' |
Caller-repo workflow file dispatched for an Antigravity review. |
cursor-review-workflow-file |
string | 'cursor-code-review.yml' |
Caller-repo workflow file dispatched for a Cursor Bugbot review. |
opencode-review-workflow-file |
string | 'opencode-code-review.yml' |
Caller-repo workflow file dispatched for an OpenCode review. |
watch-timeout |
string | '30m' |
Timeout bound for watching each dispatched agent’s review run before falling through to the next candidate. Sized against the overall 60-minute job timeout. |
Secrets
| Secret | Required | Description |
|---|---|---|
CLAUDE_CODE_OAUTH_TOKEN |
no | Max-plan OAuth token. Either this or ANTHROPIC_API_KEY makes claude an eligible candidate. |
ANTHROPIC_API_KEY |
no | Direct Anthropic API key. |
GEMINI_API_KEY |
no | Gemini API key. Makes gemini and antigravity eligible candidates. |
CURSOR_API_KEY |
no | Cursor Enterprise Bugbot API key (admin:*). Makes cursor an eligible candidate. |
OPENCODE_API_KEY |
no | OpenCode Zen API key. Makes opencode an eligible candidate. |
Permissions
Grant contents: read, pull-requests: read, issues: read, and actions: write (the last so it can dispatch the selected agent’s review workflow).
The dispatch uses GITHUB_TOKEN, so no personal access token is needed: actions: write is enough to start a workflow in the caller’s own repository. Each agent’s own review workflow declares whatever permissions it needs for itself.
Concurrency
Do not declare a top-level concurrency: block in your caller workflow. ai-code-review.yml manages per-PR concurrency internally on its select-and-review job (group: ai-review-<PR>). Adding a top-level concurrency: block in the caller with a PR-scoped group name causes GitHub Actions to detect a deadlock between the top-level workflow and the nested job, cancelling the run immediately (gha#437).
Example
# Copy to .github/workflows/ai-code-review.yml in your repo.
name: AI Code Review
on:
# Optional: automatic review on PR activity.
# pull_request:
# types: [opened, synchronize, ready_for_review, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'Pull request number to review'
required: true
type: string
jobs:
ai-review:
permissions:
contents: read
pull-requests: read
issues: read
actions: write
uses: Morrison-Lab/gha/.github/workflows/ai-code-review.yml@v2
secrets:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
with:
pr-number: ${{ inputs.pr_number }}
# with:
# agents: 'claude, gemini, antigravity, cursor, opencode'
# claude-review-workflow-file: claude-code-review.yml
# gemini-review-workflow-file: gemini-code-review.yml
# antigravity-review-workflow-file: antigravity-code-review.yml
# cursor-review-workflow-file: cursor-code-review.yml
# opencode-review-workflow-file: opencode-code-review.yml
# watch-timeout: 30mSee the examples/ directory for the full caller stub (ai-code-review.yml).