Build a GitHub PR Reviewer with n8n

In Day 7, we learned the basic ideas behind AI agents: prompts, tools, and how an AI system can use external tools to complete a task. Today, we are going to build something practical.

First, get n8n running locally ↓

Setup

Install Docker with n8n

Before we build the PR reviewer, you need n8n running on your machine.

Official install options are here: Install n8n with Docker.

Create a Docker volume for n8n data:

docker volume create n8n_data

Then start n8n:

docker run -it --rm \
 --name n8n \
 -p 5678:5678 \
 -e GENERIC_TIMEZONE="America/Los_Angeles" \
 -e TZ="America/Los_Angeles" \
 -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
 -e N8N_RUNNERS_ENABLED=true \
 -v n8n_data:/home/node/.n8n \
 docker.n8n.io/n8nio/n8n

After it starts, open http://localhost:5678 in your browser.

If you want a video walkthrough of n8n installation and a related project, DevOps Interview Buddy using n8n, Ollama, and Gemma, watch this:

Video thumbnail for n8n installation and DevOps Interview Buddy with Ollama and Gemma
n8n install + DevOps Interview Buddy (n8n, Ollama, Gemma) Watch on YouTube ↗

Prefer watching the GitHub PR Reviewer workflow being built step by step?

Video thumbnail for the Day 8 lesson: GitHub PR Reviewer with n8n
GitHub PR Reviewer with n8n — Video Tutorial Watch on YouTube ↗

We will create an AI-powered GitHub Pull Request Reviewer using n8n, GitHub, and OpenAI.

The idea is simple:

A developer creates a Pull Request → n8n gets the changed code → OpenAI reviews the code → n8n posts the AI feedback back to GitHub.
n8n workflow canvas showing Github Trigger, HTTP Request, Code in Python, AI Agent with OpenAI Chat Model, and Create a review
What this shows: the finished n8n workflow. A GitHub trigger starts the flow, HTTP and Python prepare the PR changes, an AI Agent reviews them with OpenAI, and the last node posts the review back to GitHub.

By the end of this lesson, you will understand how different tools can be connected together to build a useful AI automation.

The problem

What problem are we trying to solve?

Before building anything, let's understand the problem.

Imagine that your team uses GitHub to store its code.

A developer creates a new branch:

main
 |
 └── feature/update-deployment

They make some changes and then create a Pull Request (PR).

A Pull Request is basically the developer saying:

I changed some code. Can someone review it before we merge it into the main branch?

Normally, another engineer opens the Pull Request and checks the changes.

For example, they may look for:

  • Security problems
  • Hardcoded passwords or API keys
  • Dangerous commands
  • Incorrect configuration
  • Missing error handling
  • CI/CD problems
  • Infrastructure mistakes

This review process is extremely important.

But it also takes time.

If a team receives many Pull Requests every day, engineers can spend a significant amount of time doing the first round of reviews.

This is where an LLM can help.

We can ask an AI model to perform a first-pass review.

The AI is not going to replace the engineer. Instead, it can quickly look through the changes and point out things that deserve human attention.

The plan

What are we going to build?

Our workflow will look like this:

Six-step flow: developer creates a pull request, GitHub trigger, get changed files, prepare a prompt, OpenAI reviews, post review on GitHub.
A developer opens a PR. n8n collects the changes, OpenAI reviews them, and the feedback goes back to GitHub.

We will build this using five main n8n nodes:

  1. GitHub Trigger — detects that a Pull Request was created.
  2. HTTP Request — gets the actual code changes from GitHub.
  3. Code — converts those changes into a prompt for the LLM.
  4. AI Agent + OpenAI Chat Model — reviews the code.
  5. GitHub Create Review — posts the AI feedback on the Pull Request.
Five n8n nodes: GitHub trigger, HTTP request, Python code, OpenAI, GitHub review.
The five n8n nodes we will connect: trigger, fetch diffs, format prompt, review, post comment.

Don't worry if some of these terms are new. We will go through them one at a time.

The tool

First, what is n8n?

n8n is a workflow automation platform.

It allows us to connect different applications and APIs together.

Instead of writing an entire application from scratch, we can create a visual workflow using boxes called nodes.

