6 specialists per PR.
Not 1 generalist guessing.
Every pull request is reviewed by six agents in parallel — each looking for one specific kind of problem. Findings must quote the offending code verbatim, get run past an adversarial verifier that refutes the weak ones, dedup across agents, tier as Actionable / Suggestion / Nitpick, and post one-click Apply-suggestion blocks on mechanical fixes. Bring your own OpenAI or OpenRouter key — or use Managed AI (zero setup, LGTM covers the tokens).
10 reviews/mo free · No card · Counts roll over
How a review actually runs
One pipeline. Five stages. Streamed live to the dashboard so you watch the agents finish in real time.
Webhook received
GitHub fires pull_request opened/synchronize/reopened. Signature verified via X-Hub-Signature-256, idempotency keyed by X-GitHub-Delivery.
Diff + context
Diff fetched via App installation token. Context bundle: tree-sitter symbols, smart file-content windows (±100 lines around each touched line on files >400 lines), repo conventions (CLAUDE.md / AGENTS.md / .cursorrules / etc.), detected frameworks (from package.json / pyproject.toml / go.mod / ...), and per-language hints. All untrusted content wrapped in <untrusted_KIND> tags.
6 LLM agents (parallel) + ci-security
One BullMQ job per LLM agent. The deterministic ci-security agent runs alongside if the PR touches CI/CD or lockfile paths. Every LLM finding must include an evidenceQuote that quotes the offending code verbatim; unverifiable quotes are dropped.
Adversarial verifier
Each surviving finding is passed to a skeptic LLM that tries to refute it. Refuted findings drop out. Concurrency-capped at 6; JSON-parse errors safely default to KEEP so real bugs don't vanish on a bad LLM day.
Cross-agent dedup + tiering
Findings grouped by (file, line). Highest-severity variant kept, consensus tag added ('Flagged by: bugs, security, best-practices'), cap 25 → 10 comments. Each surviving finding tiered as Actionable (critical/high), Suggestion (medium), or Nitpick (low/info).
Synthesizer
Reads surviving findings + diff + per-repo guidelines. Emits verdict + summary + inline comments — including ```suggestion``` blocks on mechanical single-line fixes when the LLM opted in via codeSuggestion.
Posted to GitHub
Single POST to /repos/{...}/pulls/{pr}/reviews. If GitHub rejects 422 (force-push race), we retry without inline comments, posting just the summary.
Meet the six agents
Each agent has one job. Specialists outperform generalists because they don't spread attention thin trying to check everything at once.
Bugs
Catches what causes incidents
What it catches
- ·Null derefs and missing await
- ·Off-by-one and boundary bugs
- ·Race conditions in async code
- ·Returning wrong types under edge cases
- ·Unhandled error paths
Sample finding
`getUser(id)` can return undefined when the cache misses — but line 42 calls `.email` on it without a guard.
Security
40-class taxonomy on the diff hunks
What it catches
- ·SQL / NoSQL injection · XSS · SSRF
- ·JWT alg confusion · prototype pollution
- ·Broken auth + missing authz
- ·Secrets in the diff · weak crypto
- ·40-class enum with CWE cross-refs
Sample finding
User-controlled `repoId` flows into `Repo.findOne({ _id: repoId })` without ObjectId validation — Mongoose will accept arbitrary objects. category: nosql-injection (CWE-943).
Performance
Hot-path regressions, not micro-opts
What it catches
- ·N+1 queries in loops
- ·Blocking I/O on the request path
- ·Regex catastrophic backtracking
- ·Unnecessary re-renders / hook deps
- ·Missing pagination on unbounded lists
Sample finding
The loop on line 88 hits `User.findById(c.author)` per comment — 1 + N queries. Use a single `find({ _id: { $in: authors } })`.
Readability
Future you will thank present you
What it catches
- ·Variables named `data` / `result` / `temp`
- ·Functions over 60 lines or 4 nesting levels
- ·Magic numbers + strings
- ·Dead code, unreachable branches
- ·Clever > clear
Sample finding
`fn(d, t, x)` — what are `d`, `t`, `x`? The body uses them as `diff`, `target`, and `xform` — say that.
Best practices
Language and framework idioms
What it catches
- ·TS: `any` where a real type is obvious
- ·React: missing useEffect deps
- ·Express: middleware order wrong
- ·Go: error wrapping skipped
- ·Python: `mut_default = []` in args
Sample finding
`useEffect(() => { fetchPR(); }, [])` — missing `id` in the dep array. PR ID changes won't trigger re-fetch.
Documentation
Stale comments are worse than none
What it catches
- ·Missing JSDoc on exported functions
- ·Comments that contradict the code
- ·Stale TODOs and FIXMEs
- ·Public API without examples
- ·README claims vs code reality
Sample finding
The function comment says 'returns null on missing user' but the body now throws. Update the comment or restore the null return.
One verdict, not six conflicting opinions
After the six agents finish, a synthesizer agent reads all six reports plus the diff plus any per-repo review guidelines you've set. It produces:
Overall verdict
approve · request_changes · comment
Executive summary
2-4 sentences explaining the verdict to a busy reviewer.
Confidence score
0-100 — how certain the model is. Below 50 = manual review recommended.
Dedup'd inline comments
Same bug flagged by Bugs + Security = one comment, not two.
Live verdict in dashboard
request_changes
Confidence 78%
"Adds the new export but doesn't handle the cache-miss case the existing tests exercise — see line 42 in user.service.ts. Suggest pulling the cache check up one frame."
Tune it per repo
Different repos want different reviews. A monorepo for a payment API needs paranoia. A side-project Astro blog needs speed.
Focus areas
Pick a subset of the 6 agents. Repo A runs all six; Repo B only runs Bugs + Security. Saves tokens for teams who only care about a slice.
Custom review guidelines
Free-text appended to every review prompt for this repo. Drop your style guide, your no-go list, your 'we prefer X over Y' preferences.
Per-repo provider override (Pro)
Pin OpenAI on the Rust monorepo. Pin Claude Sonnet on the React app. Different repos can run on different models without changing your default. Readability + documentation agents auto-route to the same-provider mini/flash model — about 3.3× cheaper on those two.
Auto-review on every PR (Pro)
opened / synchronize / reopened — Pro fires automatically. Free users keep the manual 'Review' button on the dashboard or `lgtm review --pr <num>`.
Watch the agents finish, live
Socket.IO streams every step to the dashboard: review:started, agent:started / completed / failed per agent, synthesizer:started, review:completed. No polling, no spinners that never finish.
If the socket drops the dashboard shows a discreet "reconnecting…" pill — never a frozen UI.
FAQ
Does LGTM store our source code?
Can I block merges based on the verdict?
status: failure when the verdict is request_changes. GitHub branch protection then refuses the merge. For CI/CD-specific gates (36 deterministic detectors across GitHub Actions, GitLab CI, CircleCI, and Azure Pipelines) see LGTM Security.What if the diff is huge?
How does dedup work between agents?
(file, startLine, ruleId) and merges descriptions when two agents flag the same spot. A SQL-injection callout from Bugs and Security becomes one comment with both lenses noted.Which AI providers are supported?
/dashboard/ai-providers. BYOK OpenAI: gpt-5.4 / pro / mini / nano, gpt-5.3-codex, gpt-5.2, gpt-4.1-mini via Chat + Responses APIs with strict json_schema. BYOK OpenRouter: one key unlocks Claude Opus 5 / Sonnet 5 / Haiku 4.5, Gemini 3.1 Pro / Flash, Grok 4.5, DeepSeek V4 Pro, Llama 4, Mistral Large, Qwen 3.8 Max, and 400+ more — Claude models keep prompt caching via cache_control forwarding. Managed AI: LGTM covers the LLM cost on DeepSeek V4 Flash (CoreWeave, :nitro routing) — zero setup, works on Free tier. On BYOK, we never see your provider tokens unencrypted. Multiple keys per provider with labels; per-repo mode + key overrides available on every plan.Does LGTM hallucinate findings?
evidenceQuote that quotes the offending code verbatim from the diff or file window; a validator drops any unverifiable quote. On top of that, an adversarial verifier LLM tries to refute each surviving finding — refuted ones are dropped before you see them. Cross-agent dedup caps inline comments at 10 per review.Is LGTM safe against prompt injection in reviewed code?
<untrusted_KIND>…</untrusted_KIND> tags. The system prompt tells the LLM that content inside these tags is data, never instructions. Red-teamed against unicode ZWJ payloads, base64- encoded prompts, non-English (Hindi) injections, and fake-schema payloads — all ignored while real SQL-injection findings continue to fire.Do reviewers get one-click fixes?
parseInt radix, md5 → sha256, etc.) ship as native GitHub ```suggestion``` blocks. Reviewers Apply-suggestion in one click without leaving the PR.Does LGTM understand my project's conventions?
Can I disable specific agents per repo?
focusAreas: ["security", "bugs"] and only those two agents run. Lower token spend, faster reviews.Stop reviewing alone
10 reviews/month on Free. No card. Same 6 agents as Pro, same dashboard, same CLI.