Production-ready AI Code Review Agent built with Google Cloud Agent Development Kit (ADK). Reviews pull requests via GitHub webhooks and posts structured feedback as PR comments.
An AI agent that performs pull request code reviews for your repositories:
- Trigger: GitHub webhook on PR events (opened, reopened)
- Input: PR title, description, and file diffs from the GitHub API
- Processing: Agent (Gemini via ADK) analyzes changes incrementally in batches and uses GitHub-backed tools when needed
- Output: Structured JSON review (PR summary, findings summary, detailed findings) formatted as GitHub PR comments with inline suggestions
The agent focuses on correctness, security, performance, and maintainability and avoids speculation or large refactors unless necessary.
| Component | Implementation |
|---|---|
| Framework | Google ADK (Agent Development Kit) |
| Model | Gemini 2.5 Flash / Gemini 2.5 Flash Lite (configurable via MODEL_NAME env var) |
| Tools | GitHub-backed: github_file_contents (reads file content with line numbers via PyGithub) |
| Deployment | Vertex AI Agent Engine (for production) or InMemoryRunner (for webhook local execution) |
| Webhook | FastAPI on Cloud Run β receives GitHub webhooks, returns 200 immediately, runs review in background using InMemoryRunner |
| Infrastructure | Makefile + Cloud Build (webhook image), Agent Engine deploy script |
| Region | e.g. us-central1 (webhook + Agent Engine; set in env) |
.
βββ agent/ # Agent application code
β βββ agent.py # Main agent logic, instructions, and tools (includes github_file_contents)
β βββ agent_engine_app.py # Agent Engine deployment entrypoint
β βββ models.py # Pydantic models (PRAnalysisInput, PRAnalysisOutput, Finding, etc.)
β βββ prompts.py # Agent prompts (ROOT_PROMPT, GIT_FILE_ANALYSIS_PROMPT)
β βββ utils.py # GitHub API client (GithubManager) and utilities
β βββ app_utils/ # Deploy script, env config
β βββ deploy.py # Vertex AI Agent Engine deployment
β βββ env_config.py # Environment variable helpers
β βββ telemetry.py # BigQuery telemetry (optional)
β βββ gcs.py # GCS utilities (optional)
β
βββ webhook/ # GitHub webhook listener (Cloud Run)
β βββ main.py # FastAPI app: /webhook (PR events), /health
β βββ models.py # Webhook models (RootReviewOutput, CodeDiffAnalysisInput)
β βββ Dockerfile # Container for Cloud Run
β βββ requirements.txt # Webhook dependencies
β βββ .env.example # Webhook env template
β
βββ Makefile # Build and deploy commands
βββ pyproject.toml # Python dependencies (uv)
βββ validate_env.py # Validates required env vars for playground and deploy
βββ deployment_metadata.json # Written after deploy (Agent Engine ID, timestamp)
β
βββ README.md # This file
βββ webhook/README.md # Webhook build and deploy details
- uv β Python package manager
- gcloud β Google Cloud SDK
- make β Build automation (pre-installed on macOS/Linux)
# 1. Set project and install dependencies
export PROJECT_ID="your-gcp-project-id" # replace with your GCP project ID
gcloud config set project $PROJECT_ID
make install
# 2. Configure environment (copy and edit .env from repo or create from validate_env.py vars)
# Ensure .env has all required vars (see Configuration below)
make validate-env
# 3. Run local playground
make playgroundThen open the ADK UI (e.g. http://localhost:3000), select the code-review-agent folder, and send a message that includes PR context or a diff for the agent to review.
| Document | Purpose |
|---|---|
| README.md (this file) | Project overview, architecture, quick start |
| webhook/README.md | Webhook build, Docker, Cloud Run deploy, health check |
- Senior engineer persona β High-signal, low-noise PR reviews
- Structured output β Sections: PR summary, findings summary, and detailed findings with confidence scores
- GitHub-backed tools β Reads repo content via GitHub API (
github_file_contentsfor file content with line numbers) - Incremental batching β Processes PR commits in token-budgeted batches to handle large PRs efficiently
- Focused scope β Reviews only the diff; uses tools only when context is missing
- Concise style β Actionable feedback, small code snippets for fixes; βLGTMβ when no issues
- Local: ADK playground for testing (
make playground) - Agent: Deployed to Vertex AI Agent Engine (
make deploy-agent) - Webhook: Fast response (200) then background review; Docker image built with Cloud Build; deployed to Cloud Run (
make deploy-webhookormake build-webhook-force) - Change detection:
make deploy-webhookbuilds and deploys only whenwebhook/has changes (or when.gitis missing, e.g. CI)
| Command | Description |
|---|---|
make install |
Install dependencies (uv sync); installs uv if missing |
make validate-env |
Validate required environment variables |
make playground |
Launch local ADK testing UI (port 3000) |
make deploy-agent |
Deploy agent to Vertex AI Agent Engine |
make deploy-webhook |
If webhook/ changed: build image, deploy webhook to Cloud Run (does not deploy agent) |
make build-webhook-force |
Build and deploy webhook (bypass change check, does not deploy agent) |
make test |
Run unit and integration tests (if tests/unit and tests/integration exist) |
make lint |
Run codespell, ruff, mypy |
make register-gemini-enterprise |
Register deployed agent with Gemini Enterprise (interactive) |
User (or webhook payload): PR with title βAdd login validationβ and diff for a few files.
Agent:
{
"pr_summary": "This PR adds login validation to the authentication module. Main changes are in `auth.py` with new password validation logic.",
"findings_summary": "One correctness issue found: empty password validation is missing.",
"findings": [
{
"title": "Empty password not rejected",
"body": "In `auth.py` line 42, empty password is not rejected. Add validation to prevent empty passwords.",
"confidence_score": 0.95,
"file_path": "auth.py",
"line_start": 42,
"line_end": 42,
"code": "if not password.strip():\n return None",
"suggestion": "Add a check to reject empty passwords"
}
]
}The webhook formats this into GitHub PR comments with inline suggestions.
- Main logic and instructions:
agent/agent.py(containsPRAnalysisAgentandroot_agent) - Tools:
github_file_contentsfunction inagent/agent.py(GitHub App auth via Secret Manager; reads file content with line numbers) - GitHub API client:
agent/utils.py(GithubManagerclass for PR operations, file fetching, incremental batching) - Models:
agent/models.py(PRAnalysisInput, PRAnalysisOutput, Finding, FlatIssue, GitDiffAnalysisOutput) - Prompts:
agent/prompts.py(ROOT_PROMPT, GIT_FILE_ANALYSIS_PROMPT) - Entrypoint for Agent Engine:
agent/agent_engine_app.py(exportsagent_enginefromagent/agent.py)
Validated by validate_env.py. Required for playground and deploy (see script for full list). Key groups:
- GitHub App:
APP_ID_GITHUB,INSTALLATION_ID_GITHUB,MYSELF,SECRET_MANAGER_PROJECT_ID,SECRET_MANAGER_SECRET_NAME,SECRET_MANAGER_TOKEN_NAME - Vertex AI Agent Engine:
VERTEX_AI_PROJECT_ID,VERTEX_AI_LOCATION,VERTEX_AI_RESOURCE_ID - Deploy / ADK:
PROJECT_ID,DEPLOYMENT_REGION,MODEL_LOCATION,MODEL_NAME(e.g.,gemini-2.5-flash),LLM_LOCATION,DATA_STORE_REGION,DATA_STORE_ID,STAGING_BUCKET,LOGS_BUCKET_NAME,DATASET_ID,TABLE_ID,AGENT_DISPLAY_NAME,AGENT_DESCRIPTION, and optional agent deploy vars (seevalidate_env.py)
Create a .env in the project root (and optionally webhook/.env for local webhook runs). Use make validate-env to confirm.
- Webhook URL (GitHub App):
https://<cloud-run-service-url>/webhookβ set in your GitHub App settings (see below). - Health check:
GET https://<cloud-run-service-url>/healthβ{"status": "healthy", "service": "code-review-webhook-listener"} - Implementation: Uses
InMemoryRunnerto execute the agent locally (importsroot_agentfromagent/agent.py), not a remote Agent Engine call - Env for Cloud Run: Set via Makefile
--set-env-vars(or Secret Manager); seewebhook/README.mdandwebhook/.env.example.
To receive PR events and post comments, use a GitHub App and point its webhook to your Cloud Run service.
-
Create a GitHub App
- GitHub β Settings β Developer settings β GitHub Apps β New GitHub App (or use an existing App).
- Name: e.g.
Code Review Agent. - Homepage URL: any (e.g. your org URL or
https://github.com). - Webhook: check Active and set Webhook URL to your Cloud Run URL:
https://<your-cloud-run-service-url>/webhook. - Webhook secret: optional; leave empty unless you add verification in the webhook handler.
- Permissions β Repository permissions:
- Pull requests: Read and write.
- Contents: Read-only (for reading repo files).
- Metadata: Read-only (default).
- Subscribe to events: Pull requests.
- Create the App.
-
Generate a private key
- In the App β General β Private keys β Generate a private key. Save the
.pemfile.
- In the App β General β Private keys β Generate a private key. Save the
-
Store the private key in Secret Manager
- Create a secret (e.g.
your-github-app-private-key) in Google Cloud Secret Manager with the full PEM contents. - Set
SECRET_MANAGER_PROJECT_IDandSECRET_MANAGER_SECRET_NAMEin.envto the project and secret name.
- Create a secret (e.g.
-
Install the App
- Install App β choose your organization or user β select repositories (or all).
- Note the Installation ID (from the install URL, e.g.
https://github.com/organizations/YOUR_ORG/settings/installations/12345β ID is12345). SetINSTALLATION_ID_GITHUBin.env.
-
App ID and optional token secret
- In the App General page, copy the App ID β
APP_ID_GITHUB. - If your agent uses a token from Secret Manager, create a secret for it and set
SECRET_MANAGER_TOKEN_NAME.
- In the App General page, copy the App ID β
-
Webhook delivery
- After deploy, GitHub sends Pull request events to
https://<cloud-run-service-url>/webhook. No need to add a separate repo webhook when using a GitHub App; the Appβs webhook URL is used for all installed repos.
- After deploy, GitHub sends Pull request events to
- Local development β
make playground - Validate env β
make validate-env - Deploy agent β
make deploy-agent(writesdeployment_metadata.jsonwith Agent Engine ID) - Deploy webhook β
make deploy-webhook(only ifwebhook/changed) ormake build-webhook-force- Note: The webhook uses
InMemoryRunnerto run the agent locally, so it doesn't require the Agent Engine to be deployed for basic functionality. However, for production scalability, you may want to deploy the agent to Agent Engine and modify the webhook to call it remotely.
- Note: The webhook uses
- Configure GitHub App β Set the Appβs Webhook URL to
https://<your-cloud-run-service-url>/webhook(see Create a GitHub App and add webhook). - Monitor β Cloud Run logs, Vertex AI Agent Engine console (if using Agent Engine)
| Issue | Action |
|---|---|
| Missing env vars | Run make validate-env and set all required variables in .env. |
| Webhook timeout in GitHub | Webhook returns 200 immediately and runs review in background; timeouts should stop. If not, check Cloud Run logs. |
| Agent not found / wrong engine | If using Agent Engine: Ensure VERTEX_AI_RESOURCE_ID (and optional deployment_metadata.json) match the deployed Agent Engine. Re-run make deploy-agent if needed. Note: The webhook uses InMemoryRunner locally, so Agent Engine is optional. |
| GitHub API errors | Check GitHub App installation ID, Secret Manager secret for private key, and repo permissions. Verify APP_ID_GITHUB and INSTALLATION_ID_GITHUB are set correctly. |
| No build on deploy-webhook | By design when there are no changes in webhook/. Use make build-webhook-force to build and deploy anyway. |
| Webhook imports agent locally | The webhook imports root_agent from agent/agent.py and runs it with InMemoryRunner. This means the agent code must be included in the webhook Docker image. |
For webhook build and Cloud Run details, see webhook/README.md.