Adversarial verifier (LLM review)
An adversarial verifier is a second LLM pass whose job is to refute every finding produced by the primary review agents. Findings that survive refutation are kept; findings that don't are dropped before they reach the user.
Why single-pass LLM review needs a second opinion
Single-pass LLM code review has a well-documented failure mode: the model produces plausible-sounding findings that don't survive contact with the actual code. A finding might reference a variable that doesn't exist, claim a race condition that isn't reachable, or flag a security issue in a code path that never runs.
You can push false-positive rates down with better prompting, structured output, and evidence-quoting — but you can't get them to zero. What you can do is have a second model check the first one's work.
That's the adversarial verifier. It's not a duplicate reviewer; it's a critic. Its prompt says "here is a finding another agent produced; find the strongest reason it might be wrong." If the verifier can articulate a plausible refutation, the finding is dropped.
How LGTM's verifier works
After the 6 review agents (bugs, security, performance, readability, best-practices, documentation) complete, LGTM assembles the deduplicated list of findings. Each finding — with its evidenceQuote, category, severity, and reasoning — is sent to the verifier LLM with a fixed prompt: "Argue this finding is a false positive. Consider whether the code path is reachable, whether the flagged pattern is a real vulnerability in this framework, whether the evidence quote actually shows the described problem, whether the finding contradicts the repository's stated conventions."
The verifier returns a structured object with a keep / drop verdict and a refutation string. Dropped findings are logged (so we can measure the verifier's precision over time) but don't post to the PR.
Concurrency is capped at 6 to stay within provider rate limits. In practice the verifier adds 3-8 seconds to the tail latency of the review — well within the overall 30-90s budget.
What makes a verifier useful vs. a duplicate reviewer
The critical design choice is the prompt orientation. A duplicate reviewer with "find the bugs" produces its own findings — often confabulating alongside the primary agent. A verifier with "argue this is wrong" is oriented toward scepticism, which is the underrepresented direction in a naïve pipeline.
The verifier also has more information than the primary agent had: it can see the finding, the diff, the surrounding file context, and the repository's conventions. That extra context is exactly what enables it to spot "this finding is technically true in vanilla PHP but Laravel's default middleware already handles it."
Combined with the evidenceQuote gate (every finding must quote the offending code verbatim), the verifier catches roughly the top 15-25% of hallucinated findings — the ones that pass the syntactic quote check but fail the semantic reachability check.
Trade-offs and honest limits
A verifier is not free. It costs one LLM call per finding, which on the strong tier is the dominant per-review cost after the primary agents. LGTM uses the same-tier model as the primary agents (not a cheaper one) because a mini-tier verifier tends to defer too easily and lets weak findings through.
A verifier can also introduce false negatives — genuine findings the verifier successfully refutes. We measure this via the golden-set eval harness: fixture PRs with known-good findings, run through the full pipeline, and any finding the verifier drops that our human ground-truth kept counts against verifier precision.
The pragmatic answer is: verifier-off is worse than verifier-on for typical PRs, and the false-negative floor is small enough that Actionable-tier findings survive at ≥95%.
See LGTM's verifier in action
6 agents → verifier → synthesizer · concurrency capped at 6 · same-tier model
Go to the product pageFAQs
Isn't this just running the model twice?
It's running the model with a different objective. The primary agent optimises for recall (find every issue). The verifier optimises for precision (drop everything that isn't clearly a real issue). Same model class, opposite pressure. The combination lands higher than either single-pass approach.
How much does the verifier add to review latency and cost?
Latency: 3-8 seconds on the tail (verifier runs after the 6 agents finish). Cost: one strong-tier LLM call per finding — so a PR with 8 raw findings pays for 8 verifier calls. Anthropic prompt caching (cache_control: ephemeral) on the shared per-review context absorbs most of the repeated tokens after the first call.
What kinds of findings does the verifier drop?
Common drops: (a) findings referencing an unreachable code path, (b) findings that flag a pattern the framework already handles safely, (c) findings whose evidenceQuote is real but doesn't actually demonstrate the described problem, (d) findings that contradict a stated repository convention. Findings backed by concrete evidence in a reachable, unconventional code path almost always survive.
Can I see what the verifier dropped?
Not in the PR UI (that's noise), but the dropped findings + refutation strings are logged and surface on the admin analytics tile for the golden-set eval harness. Users see only the findings that survived — the ones we're confident enough to post.
Related across LGTM
Related terms
AI code review
AI code review uses large language models (and increasingly multi-agent pipelines) to review pull requests for bugs, security issues, performance regressions, readability, and style — automatically, on every PR, in 30-90 seconds.
LLM code review pipeline
An LLM code review pipeline is the end-to-end system that ingests a GitHub PR webhook, fetches the diff, gathers repo context, runs one or more LLM agents in parallel, synthesizes their outputs, and posts the result back to GitHub as a review with inline comments.
Prompt injection defence (for AI code review)
Prompt injection defence for AI code review means treating every user-controlled input (diff, files, PR history, repo conventions) as data — never as instructions. LGTM wraps every such input in <untrusted_KIND>…</untrusted_KIND> XML tags the system prompt is trained to ignore as commands.