Each box performs one task. In this lesson those boxes are GitHub, Python, OpenAI, then GitHub again.

In n8n, these boxes are called nodes.

A node might:

  • Receive an event from GitHub
  • Call an API
  • Run Python code
  • Send something to OpenAI
  • Send a Slack message
  • Write information back to GitHub

You connect these nodes together to create a workflow.

Three ideas

Three n8n concepts you should understand

Before building the workflow, let's understand three important concepts.

1. Nodes

A node represents one step in the workflow.

For example:

GitHub Trigger

might detect a new Pull Request.

The next node:

HTTP Request

might ask GitHub for the changed files.

The next node:

OpenAI

might review those changes.

Think of nodes as individual workers where each worker has one specific job.

2. Credentials

n8n sometimes needs permission to access another service.

For example, if n8n wants to access your GitHub repository, GitHub needs to know:

Is this application allowed to access this repository?

That is where credentials come in.

Instead of putting passwords or API keys directly inside your workflow, n8n stores them securely as credentials.

For this project, we need credentials for:

GitHub
OpenAI

3. Expressions

Expressions allow us to use information from previous nodes.

For example, suppose Pull Request number 8 is created.

We could hardcode:

pulls/8

But then our workflow would only work for PR #8.

Tomorrow somebody might create PR #9.

Next week it might be PR #25.

Instead, we tell n8n:

Get the Pull Request number from the GitHub Trigger.

This is called an expression.

So instead of:

PR = 8

we dynamically get:

PR = Pull Request number from GitHub

This makes the workflow reusable for every Pull Request.

Step 1

Detect a new Pull Request

Our workflow needs to start when something happens.

In our case:

Start the workflow when a Pull Request is created or updated.

For this we use the GitHub Trigger node.

Developer creates a pull request, GitHub sends a webhook, n8n GitHub Trigger starts the workflow.
GitHub tells n8n that a Pull Request event just happened. That message is a webhook.

GitHub sends information about the Pull Request to n8n.

This is commonly called a webhook.

A webhook is simply one application telling another application:

Something just happened.

Here, GitHub tells n8n:

A Pull Request event just happened.
GitHub Trigger

Configure the GitHub Trigger

Add a GitHub Trigger node.

Choose:

Event: Pull Request

Connect your GitHub account using OAuth.

Then select the repository you want to monitor.

For example:

Owner: ideaweaver-ai
Repository: devops-testing
Event: Pull Request

Now execute the node and create a test Pull Request.

GitHub will send information to n8n.

The output will be JSON.

You may see information such as:

action
number
repository
sender
html_url

For example:

action = opened
number = 8
repository = devops-testing
sender = prashant

There will be much more information in the real response.

Don't worry about understanding every field.

We only need a few pieces of information.

A useful n8n feature

Pin Data

While building a workflow, you don't want to create a new Pull Request every time you test another node.

n8n provides a useful feature called Pin Data.

When you pin the GitHub Trigger output, n8n saves that sample response.

You can then continue building your workflow using the same data.

Think of it like taking a snapshot of a real GitHub event, then building the rest of the workflow on that saved test data.

When your workflow is ready, unpin the data and test it with a real Pull Request.

Step 2

Get the actual code changes

At this point, GitHub has told us:

A Pull Request exists.

But we still need to know:

What code actually changed?

This distinction is important.

The GitHub Trigger mainly gives us information about the Pull Request.

For the AI reviewer, we need the actual changed files.

For that, we call the GitHub API.

GitHub API

What is an API?

An API allows one application to request information from another application.

For example, n8n can ask GitHub:

Give me the files changed in Pull Request #8.

GitHub provides an API endpoint for this:

GET /repos/{owner}/{repo}/pulls/{pull_number}/files

For example:

GET /repos/ideaweaver-ai/devops-testing/pulls/8/files

GitHub responds with information about the changed files.

For each file, we may receive information such as:

filename
status
additions
deletions
patch

The most important field for us is:

patch

The patch contains the actual lines that were added or removed.

Why it matters

Why do we need the patch?

Imagine a developer changes this:

path = "/var/log"
shutil.rmtree(path)

The AI needs to see those lines to identify the danger.

If we only tell the AI:

