TutorialsJun 13, 202510 min read

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

Olususi Oluyemi

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:

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.

Ngrok tunnel

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:

  1. Go to your test repo on GitHub
  2. Go to Settings > Webhooks > Add webhook
  3. 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
  4. Click Add webhook

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).

CircleCI project

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.

Pipeline failed

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 in username/repo-name format (e.g., yemiwebby/go-ai-code-review)

CircleCI environment variables

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

  1. Go to your GitHub repo and click Settings → Rules → Rulesets → New branch ruleset

GitHub rulesets

  1. Set the ruleset name: e.g., Main Branch Protection
  2. For enforcement status, select Active
  3. For target branches:
    • If your default branch is main, select that
    • Otherwise, choose Branch name pattern and enter main
  4. For branch rules:
    • Check Require a pull request before merging
    • Check Require conversation resolution before merging
  5. For Require Status Checks to Pass:
    • Check Require branches to be up to date before merging.
  6. Add a required status check:
    • Start typing gatekeeper, and select ci/circleci: gatekeeper-check from the list.

GitHub Status Check

  1. 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.

Compare and 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.

Open pull request

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.

CircleCI pipeline

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?


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.