All postsHome
Engineering notes · August 28, 2026

Code review for less than a cent.

How I wired GLM 5.3 Flash, open-source PR-Agent, GitHub Actions, and two repository-local Codex skills into a review loop that still asks me before merge.

By Layken Varholdt~9 min read

Review should be cheap enough to repeat

I want an automated review when a pull request opens. I want another review after every fix. I also want the reviewer to read the entire change instead of clipping a normal diff because its model has a small context window.

That sounds expensive if every pass uses a frontier coding model. It does not have to. I set up the original open-source PR-Agent with GLM 5.3 Flash and ran a small test through the complete pull request loop. Three model calls cost less than half a cent on the OpenRouter dashboard. The model caught the planted bug, ignored a planted false positive, and updated its review after the fix without a manual prompt.

The model is only one part of the result. Deterministic CI catches failures a reviewer should never guess about. Two local Codex skills control how the pull request gets filed and what happens after the bot comments. I still decide whether anything merges.

Four jobs, not one agent

Calling the whole setup an AI reviewer hides the useful part. Each piece has a narrow job.

PR-Agent does not write my fixes. It does not merge. It reviews the diff and leaves evidence for the next decision. The surrounding workflow determines whether that review becomes useful or becomes another bot comment nobody reads.

What PR-Agent is

PR-Agent is the original open-source pull request reviewer. The community project is separate from Qodo's hosted product. I run releasev0.43.0 inside my own GitHub Actions workflow, then choose the model and provider myself.

A pull request open event runs /describe and /review. A new push runs only /review. Comments can invoke /review, /describe, or /ask on demand.

The action has read-only access to repository contents and write access to pull request comments. Restricted mode prevents operations that need repository write permission. This is still an external model call. OpenRouter and the provider that serves the request see the diff. Running an open-source GitHub Action does not make the review private.

Why GLM 5.3 Flash

The model choice came down to cost, context, and the job. Pull request review is asynchronous. I do not need chat latency. I need enough context for the diff and enough judgment to identify a concrete defect without turning every preference into a finding.

On August 28, 2026, OpenRouter listed GLM 5.3 Flash at $0.075 per million input tokens and $0.25 per million output tokens, with a one-million-token context window. Those prices include a limited Z.ai discount through September 9. The same page lists the normal Z.ai rate at $0.15 input and $0.50 output per million tokens.

My three-call test stayed below half a cent at the discounted rate. Doubling that measured cost still leaves the same test below one cent. That is cheap enough to review the first pull request and then review the corrected commit instead of treating the first bot pass as final.

This is a useful result, not a benchmark. I tested one planted case and then used the setup on real work. I have not compared GLM 5.3 Flash against every budget model or measured recall across a labeled defect set.

The small configuration that matters

PR-Agent reads a .pr_agent.toml file from the repository root. These are the settings doing the real work in my setup.

[config]
model = "openrouter/z-ai/glm-5.3-flash"
fallback_models = ["openrouter/z-ai/glm-5.3-flash"]
custom_model_max_tokens = 1000000
max_model_tokens = 1000000
persistent_inline_comments = true
restricted_mode = true

[github_action_config]
auto_review = true
auto_describe = true
auto_improve = false
handle_push_trigger = true
push_commands = ["/review"]

[pr_reviewer]
require_score_review = true
persistent_comment = true

These two token settings do different jobs. custom_model_max_tokens tells PR-Agent how much context an unknown model supports. max_model_tokens replaces PR-Agent's separate 32,000-token quality cap. Without the second setting, PR-Agent can prune a diff even when the model has room for it.

I missed that distinction in the first version of this article. The production logs made it plain. Reviews with 41,590, 43,233, and 63,145 input tokens all reported pruning diff at the 32,000-token limit. The setup now gives both settings a one-million-token ceiling, below GLM's 1,310,720-token context window. Those three diff sizes now fit without token-budget pruning. Huge one-shot reviews can still lose focus, so deterministic CI and the human pass remain mandatory.

Persistent inline comments prevent the same finding from appearing again after every push. The persistent review setting edits the main score and summary in place. The review follows the latest commit instead of leaving a stack of obsolete verdicts.