Pull Request #8 was created

there is nothing useful for the model to review.

We need to give it the code changes. The trigger says a Pull Request exists. The next node gets the actual code differences.

HTTP Request

Configure the HTTP Request node

Add an HTTP Request node after the GitHub Trigger.

The request will call GitHub's API.

Conceptually:

https://api.github.com/repos/
        OWNER/
        REPOSITORY/
        pulls/
        PR_NUMBER/
        files

But we should not hardcode these values.

Instead, we get them from the GitHub Trigger.

For example:

Owner      → repository.owner.login
Repository → repository.name
PR Number  → number

The exact path may vary slightly depending on the GitHub Trigger output, so inspect the JSON produced by your trigger.

This is where n8n expressions become useful.

Expressions

Why expressions matter

Suppose today we receive:

PR #8

Tomorrow:

PR #9

And later:

PR #100

Our workflow should work for all of them.

We don't want:

pulls/8/files

We want:

pulls/{PR_NUMBER}/files

where PR_NUMBER comes from the GitHub Trigger.

The same idea applies to the repository owner and repository name.

This makes the workflow dynamic.

Step 3

Prepare the prompt

GitHub now gives us the changed files.

But there is another problem.

GitHub returns structured JSON.

An LLM works better if we give it a clear instruction.

For example:

You are a senior DevOps engineer.

Review the following code changes.

Look for:

- Security problems
- Hardcoded secrets
- Dangerous filesystem operations
- CI/CD problems
- Missing validation
- Infrastructure risks

Explain each issue clearly and suggest a safer solution.

Changed files:

...

We therefore need to convert GitHub's API response into a good prompt.

For this we use an n8n Code node.

Code node

Turn GitHub JSON into one prompt

Add a Code node and choose Python.

The purpose of this node is simple: take GitHub JSON, extract the changed files, combine the patches, add review instructions, and create one prompt.

You can think about this as a data transformation.

The Python code needs to:

  1. Read the changed files.
  2. Extract each filename.
  3. Extract each patch.
  4. Combine them.
  5. Add instructions for the AI reviewer.
  6. Return the final prompt.

The output might look like:

You are a senior DevOps engineer.

Review the following Pull Request.

Check for:

- security problems
- hardcoded secrets
- dangerous commands
- CI/CD mistakes
- filesystem risks
- missing validation

File: cleanup.py

Changes:

+ path = "/var/log"
+ shutil.rmtree(path)

Explain the problems and suggest safer alternatives.

Now we have something the LLM can actually understand and review.

The Python for this Code node is in the same GitHub repo: DevOps-GitHub-PR-Reviewer.

Step 4

Send the prompt to OpenAI

Now we add the AI part.

Add an AI Agent and connect an OpenAI Chat Model.

You will need an OpenAI API credential.

n8n stores the API key inside its credential system so we don't need to put the key directly inside our workflow.

By this point the chain is: GitHub Trigger → HTTP Request → Code → AI Agent → OpenAI.

Inside the AI Agent, use an expression to pass the prompt created by the Code node.

The model receives something like:

You are a senior DevOps engineer.

Review these code changes...

and returns something like:

Potential issue:

The script recursively deletes /var/log.

This is dangerous because /var/log is a system directory.

Consider validating the path and preventing deletion of protected system directories.

That becomes our automated first-pass review.

A useful distinction

Is this really an AI agent?

This is an important distinction.

The LLM itself is not calling GitHub.

n8n is calling GitHub.

The model only receives text and generates text.

n8n listens to GitHub, calls APIs, and posts results. OpenAI only reads the code changes and generates review text.
n8n handles the workflow and external actions. OpenAI is responsible for reasoning about the code.

So n8n is responsible for the workflow and external actions.

The LLM is responsible for reasoning about the code.

Step 5

Post the review back to GitHub

We now have the AI-generated review.

But it is still inside n8n.

We want developers to see it directly inside the Pull Request.

Add another GitHub node.

Choose:

Create a Review

We again dynamically provide:

Owner
Repository
Pull Request Number

Then use the output from the AI Agent as the review body.

Review event

COMMENT vs APPROVE

GitHub reviews can have different outcomes.

For our AI reviewer, we should use:

