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) from webhooks and slash commands, then runs LLM agent loops on workers using local PR workspaces (full shallow checkout of the PR head for context) 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, Metadata read.
- 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
corepack enable
pnpm install
# terminal 1: enqueue only
ROLE=web DATABASE_URL=postgres://pr_agent:pr_agent@localhost:5432/pr_agent pnpm dev
# terminal 2: reviews, descriptions, asks
ROLE=worker DATABASE_URL=postgres://pr_agent:pr_agent@localhost:5432/pr_agent pnpm devpnpm dev alone does not load .env. Prefer node --env-file=.env --import tsx src/index.ts when you need env file values. Tunnel webhooks (e.g. smee.io) to /webhooks.
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. Supported values includecomposer-2.5,composer-2,gpt-5.5,claude-opus-4-7, andauto(seesrc/agent/providers/cursor/models.ts).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 and /review-quality 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 | same | /describe |
Merges under ## PR Agent Description |
| Security lens | No | /review-security |
## PR Agent Security Review |
| Quality lens | No | /review-quality |
## PR Agent Quality Review |
| 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]
AckQ --> Worker["ROLE=worker executors"]
RevQ --> Worker
AskQ --> Worker
DescQ --> Worker
Worker --> LLM[LLM plus tools]
LLM --> Publish[GitHub PR-surface publish]
- 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). - Ack worker: acknowledgement reaction and review progress comment stub before long runs.
- Review / ask / description workers (
executors/): installation token, local PR workspace (depth-1 full head checkout + GitHub PR-file diff metadata), 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.




