How you can set up pull requests to get an automatic first review

Give every pull request an automatic first review the moment it opens, and send each new pull request and its review to a dedicated Slack channel. Here is how the pieces fit.

The Slack logo on a soft cream background

Nobody enjoys being the first reviewer on a pull request. Before you reach the interesting part, you have to hunt for the forgotten debug line, the password someone pasted in by accident and the function that quietly swallows its errors. A first review hands that chore to an AI model. The moment a pull request opens, a small service reads the changes and leaves a real review on GitHub: approve, or request changes, with a short note explaining why. A person still makes the final call. The difference is that by the time they sit down, the obvious problems are already on the table, and the whole team can see them in Slack.

How the pieces fit

There are three parts. GitHub is the doorbell: it can send a webhook, an HTTP POST describing the event, to an address you choose whenever something happens in a repository, such as a pull request being opened. Your service is the reader: it receives that message, fetches the changes and asks an AI model to review them the way a careful senior engineer would. The review is the result: the service posts it back on the pull request, and can also announce it in a Slack channel set aside for pull requests.

None of this needs a big server. Any small web endpoint that can accept a POST request and make a few API calls will do, whether that is a serverless function, a tiny app on a cheap host or a spare machine under a desk. It sits idle most of the day and only wakes up when a pull request arrives, which makes it one of the cheapest colleagues you will ever have. The Slack part is optional, but once pull requests come to you, going back to refreshing the pull requests tab feels like checking the mailbox every ten minutes.

Setting up the reviewer

Your webhook address is public, so anyone can knock. When you create the webhook in GitHub, give it a long random secret. GitHub then signs every delivery and sends the signature in the X-Hub-Signature-256 header. Your service computes the same HMAC-SHA256 signature over the raw request body and compares the two with a constant-time check, not a plain equals. No match, no review. Subscribe only to pull request events, and check the action before doing any work. Opened, reopened, synchronize (new commits pushed) and ready_for_review cover most cases. Someone renaming a label does not need an AI opinion.

GitHub expects a response within 10 seconds, or it counts the delivery as failed. An AI review nearly always takes longer, so reply straight away and do the thinking in the background with a queue or background task. Then fetch the diff and put a size cap on it, so a pull request that touches a thousand files does not run up your bill. Finally, write the prompt like a job description: look for real bugs, leaked secrets, injection risks and missing error handling. Tell it that style nits deserve a mention but never a block, or people will learn to ignore it within a week.

Posting the review on GitHub

Ask the model for structured output with two fields: an outcome, either approve or request changes, and the review text. Then post it through GitHub's API for creating a pull request review, which accepts an event of APPROVE, REQUEST_CHANGES or COMMENT. Use the first two. A proper review shows up in the pull request's review status, where it counts, instead of drifting down the comment thread. Make one rule non-negotiable: the outcome and the text must agree. A review that says ship it while formally requesting changes is worse than no review at all.

Give the reviewer its own identity, such as a GitHub App or a separate bot account, with only the permissions it needs. That makes it obvious which reviews came from the machine, and it sidesteps a quirk: GitHub does not let authors approve their own pull requests, so a reviewer posting under your personal account can never approve your work. Have it skip pull requests that it or other automations opened, too. Two bots politely reviewing each other's reviews forever is funny exactly once, and then it is just a very long thread.

A pull request channel, the quick way

Reviews on GitHub are useful, but most teams live in Slack. A dedicated channel where every new pull request appears means nobody has to remember to go looking. The fastest way to get one is GitHub's official app for Slack. Once a workspace admin has installed it, create a channel just for pull requests, invite the app with /invite @github, connect your GitHub account when it asks, and run /github subscribe owner/repo in that channel. From then on, new and merged pull requests show up there without any code on your side.

Out of the box, the subscription is chatty. It also covers issues, commits to the default branch, releases and deployments. To keep the channel about pull requests, trim it with /github unsubscribe owner/repo issues commits releases deployments, then add reviews with /github subscribe owner/repo reviews. The app groups each pull request into a thread whose top message shows its latest status, and reviews land in that thread. Because your automatic reviewer posts a real GitHub review, its outcome appears in Slack next to everyone else's, and you have not written a single line of Slack code.

A pull request channel with your own bot

If you want the message in exactly your format, say a one-line summary of the review with the outcome up front, build a small Slack app of your own. Create it in Slack's app settings, add the chat:write scope under Bot Token Scopes on the OAuth and Permissions page, and install it to your workspace. That gives you a bot token, which belongs to the app rather than to a person, so it keeps working if whoever installed it leaves. Store it like the webhook secret: in an environment variable or secret store, never in the repository.

Next, create the pull request channel and invite your app with /invite followed by its name. New Slack apps cannot post in channels they have not joined, and trying anyway is how you meet the not_in_channel error. When a pull request opens, have your service call Slack's chat.postMessage method with the channel ID, the title, the author and a link. When the review is done, post the outcome as a reply by passing that first message's timestamp as thread_ts, so each pull request gets its own tidy thread. If you only need one-way posting, an incoming webhook URL tied to that channel also works. Treat it as a secret too.

Keeping it safe and sensible

Models occasionally return something that is not valid JSON, or an outcome you never asked for. Decide in advance what happens then, and fail closed: if the output cannot be read, or the outcome is not one of the two allowed values, treat it as request changes with a note asking a human to take a look. A reviewer that fails closed will sometimes annoy you, but it will never wave through something it did not actually check. And when your size cap cut the diff short, say so in the review, so nobody assumes every line was read.

Keep the humans in charge. A branch rule that requires approving reviews before merging, with the count set high enough that a person must approve too, keeps the automatic review a helpful first pass rather than a rubber stamp. Keep Slack light, too: one message per pull request with the review in its thread is plenty, and Slack's docs say chat.postMessage generally allows about one message per second per channel anyway. Then watch how people use it. If they start muting the channel or skimming past reviews, tighten the prompt and trim the subscription. A channel people read beats a thorough one they ignore.

That is the whole setup: a doorbell you can trust, a quick reply, a clear job description, a result that says what it means, and one Slack channel where every pull request and its first review show up together. An automatic first review will not replace the person who knows why the code exists, and it is not meant to. It just means that when a human opens the pull request, the leaked key, the missing error check and the obvious bug are already flagged. After a few weeks, opening a pull request without one feels like leaving the house without checking for your keys.