Debates, voting, and reflection loops: composing an agentic PR reviewer that costs less than a dollar A Quarkus LangChain4j team built an agentic pull-request reviewer that reviews a 2,900-line pull request for $0.45, combining routing, debating, voting and reflection patterns in a single Quarkus application. The reviewer, built on Quarkus LangChain4j 1.15 over LangChain4j 1.21 with the Anthropic and OpenAI extensions, TypeSafe decision models and quarkus-github-api, scores PRs from 0 to 10 on usefulness, correctness, conciseness, security, test coverage, maintainability, API and documentation, and PR hygiene, and issues an APPROVE, COMMENT or REQUEST_CHANGES verdict. The team cited 1,698 pull requests received by the LangChain4j project since the start of the year as motivation, and the reviewer uses a read-only GitHub token, never writing to GitHub and emitting a Markdown report, a JSON report and an HTML trace of agent execution. public interface PrReviewSystem extends MonitoredAgent { @SequenceAgent name = "prReviewSystem", description = "Reviews a GitHub pull request and produces a scored report", outputKey = Keys.FINAL REPORT, subAgents = { PrFetcher.class, DiffPreprocessor.class, DiffTextProjection.class, PrOverviewProjection.class, DiffChunksProjection.class, PrTriage.class, RoutingInputs.class, ContextGate.class, ClarificationGate.class, ReviewBundleBuilder.class, UsefulnessAssessor.class, ReviewPanel.class, CoverageFloor.class, DiffChunkDeclaration.class, LargeDiffGate.class, FindingsConsolidator.class, ReviewRevisionLoop.class, FinalizerGate.class, ReportExporter.class } ReviewReport review String prUrl, ReviewMode mode, ReviewOptions options ; } At the moment when I write this, the LangChain4j project has received 1,698 pull requests since the beginning of this year. Reviewing them all is a lot of work, and we wanted an agentic system to help. But a single pattern can’t do it: routing, debating, voting and reflection all need to work together, within a cost budget, in a real Quarkus application. Here’s how we built one that reviews a 2900-line pull request for $0.45. In previous articles we discussed why no single agentic pattern can cover all use cases, introducing a generic Planner abstraction https://quarkus.io/blog/agentic-ai-patterns/ to define custom orchestration strategies, and we showed how the voting pattern and dynamic chat model selection https://quarkus.io/blog/introducing-voting-pattern/ make an agentic system more reliable and more cost-efficient. Each of those articles focused on one pattern, applied to a deliberately small example. This time we want to see what happens when many of these patterns have to work together in a real application, with real costs, real failures, and a human who wants to have the last word. Given a pull request, the reviewer produces a report saying what is good, what is wrong and what could be improved, with every problem anchored to a file and a line of the diff. It also gives a score from 0 to 10 for usefulness, correctness, conciseness, security, test coverage, maintainability, API and documentation, and PR hygiene, plus an overall score with its confidence, and a verdict: APPROVE , COMMENT or REQUEST CHANGES . It only reads GitHub, with a read-only token, and never writes to it: its output is a Markdown report, the same report in JSON, and an HTML trace of the execution of its agents. The reviewer is a Quarkus application built with the Quarkus LangChain4j extensions, version 1.15 on LangChain4j 1.21: quarkus-langchain4j-agentic for the agents, the Anthropic and OpenAI extensions for the chat models, quarkus-langchain4j-typesafe for the decision model where TypeSafe https://typesafe.ai is the company behind the Jev decision models , and quarkus-github-api to read GitHub. The agents are plain Java interfaces written with the declarative agentic API: the extension finds them at build time, validates how they are wired together and registers each of them as a CDI bean. The reviewer can be used both from the command line and from a local web interface. Let’s see how it works. When designing an agentic system, it is tempting to hand everything to a supervisor and let an LLM decide what to do next. For a reviewer this would be a poor choice: we want every review to fetch the same data, to run the checks that matter and to produce a report with the same structure, and we want to be able to test all of this. For this reason, the root of the reviewer is a plain sequence, and model judgment lives inside its steps, where it is actually needed. There is nothing to implement behind this interface. Quarkus LangChain4j detects it at build time, checks that every parameter an agent reads is the output key of another agent or an input of the root, and registers the whole system as a CDI bean, so that running a review is one injection away: @ApplicationScoped public class ReviewService { @Inject PrReviewSystem system; // ... } A parameter named after a key that no agent produces fails the build, with the message No agent provides an output key named '…' , instead of failing a review. Many of these subagents don’t use an LLM at all. Fetching the pull request, parsing and classifying its diff, validating the findings and rendering the report are better done by plain code, which in the declarative API is simply a static method annotated with @Agent . For instance, this non-AI agent renders the description of the pull request that all the reviewers read: public class ReviewBundleBuilder { @Agent name = "reviewBundleBuilder", description = "Renders the pull request bundle shared by all reviewers", outputKey = Keys.REVIEW BUNDLE public static String build String prOverview, PrSummary prSummary, String codeContext, String reviewerGuidance, String diffText { return " Overview\n" + prOverview + "\n Triage\n" + prSummary // ... the code context, the guidance of the human reviewer and the diff + "