Self-hosted GitHub App for AI pull request reviews
pr-agent Β· Node 22+ Β· Postgres Β· pg-boss
Async by design. Webhooks return
200after durable intake (Postgres + pg-boss enqueue). Reactions, progress comments, reviews, descriptions, and ask answers publish onROLE=workerand may appear seconds later.
PR Agent is a GitHub App that enqueues durable agent work items (reviews, descriptions, asks, triage) from webhooks and slash commands, then runs LLM agent loops on workers using local PR workspaces or isolated writable checkouts and GitHub APIs for publish.
Domain terms: CONTEXT.md. Configuration: docs/configuration.md. Behaviour and deployment: docs/operations.md. Queue runbook: docs/agent-work-ops.md.
- Getting Started
- Configure the agent provider
- Why Use PR Agent?
- Features
- See It in Action
- How It Works
- Data Privacy
- Create a GitHub App.
- Set Webhook URL to
https://<host>/webhooksand Webhook secret to matchWEBHOOK_SECRET. - Subscribe to events:
pull_request,issue_comment,pull_request_review_comment(do not requirepull_request_review). - Repository permissions (typical): Issues and Pull requests read/write, Contents read/write, Metadata read. Contents write is only needed for
/triage. Commit statuses read/write whenENABLE_REVIEW_COMMIT_STATUS=true. - Install the app on target orgs or repos. Set
GITHUB_APP_IDandGITHUB_APP_PRIVATE_KEYin.env(see.env.example).
Full stack: Postgres, web intake, and worker consumers.
cp .env.example .env
# Set GITHUB_*, WEBHOOK_SECRET, and agent provider keys (see Configure the agent provider)
docker compose build
docker compose up- Webhook URL (default ports):
http://<host>:7224/webhooks GET /health: liveness (ok)GET /ready: readiness (Postgres reachable)- Both
pr-agent-web(ROLE=web) andpr-agent-worker(ROLE=worker) are required for reviews and asks.
More deployment detail: docs/operations.md.
DATABASE_URL is required for both roles (src/config.ts).
docker compose up postgres
cp .env.example .env
npm install -g --ignore-scripts=false @nubjs/nub
nub install
# terminal 1: enqueue only
ROLE=web DATABASE_URL=postgres://pr_agent:pr_agent@localhost:5432/pr_agent nub src/index.ts
# terminal 2: reviews, descriptions, asks
ROLE=worker DATABASE_URL=postgres://pr_agent:pr_agent@localhost:5432/pr_agent nub src/index.tsnub src/index.ts loads .env automatically. For auto-restart on source changes, use nub watch src/index.ts. Tunnel webhooks (e.g. smee.io) to /webhooks.
If you previously installed with pnpm, delete node_modules before your first nub install to avoid mixed virtual-store layouts (.pnpm/ vs .nub/).
Vercel site deploys still use pnpm via site/vercel.json until Vercel has native Nub support.
Minimal env:
DATABASE_URL=...
GITHUB_APP_ID=...
GITHUB_APP_PRIVATE_KEY=...
WEBHOOK_SECRET=...
# Agent provider: see Configure the agent providerDeveloper scripts: see docs/operations.md.
LLM runs happen on ROLE=worker only. Pick a runner with AGENT_PROVIDER, then set model and credentials.
| Runner | AGENT_PROVIDER |
Model env | Credentials |
|---|---|---|---|
| Pi (default) | pi |
PI_PROVIDER, PI_MODEL |
Provider API key env vars (see below) |
| Cursor SDK | cursor |
PI_MODEL (Cursor model id) |
CURSOR_API_KEY (required) |
Full tunables: docs/configuration.md. Cursor integration: ADR 0013.
Uses @earendil-works/pi-ai and the Pi coding-agent session loop.
AGENT_PROVIDER=pi
PI_PROVIDER=openai
PI_MODEL=gpt-4o-mini
OPENAI_API_KEY=sk-...PI_PROVIDER: pi-ai provider slug (for exampleopenai,anthropic,google,deepseek,openrouter,amazon-bedrock,groq). Startup validates against the installed pi-ai provider list.PI_MODEL: model id for that provider (for examplegpt-4o,claude-sonnet-4-5).- API keys: set the env var for your provider. pr-agent loads
OPENAI_API_KEY,ANTHROPIC_API_KEY, andGOOGLE_GENERATIVE_AI_API_KEYinto the worker at startup. Other Pi providers use their standard env vars in the worker process (for exampleDEEPSEEK_API_KEY,OPENROUTER_API_KEY,GROQ_API_KEY). See the Pi providers reference for the full key table, cloud setup (Azure, Bedrock, Vertex), and custom endpoints.
Do not set PI_PROVIDER=cursor. Use AGENT_PROVIDER=cursor for Cursor models instead.
Uses the Cursor SDK local agent with an HTTP MCP bridge to pr-agent's GitHub, Context7, and submitReview tools. Register at worker boot only.
AGENT_PROVIDER=cursor
CURSOR_API_KEY=...
PI_MODEL=composer-2.5CURSOR_API_KEY: required whenAGENT_PROVIDER=cursor.PI_MODEL: Cursor model id fromCursor.models.list(). The worker fetches the live catalog at boot and validates your choice. Common ids (first ten from a typical list):composer-2.5,composer-2,gpt-5.5,gpt-5.4-high,claude-opus-4-7,claude-opus-4-8,claude-4.6-sonnet-high-thinking,gpt-5.3-codex-high,gemini-3.1-pro,auto. Append-fastfor the fast tier when the SDK exposes afastparameter (for examplecomposer-2.5-fast,gpt-5.5-fast). Plain ids use the standard tier.PI_PROVIDERis ignored for Cursor runs.
Restart pr-agent-worker (or the ROLE=worker process) after changing provider env vars.
Webhook handlers validate, dedupe, and enqueue work in Postgres before responding. Workers scale independently; a review backlog does not block webhook acceptance.
File listing and patch caps (MAX_PR_FILES_LISTED, MAX_PR_FILES_PATCH_BYTES) plus Octokit throttling keep runs bounded. Truncation metadata is explicit when the change set is clipped.
Tunables live in env vars and docs/configuration.md. Prompt prose stays in code; limits and shared strings live in src/settings/.
Run on your infrastructure with your GitHub App credentials and chosen LLM provider (Pi/OpenAI, Cursor SDK, and others via @earendil-works/pi-ai).
General bug-and-correctness reviews run on PR open and sync. /review-security, /review-quality, and /review-tests add separate review summary comments on demand, each with its own review lens and progress comment.
| Capability | Auto on PR | Slash command | Notes |
|---|---|---|---|
| General review | opened / sync / reopen | /review |
## PR Agent Review; inline P0 to P2 on Files tab when present |
| PR description | opened (configurable) | /describe |
Merges under ## PR Agent Description |
| Security lens | No | /review-security |
## PR Agent Security Review |
| Quality lens | No | /review-quality |
## PR Agent Quality Review |
| Tests lens | No | /review-tests |
## PR Agent Tests Review; proposed test cases as markdown (never commits tests) |
| Triage | No | /triage |
Fixes earlier findings, commits and pushes to the PR branch; ## PR Agent Triage |
| Ask | No | /ask <question> |
PR conversation or inline diff code anchor |
| Help | No | /help |
Worker-published guidance |
| Lightweight auto-review | docs-only trivial PRs | No | Skips full review run; see ADR 0014 |
| Deployment | Supported |
|---|---|
| Docker Compose (web + worker + Postgres) | Yes |
| Bare Node + Postgres | Yes |
Cursor provider (AGENT_PROVIDER=cursor) |
Yes |
Slash commands are case-sensitive and must start the first non-empty line of a new comment. Full behaviour: docs/operations.md.
flowchart LR
GitHub[GitHub webhooks] --> Web["ROLE=web /webhooks"]
Web --> Dedupe[Postgres webhook_events dedupe]
Dedupe --> Items[agent_work_items]
Items --> Boss[pg-boss enqueue]
Boss --> AckQ[ack queue]
Boss --> RevQ[review queue]
Boss --> AskQ[ask queue]
Boss --> DescQ[description queue]
Boss --> TriageQ[triage queue]
Boss --> RetQ[retention queue]
AckQ --> Worker["ROLE=worker executors"]
RevQ --> Worker
AskQ --> Worker
DescQ --> Worker
TriageQ --> Worker
RetQ --> Worker
Worker --> Retention[retention cleanup]
Retention --> Dedupe
Retention --> Items
Worker --> LLM[LLM plus tools]
LLM --> Publish[GitHub PR-surface publish]
Worker --> Push[git push PR branch]
- Web (
processWebhookRequestEffect): verify signature, parse payload, durable dedupe, schedule agent work items. - Scheduler (
AgentWorkScheduler): write Postgres rows and enqueue pg-boss jobs (ack, review, ask, description, triage). - Ack worker: acknowledgement reaction and review progress comment stub before long runs.
- Worker maintenance (
AgentWorkerLive): owns pg-boss cron/supervision and the daily retention cleanup lane. - Review / ask / description / triage workers (
executors/): installation token, local PR workspace or isolated writable checkout, agent harness, PR-surface I/O. - Reviews (
runFullPrReview): investigation tools, then one structuredsubmitReviewpublish path.
Queue inspection and recovery: docs/agent-work-ops.md. Architecture ADR: docs/adr/0009-durable-agent-work.md.
Postgres, pg-boss, and GitHub App credentials run on your infrastructure. Webhook bodies and workflow state stay in your database.
Review, description, and ask content is sent to your configured model provider during worker runs only (Pi/OpenAI, Cursor, or others per PI_PROVIDER / AGENT_PROVIDER). See your provider's data policy (for example OpenAI or Cursor).
When enabled, library lookup tools may call https://context7.com/api. Set CONTEXT7_API_KEY for higher limits; queries leave your network to Context7 when those tools run.
Structured logs use evlog on your hosts. LOG_REDACT (default true) redacts secret-shaped substrings; tune via docs/configuration.md.
/ask replies apply outbound redaction before posting. Probes for bot internals may receive an Ask meta refusal without an LLM call (ADR 0010).
More security detail: docs/operations.md.




