// answer

How to keep AI coding agents from shipping unreviewed code

Short answer

Keep AI coding agents in a draft-only lane: let them open branches or pull requests, require human approval, require status checks, and block direct pushes to release branches.

Other people are working this out at the same time: See what people are building

How do I keep AI coding agents from shipping unreviewed or untested code

Keep the agent in a draft-only workflow. Let it create branches or pull requests, then require human approval and passing checks before merge. Protect release branches so the agent cannot push directly, and give it only the permissions it needs to propose changes, not publish them. GitHub supports branch protection rules that require reviews and status checks before merge, and GitLab supports merge request approval and protected-branch controls that serve the same purpose.

The mistake people make is trusting the agent at the wrong boundary. A coding agent can be useful for writing a patch, but shipping is a separate action. The release boundary needs a hard gate, because code that looks fine in a diff can still break at runtime, fail a hidden test, or overwrite a manual fix from another branch. A draft pull request is work in progress, not approval.

Set branch protection on the branches that matter, usually main, release, or whatever branch production deploys from. Require pull request reviews before merging, require status checks before merging, and block bypasses for repository admins if your platform supports it. GitHub documents those controls directly, including the option to require code owner review and the option to prevent force pushes and deletions on protected branches.

Require tests to pass before merge, and make those tests real. A linter is not enough by itself. Use unit tests, integration tests, and the checks that catch deployment breakage in your stack. GitHub’s protected-branch rules can require status checks, and those checks must pass before the pull request can be merged. GitHub also notes that required status checks can be tied to a specific GitHub App, which helps prevent a random process from marking work complete.

Make the agent prove the change in a branch, not in production. A good pattern is: the agent edits code, opens a pull request, attaches a test plan, and stops. A human reviews the diff, runs or inspects the checks, and merges only after the checks are green. If the agent is also allowed to merge, then the review step becomes a suggestion instead of a gate, and the system stops protecting you.

Use code owners for sensitive paths. If a file controls auth, billing, deployment, or database migrations, require review from the people who own that area. GitHub supports code owner reviews on protected branches, and that matters because an agent can make a change that is syntactically valid but operationally wrong. A human owner is the one who knows whether a change fits the architecture and the rollback plan.

Separate write access from merge access. The agent may need permission to create a branch or update a pull request, but it does not need permission to push to the protected branch. GitHub’s branch protection rules can restrict who can push to matching branches, and GitLab’s protected-branch settings can block branch modification and merge request shortcuts that would otherwise bypass review. This is the difference between “can prepare code” and “can release code.”

Limit the agent’s credentials so it cannot act outside the repo or environment it owns. The common failure mode is credential sprawl: one token that can edit code, trigger deploys, and access secrets. Split those permissions. Give the agent only the repo scope needed to open a branch or PR, keep deployment credentials separate, and keep secret access out of the editing path. If the agent cannot reach the deploy step, it cannot bypass review by accident or by a bad prompt.

Treat test failure as a release stop, not a warning. Required checks need to run on the exact branch state you plan to merge. GitHub notes that checks from earlier commits do not satisfy the requirement when branch protection expects the latest code. That matters with AI agents because they often iterate quickly, and an approval on an older commit can become stale as soon as new code lands.

Put the human review on a short checklist. The reviewer should confirm three things: the diff matches the ticket, the tests cover the changed behavior, and the change has an undo path. When people skip one of those, they usually trust the generated code path too much. The inconvenience is real, because review takes longer than merge. That cost is cheaper than debugging a production incident caused by code nobody intended to ship.

For teams using Google Play release flow, keep the same principle at the app boundary. A test track is where you validate the build, not where you prove the agent can ship safely. Google Play’s current testing requirements for personal accounts created after 13 November 2023 require a closed test with at least 12 opted-in testers for 14 continuous days before production access, and internal testing does not count toward that closed-test requirement.

If you work with mobile or other release pipelines, keep your testing exchange inside your own property. DevConnect is one way to organize reciprocal testing without handing release control to an agent or paying for fake engagement, and it is easy to connect that process to your own branch and app review gates: https://devconnectplatform.com. The useful pattern is still the same, tester feedback comes back into review, and the merge stays blocked until the checks pass.

The inconvenient part is that AI agents are best when they can move fast, and safe release is slower by design. The right compromise is not more freedom for the agent, it is better automation around the gate: required reviews, required checks, protected branches, and a deployment path that only humans can approve. If the agent can draft, test, and explain, that is enough. If it can also ship, you have removed the control that keeps the system trustworthy.

A practical setup looks like this: the agent works on ai/task-123, opens a pull request, attaches test output, and tags the owner. The owner reviews, the CI suite runs, and the merge button stays blocked until the checks pass. The release branch stays protected, and the deploy job only reads from merged code. That gives you the speed of AI drafting without giving up the review step that prevents bad code from shipping.

If you want the shortest rule, use this: AI can propose, humans approve, tests must pass, and protected branches decide what ships. Everything else is implementation detail.

Frequently asked questions

Should the agent be allowed to merge its own pull requests

No. Keep merge permission with humans or a tightly controlled release process, and require review plus checks before anything reaches the protected branch.

Are tests alone enough to stop bad AI code from shipping

No. Tests catch part of the risk, but branch protection and human review stop bad code from bypassing the test suite or shipping on an unreviewed path.

What is the safest branch setup for an AI coding agent

A separate work branch, pull requests only, required approvals, required status checks, and no direct pushes to the release branch.

How do protected branches help with AI-generated code

They make review and test results mandatory before merge, which turns the agent into a contributor instead of a release actor.

Know someone stuck on this? Send them the answer.

Sources

Every link here was fetched and confirmed to resolve before this page went live.

More on this topic: Building with AI

Related questions

Not the question you had?

Ask it. Every source gets fetched and checked before anything goes up, so it takes a day or two, and questions that cannot be answered honestly do not get a page at all.

No account, no email address needed.

Everyone here builds with AI, and says so

DevConnect is for developers who use AI and are honest about it. The interesting part is not that the code was generated, it is what you did with it afterwards.