# pragent An extensible, forge-agnostic PR review framework. Not a product — a toolkit that teams extend with their own review dimensions. **Status:** design approved; framework build deferred. A **pilot** is live on `glm-5.2:cloud` with two delivery paths: - **Central webhook service** (preferred, least per-repo setup): a Gitea user-level webhook posts PR events to an always-on in-cluster service that gates on the `AI-REVIEW` label. Onboarding a repo = add `pragent-bot` collaborator + create the label + label a PR. See [`pilot/README-webhook.md`](pilot/README-webhook.md). - **CI-step** (legacy): a per-repo Gitea Action fetches the reviewer script at runtime. See [`pilot/README.md`](pilot/README.md). The framework design remains at [`docs/plans/2026-08-04-pragent-design.md`](docs/plans/2026-08-04-pragent-design.md); the pilot is its bootstrap and will be superseded by `pragent review` when the framework build resumes. ## What it is `pragent` runs as a CI step. It reads a pull request, decides how much attention the change deserves, runs the analyzers that apply, and posts ranked findings back to the forge. ``` pragent init # one-time repo scan → .pragent/profile.yml (committed, reviewable) pragent review # the CI step: tier → analyze → aggregate → publish pragent explain # why did this PR get this tier / these findings? pragent replay # re-run a past PR against a new prompt or model (the eval loop) pragent doctor # config, credentials, and adapter health ``` ## Why not CodeRabbit / Greptile / Qodo Those are good products with fixed review dimensions and per-seat pricing. `pragent` targets the case where a platform team needs to **add its own dimensions** — an internal compliance rule, a service-catalog ownership check, a house performance idiom — without forking a vendor's reviewer. Cost lands in the same range (~$25/dev/month at 350 PRs/mo for 20 devs), but the analyzers, the data, and the analytics are yours. ## Attention tiers Every PR is classified before any expensive work happens. Deterministic rules decide first; an ambiguous case gets one cheap model call as tie-breaker. | Tier | What it means | Cost/PR | |---|---|---| | `trivial` | lockfile bumps, generated code, docs typos | ~$0.005 | | `lite` | small change, no risk paths | ~$0.08 | | `full` | the default for real changes | ~$0.80–2.00 | | `oversized` | too big to review whole; structural summary + deep pass on the hot subset | ~$5 ceiling | Every tier decision records *why*, so a surprising outcome is explainable rather than mysterious. ## What it costs The pilot runs on `glm-5.2:cloud` through the on-network headroom proxy, so today it bills nothing per token — but the token *work* is real, and `pilot/cost_model.py` prices it against published API rates. The factory's prompt sizes are measured from the files in this repo; the per-tier workloads come from the `attention-tiering` budgets. Blended over a 5/35/55/5 tier mix, prompt caching on: | Model | per PR | 350 PRs/month | |---|---:|---:| | Claude Opus 5 / GPT-5.6 Sol | ~$0.61 | ~$212 | | Claude Sonnet 5 / GPT-5.6 Terra | ~$0.24 | ~$85 | | Claude Haiku 4.5 | ~$0.12 | ~$43 | | GPT-5.6 Luna | ~$0.02 | ~$8.5 | Run `python3 pilot/cost_model.py --help` for other mixes and PR volumes. The dominant cost is the agent loop resending its own context each step, not the diff — turning prompt caching off multiplies the bill by ~2.3x, which is why the tiering skill caps steps, file reads, and subagent fan-out per tier. ## Extension points Five, all documented in the design doc. Teams override or add; nobody forks. 1. **Analyzers** — drop a YAML + prompt in `.pragent/analyzers/`, or install from npm 2. **Forge adapters** — Gitea, GitLab, GitHub, local diff 3. **Tier policy** — thresholds and the path risk map, per repo or per org 4. **Profile enrichers** — extend what `pragent init` learns about a repo 5. **Emitter sinks** — JSONL by default, OpenTelemetry, or your own Org config can lock keys, so a repo cannot quietly disable the security analyzer. ## Design principles - **Polyglot by construction.** Language knowledge lives in the repo profile, not in the reviewer. A new language is a profile change, not a core change. - **One shared prompt prefix.** All analyzers for a PR share a byte-identical cached prefix. This is what makes fan-out affordable; it is enforced, not hoped for. - **Everything is traceable.** Tier reasons, token counts, cost, latency, and finding outcomes are recorded per run. False-positive rate is measurable per analyzer. - **Fail open.** A budget ceiling or an analyzer crash yields a partial review with a clear note, never a blocked pipeline with no explanation. - **The reviewed code is untrusted input.** The reviewer runs an agent over a branch anyone with PR access can write. So it holds no credentials in its environment, the checkout is stripped of files an agent runtime would load as instructions, PR-authored text is fenced as data, and reviewer config is read from the base branch. See "Threat model" in [`pilot/README-webhook.md`](pilot/README-webhook.md). ## Stack TypeScript + Node, built on the [`pi`](https://github.com/badlogic/pi-mono) agent SDK. Shipped as an npm package and an OCI image, so CI runners need no local Node install. ## Roadmap 1. Walking skeleton — local diff, one analyzer, rules-only tiering 2. Gitea end to end — adapter, Woodpecker step, PR comments, status checks 3. Profile + full tier — `pragent init`, shared-prefix caching, analyzer fan-out 4. Extensibility hardening — plugin loading, config layering, `explain` / `replay` 5. Second forge — GitLab adapter, Jenkins recipe 6. Analytics maturity — OTel export, feedback loop, eval harness ## License TBD.