Build an AI-powered Golang code review agent with CircleCI and GitHub webhooks

Fullstack Developer and Tech Author

Code reviews are a crucial step in maintaining code quality, but many developers find them tedious and inconsistent. What if you could get helpful feedback automatically, as soon as a pull request is opened?
In this tutorial, you’ll learn how to set up and integrate an AI-powered code review agent into your Go project. The agent uses the OpenAI API to post contextual suggestions and praise directly on pull requests. You won’t be building the agent from scratch, the core logic is already implemented and ready to use. Your focus will be on running it locally, connecting it to GitHub via webhooks, and enforcing a review workflow with CircleCI.
By the end, you’ll have a working setup that:
- Automatically reviews
.go
files in pull requests using OpenAI - Posts targeted suggestions, praise, and summaries
- Enforces feedback loops using a CircleCI pipeline (with reaction checks and optional edits)
Prerequisites
To follow along, make sure you have the following tools and accounts set up:
- Go (1.20 or newer)
- Download Ngrokfor exposing your local server to GitHub
- GitHub account with a repository to test this on and Personal Access Token, with the
repo
andpublic_repo
scopes - GitHub Webhook for PR events
- OpenAI API Key
- A GitHub account
- A CircleCI Account.
- Basic familiarity with Git and the Go programming language
Setting Up the AI code review agent
Before you connect the pieces, let’s get the agent running locally so it can receive pull request events from GitHub.
Clone the repo
Start by cloning the project and navigating into the directory:
git clone https://github.com/yemiwebby/code-review-agent.git
cd code-review-agent
Set environment variables
Create a .env
file in the project root and add the following keys:
OPENAI_API_KEY=your-openai-key
GITHUB_TOKEN=your-github-token
These credentials allow the agent to talk to both OpenAI and GitHub. You can also export them directly in your terminal if you prefer.
Run the agent locally
Once your environment is set, start the agent:
go run cmd/main.go
This spins up a local server listening on port 8080.
Note: The agent stores AI comments in memory. Restarting the server (or Ngrok) will wipe that state. Keep it running until PR + merge is complete.
Expose the server using Ngrok
To make the local server accessible to GitHub, run:
ngrok http 8080
Ngrok will assign you a public URL that tunnels requests to your local machine. You’ll need this when you set up the webhook.
Make sure both the agent and the Ngrok tunnel are running in separate terminals.
Triggering AI-powered comments
Now that the agent is running and ready to listen, you can give it something to review. You’ll create a simple Go program and push it as a pull request to trigger AI feedback.
Follow along with this example or use your own Go project if you’d rather see the agent in action on real code.
Create a test repository
Start by creating a new folder for your project:
mkdir go-ai-code-review
cd go-ai-code-review
While in the go-ai-code-review
directory, create a new Go module by running this command:
go mod init go-ai-code-review
This generates a go.mod
file in the root directory, which defines the module path and tracks dependencies.
Write a simple Go program
We’ll build a small countdown tool that prints numbers from a starting point down to zero, with a one-second pause between each.
Create a file named main.go
and add the following:
package main
import (
"fmt"
"io"
"os"
"time"
)
func main() {
Countdown(3)
}
func Countdown(start int, writer ...io.Writer) {
output := io.Writer(os.Stdout)
if len(writer) > 0 {
output = writer[0]
}
for {
if start == 0 {
fmt.Fprintln(output, "Go!")
return
}
fmt.Fprintln(output, start)
time.Sleep(time.Second * 1)
start--
}
}
Here, you define a Countdown function that prints each number to the console (or a custom writer) and waits for a second between each print. Once it reaches zero, it prints “Go!” and exits.
Add a unit test
Now, write a test to validate that your countdown behaves correctly.
Create a file named main_test.go
and add the following:
package main
import (
"bytes"
"testing"
)
func TestCountdown(t *testing.T) {
buffer := &bytes.Buffer{}
Countdown(3, buffer)
got := buffer.String()
want := `3
2
1
Go!
`
if got != want {
t.Errorf("got %q want %q", got, want)
}
}
This test passes a buffer as the writer to the Countdown
function and checks the output against the expected string. It’s a quick way to verify the core behavior without relying on os.Stdout
.
Run the test to make sure everything is working as expected:
go test -v
You should see:
=== RUN TestCountdown
--- PASS: TestCountdown (3.00s)
PASS
ok go-ai-code-review 3.395s
This confirms that your countdown logic is solid and now, you’re ready to commit your changes and create a pull request. The AI reviewer will kick in once that PR is open.
Push to GitHub and Add Webhook
With your countdown program ready and the agent running, it’s time to push your code to GitHub and connect the webhook to trigger the AI review.
Commit and push your code
Initialize a new Git repo and push the code to your test repository:
git init
git add .
git commit -m "Initial countdown implementation"
git remote add origin https://github.com/your-username/go-ai-code-review.git
git push -u origin main
This pushes your local code to GitHub where it can trigger webhook events.
Add a webhook to your repository
To let GitHub notify the agent when pull requests are opened or updated, add a webhook:
- Go to your test repo on GitHub
- Go to Settings > Webhooks > Add webhook
- Fill in the form:
- For the payload URL:
https://your-ngrok-url/webhook
- For the content type: application/json
- For the event: Select the Pull request event
- For the payload URL:
- Click Add webhook
This connects GitHub to your local agent (via Ngrok), so PRs can trigger the AI review logic automatically.
CircleCI gatekeeper integration
The AI reviewer provides useful feedback, but it doesn’t guarantee follow-through. To ensure pull requests are properly reviewed before being merged to main
, we’ll introduce a CircleCI workflow that acts as a gatekeeper
.
This pipeline runs on every pull request and checks whether AI-generated comments have been acknowledged with a reaction and, if needed, followed up with a code change. If any comments are left unreviewed, the pipeline blocks the merge.
Add the CircleCI config file
Create a .circleci
folder in your repo and add a config.yml
file with this:
version: 2.1
executors:
go-executor:
docker:
- image: cimg/go:1.24.2
working_directory: ~/project
jobs:
gatekeeper-check:
executor: go-executor
steps:
- checkout
- run:
name: Run Go tests
command: |
echo "Running unit tests..."
go test -v ./...
- run:
name: Skip on main branch
command: |
if [ "$CIRCLE_BRANCH" = "main" ]; then
echo "Skipping gatekeeper check: already on 'main' branch."
exit 0
fi
- run:
name: Trigger AI gatekeeper check
command: |
echo "Triggering AI Review Agent for comment reactions and patch check..."
STATUS_CODE=$(curl -s -w "%{http_code}" -o result.txt "$AI_REVIEW_AGENT_URL/check-reactions?repo=$REPO_NAME")
echo "Status Code: $STATUS_CODE"
echo "-------- Response --------"
cat result.txt || true
echo "--------------------------"
if [ "$STATUS_CODE" -ne 200 ]; then
echo "Gatekeeper failed: AI comments must be reviewed (reaction + patch update) before merging to main."
exit 1
fi
echo "All AI comments acknowledged. Proceeding."
workflows:
review-merge-gatekeeper:
jobs:
- gatekeeper-check
This setup runs your Go tests first, then calls the /check-reactions
endpoint of the AI agent. If any comments are unacknowledged or the code hasn’t changed, the pipeline fails and blocks the merge.
Save all the changes and push to GitHub.
Set up the project in CircleCI
Log in to CircleCI and create a new project. Select the go-ai-code-review
repository (or whichever repo you’re using for this tutorial).
Choose the branch that contains the .circleci/config.yml
file and click Set Up Project. This will trigger the first build automatically.
The pipeline will likely fail at first. That’s to be expected, because you still need to add the required environment variables.
Add environment variables
In CircleCI, go to your project settings and add the following environment variables:
AI_REVIEW_AGENT_URL
: Your public Ngrok URL (e.g.,https://abc123.ngrok.io
)REPO_NAME
: Your GitHub repo inusername/repo-name
format (e.g.,yemiwebby/go-ai-code-review
)
With these in place, the gatekeeper check will start validating PRs. It enforces that:
- Every AI-generated comment is acknowledged with a reaction.
- Suggested code changes have been made, if relevant
- Comments older than 2 minutes are the only ones enforced (grace period)
Protect the main branch
Now that the agent and pipeline are in place, the last step is making sure pull requests don’t skip the review process. GitHub’s branch protection rules help us lock that down directly at the repository level.
Setting up a ruleset ensures that every pull request to main
must pass the AI validation check from CircleCI before it can be merged.
Create a branch protection ruleset
- Go to your GitHub repo and click Settings → Rules → Rulesets → New branch ruleset
- Set the ruleset name: e.g.,
Main Branch Protection
- For enforcement status, select
Active
- For target branches:
- If your default branch is
main
, select that - Otherwise, choose Branch name pattern and enter
main
- If your default branch is
- For branch rules:
- Check Require a pull request before merging
- Check Require conversation resolution before merging
- For Require Status Checks to Pass:
- Check Require branches to be up to date before merging.
- Add a required status check:
- Start typing
gatekeeper
, and selectci/circleci: gatekeeper-check
from the list.
- Start typing
- Click Create to save the ruleset.
This procedure ensures that pull requests must pass the AI reaction and patch validation before being merged into main, fully automating your review enforcement.
Create a new branch
With everything wired up, it’s time to test the full setup by making a small code change and opening a pull request. Just make sure that Ngrok is still running alongside your agent. If it’s been restarted, you’ll need to update the new public URL in your CircleCI environment variables to keep things connected.
Start by creating a new branch:
git checkout -b feature/improve-countdown
Make a small improvement to the Countdown()
logic by updating how the counter decrements:
func Countdown(start int, writer ...io.Writer) {
output := io.Writer(os.Stdout)
if len(writer) > 0 {
output = writer[0]
}
for {
if start == 0 {
fmt.Fprintln(output, "Go!")
return
}
fmt.Fprintln(output, start)
time.Sleep(time.Second * 1)
start = start - 1
}
}
Commit and push the changes:
git commit -am "Improve countdown logic"
git push origin feature/improve-countdown
GitHub will prompt you to open a pull request.
Open a pull request
With your changes pushed to a feature branch, open a pull request targeting main
. This triggers the AI review agent and starts the CircleCI gatekeeper pipeline.
A few things will happen right away:
- Comments from the AI reviewer (summary, suggestions, praise)
- A status check from CircleCI running in the background
- A blocked merge button if the gatekeeper check hasn’t passed yet
View AI comments
Review the pull request conversation. The agent will leave comments based on its analysis of the .go
files, which may include:
- A quick summary of the changes
- Suggestions for improvement
- Positive feedback for things done well
React or refactor, then push again
To satisfy the gatekeeper, either:
- React to each AI comment with a thumbs up or down, or
- Improve the code based on the suggestions and push a new commit
You can even revert the changes and push again to demonstrate that the patch was acknowledged.
This triggers the pipeline again.
Once the gatekeeper verifies that all comments have been reviewed and any necessary updates have been made, the status check will pass. At this point, you can merge the PR.
With the AI comments acknowledged and the pipeline green, you can merge the pull request. Your main branch now shows a properly reviewed and verified change.
Conclusion
You now have a working AI powered code review agent for Go projects, connected to GitHub, enforced by CircleCI, and ready to nudge your team toward delivering better code. It reviews pull requests, posts contextual comments, and blocks merges until each one is acknowledged or resolved.
This setup is lightweight and effective, a solid foundation for automating code reviews without adding noise or friction. While the agent is currently tuned for Go, you can easily adapt it to other languages by tweaking the prompt logic. Review the prompt configuration here.
The code review agent is an open source project, and contributions are welcome — from adding new features to making it smarter or more flexible. If you found it helpful, feel free to star the repo and share it with your team.
Whether you’re extending it with inline suggestions, turning it into a GitHub App, or simply using it as is, this is a powerful starting point for leveling up your developer workflow.
Why not let the bots handle the repetition while you focus on the good stuff?