I currently let OpenRouter choose the provider. The test logs showed that Z.ai served all three calls. PR-Agent can pin OpenRouter routing to Z.ai, but I have left that option off until I have a reason to give up provider failover.

What happens when a pull request opens

  1. File a reviewable pull request

    A repository-local Codex skill runs the local checks, reads the diff, enforces one concern, writes a problem-first description, and opens a real pull request.

  2. Run deterministic CI

    GitHub Actions installs from the lockfile, then runs TypeScript, tests, the production build, and lint. These checks do not need model judgment.

  3. Describe and review

    PR-Agent reads the diff with the repository's AGENTS.md rules and posts its summary, score, and findings. A push cancels any stale run and starts a review of the new head commit.

  4. Verify every bot claim

    A second Codex skill checks the cited code before changing anything. Real defect, false positive, infrastructure failure, and scope request have different responses.

  5. Ask before merge

    Green checks are not merge authority. The skill asks me for a clear yes. After approval, it watches the deployment for the exact merge commit and runs an independent production smoke.

The first test

I opened a throwaway pull request in Public Parish with two planted review targets. One was the impossible date 2026-02-30. The other tried to bait the model into claiming a referenced variable was missing even though the prose defined it.

The bot caught the date and declined the bait. Its first pass scored the change at 85. I pushed the date fix without commenting a command. The push triggered another review, the same persistent comment moved to 92, and the resolved finding disappeared. The first end-to-end run took 2 minutes and 25 seconds.

The more useful test came on the first production evidence release. PR-Agent noticed Lafayette-specific fallback queries inside a generic action and warned that future parishes would fail. The code looked suspicious. The finding still did not apply to that pull request because Slice 1 created only the Lafayette registry. Adding the next parish belonged in a separate change.

The babysitting skill checked the product scope and source code, left a written reason, and kept the code unchanged. That is exactly why I do not let the reviewer drive. A plausible bot finding can still be wrong for the change being shipped.

The two skills around the reviewer

OpenAI describes a Codex skill as a reusable workflow built from instructions, resources, and optional scripts. Repository skills live under .agents/skills. I checked two into Public Parish so the project carries its own release rules.

file-pr

The filing skill refuses to start from a dirty tree or open a second pull request for the same branch. It runs the full local verification command and reads the actual diff. The title uses a conventional prefix and the body explains the problem before the fix. It opens a real pull request, never a draft, because the work should be ready for review before the model sees it.

babysit-pr

The babysitting skill polls CI, the persistent review, inline threads, and labels. It acts only on feedback newer than the last push. Every finding is a hypothesis until the cited behavior is reproduced in source.

A real issue gets the smallest fix. A false positive gets a written reason and a resolved thread. An infrastructure failure gets a retry only after it is identified as a failure outside the code. A style request or an idea outside the pull request goal does not get built.

After three fix cycles or about thirty minutes without convergence, the skill stops and gives the remaining problem back to a person. A green result reaches the merge gate, not an automatic merge.

What I would change next

The setup has a few honest rough edges. Persistent reviews update the main comment, but each push still leaves a small update stub. The fallback model currently repeats the primary, so it retries the same model instead of moving to another one. OpenRouter routing is not pinned to Z.ai. The cost test is too small to support a model-quality claim.

I would add a small labeled review set before declaring any budget model the best. Seed it with real TypeScript defects, scope-sensitive false positives, security findings, and large diffs. Measure what the reviewer catches, what it invents, how long it takes, and the billed cost. Then compare models without changing the rest of the loop.

For now, GLM 5.3 Flash has cleared the more practical gate. It is inexpensive enough to run repeatedly, it handled the first test, and it has already participated in a real production pull request. The tests and the human gate remain in charge.

Read the setup

The complete configuration, workflow notes, test record, and skill behavior are in the Public Parish repository. Start with pr-agent.md, then inspect .pr_agent.toml and .agents/skills.

The cheap model is worth using. The surrounding rules are what make it safe to trust as one input into a release.