COMMENT

This means:

Here is some feedback about this Pull Request.

We should not automatically use APPROVE.

Why?

Because LLMs can make mistakes.

The AI may:

  • Miss a security issue
  • Misunderstand code
  • Produce incorrect recommendations
  • Hallucinate problems that don't exist

So our design should be:

AI → COMMENT
Human → final decision

not:

AI → APPROVE → Merge

The human engineer should remain responsible for approving and merging the Pull Request.

Put it together

Complete workflow

We now have our complete pipeline, from a new Pull Request all the way to a COMMENT on GitHub, with a human still reviewing and merging.

This is a simple but useful example of connecting an LLM with real DevOps tools.

Testing

Testing our AI reviewer

We should intentionally create a bad Pull Request to see whether our reviewer catches the problem.

For example:

import shutil

path = "/var/log"

shutil.rmtree(path)

This code is extremely dangerous.

It recursively deletes:

/var/log

A useful AI review should identify problems such as:

Unsafe default path
Recursive deletion
No path validation
No protection for system directories
No existence checks

It should ideally suggest safer approaches as well.

If the model simply responds:

Looks good.

our prompt probably needs improvement.

We can make our instructions more specific about what the model should inspect.

Important

This is a first-pass reviewer

The goal of this project is not to replace human code reviewers.

Think of the AI reviewer as an assistant.

It can quickly scan the Pull Request and say:

These three areas may need attention.

Then a human engineer performs the deeper review.

Pull Request, then AI first-pass review, then human review, then approve, then merge.
The AI provides additional information. The human makes the decision.

The AI provides additional information.

The human makes the decision.

Security

Security considerations

This project is designed for learning.

If you wanted to use something similar in production, you would need additional protections.

For example:

  • Restrict GitHub permissions
  • Protect API keys
  • Limit which repositories the bot can access
  • Ignore extremely large generated files
  • Handle API failures
  • Handle rate limits
  • Validate LLM output
  • Protect against prompt injection
  • Add logging and monitoring
  • Limit token usage and cost

Most importantly, don't give an AI system permission to automatically approve and merge production code without proper controls.

The pattern

What did we learn?

The most important part of this project is not the individual n8n nodes.

It is understanding how the pieces work together.

We built this pipeline:

Five-step pattern: event, collect evidence, prepare context, ask the LLM, take an action.
Event → collect evidence → prepare context → ask the LLM → take an action. That same pattern shows up in many GenAI-for-DevOps workflows.

For our example: GitHub PR → get changed files → create a DevOps prompt → OpenAI reviews the code → post a GitHub comment.

This same pattern appears in many GenAI-for-DevOps applications.

For example:

Kubernetes alert
   ↓
Collect pod logs
   ↓
Send logs to LLM
   ↓
Generate RCA
   ↓
Post to Slack

or:

AWS alarm
   ↓
Collect CloudWatch logs
   ↓
Send evidence to LLM
   ↓
Generate troubleshooting suggestions
   ↓
Create incident report

Once you understand this pattern, you can build many different AI-powered DevOps workflows.

Before you go

Five things to remember

1. n8n connects the tools together.

GitHub, Python, OpenAI, Slack, APIs, and many other systems can become nodes in a workflow.

2. The GitHub Trigger tells us that something happened.

In our example, a Pull Request was created or changed.

3. The GitHub Files API gives us the actual code changes.

The trigger gives us metadata. The Files API gives us the evidence the AI needs to review.

4. The Code node prepares the information for the LLM.

It converts GitHub's structured data into a clear DevOps review prompt.

5. AI provides feedback; humans make the final decision.

Use the AI review as a COMMENT, not as automatic approval.

Final mental model

If you remember only one diagram from this lesson, remember this

Mental model: GitHub something changed, n8n collects the code, GitHub API returns changes, Code node prepares them for AI, OpenAI finds problems, n8n posts back, GitHub shows the AI review comment, human engineer reviews, approves, and merges.
n8n handles the workflow and tools. The LLM analyzes the information. The human makes the final decision.

The most important idea is simple:

n8n handles the workflow and tools. The LLM analyzes the information. The human makes the final decision.

That is our first practical AI-powered DevOps workflow.