AutomationFlowsAI & RAG › AI Code Review for GitHub Pull Requests

AI Code Review for GitHub Pull Requests

Original n8n title: Github AI Code Review

Github-Ai-Code-Review. Uses githubTrigger, httpRequest, agent, lmChatOpenAi. Event-driven trigger; 21 nodes.

Event trigger★★★★☆ complexityAI-powered21 nodesGithub TriggerHTTP RequestAgentOpenAI ChatGitHub
AI & RAG Trigger: Event Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "nodes": [
    {
      "parameters": {
        "authentication": "oAuth2",
        "owner": {
          "__rl": true,
          "value": "durbaezgomez",
          "mode": "name"
        },
        "repository": {
          "__rl": true,
          "value": "test-ai-code-review",
          "mode": "name"
        },
        "events": [
          "pull_request"
        ],
        "options": {}
      },
      "name": "GitHub Trigger",
      "type": "n8n-nodes-base.githubTrigger",
      "typeVersion": 1,
      "position": [
        100,
        500
      ],
      "id": "3b1d5804-8872-41cc-a4eb-11ac5f6fdaec",
      "credentials": {
        "githubOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "basicAuth",
        "url": "={{ $('Fetch Files Changed List').all()[0].json[0].contents_url }}",
        "options": {}
      },
      "name": "Fetch Files Info",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        520,
        500
      ],
      "id": "db7a1580-8115-4859-bad7-8b842c6d0d7b",
      "executeOnce": false,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "basicAuth",
        "url": "={{ $('GitHub Trigger').item.json.body.pull_request.url }}/files",
        "options": {}
      },
      "name": "Fetch Files Changed List",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        340,
        500
      ],
      "id": "e2906630-987f-4aa2-aab5-ad9a3cfab9fc",
      "executeOnce": false,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "basicAuth",
        "url": "={{ $json.download_url }}",
        "responseFormat": "string",
        "options": {}
      },
      "name": "Download Changes Files",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        900,
        420
      ],
      "id": "dc56f870-a3f7-4569-b4a0-044a7792ba34",
      "executeOnce": false,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "basicAuth",
        "url": "={{ $('GitHub Trigger').item.json.body.repository.contents_url.replace(\"{+path}\", $json[\"path\"])}}",
        "options": {},
        "queryParametersUi": {
          "parameter": [
            {
              "name": "path",
              "value": "={{ $json.path }}"
            }
          ]
        }
      },
      "name": "Download Destination branch files",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        700,
        620
      ],
      "id": "b42775c2-8d42-498b-9689-335672ad5eba",
      "executeOnce": false,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "basicAuth",
        "url": "={{ $json.download_url }}",
        "responseFormat": "string",
        "options": {}
      },
      "name": "Download Destinatio Files",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        900,
        620
      ],
      "id": "85093941-dd03-4563-8db6-6d37c0bf8b6a",
      "executeOnce": false,
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "agent": "conversationalAgent",
        "promptType": "define",
        "text": "={{ $('Merge').all()}}",
        "options": {
          "systemMessage": "Goal:\nAnalyze two files provided in a JSON format. Each file contains its fileName, content, and associated branch. The goal is to review the files content changes between the \u201cdestination\u201d and \u201cpullRequest\u201d - which contains suggested changes to the files contents focusing on:\n\t\u2022\tSyntax improvements\n\t\u2022\tLogic enhancements\n\t\u2022\tTypographical errors\n\t\u2022\tSubtle suggestions to improve code quality\n\nWhen responding, be concise, providing short, actionable feedback and examples of improvements when necessary. DO not mention the branch or file name as it is implied by the PR info. Mention if no issues are found and encourage merging the Pull Request in that scenario. Do not use any form of politeness, restrain yourself to only constructive and technical feedback sentences.\n\nThe output should only include your feedback and absolutely nothing more. Always structure your output so the feedback response is a single string and is in a json format property called \"comments\". "
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        1800,
        500
      ],
      "id": "b17111f1-5a1d-4733-a40c-f35e7ef3f13c",
      "name": "AI Agent",
      "executeOnce": false
    },
    {
      "parameters": {
        "model": "mistralai/mistral-7b-instruct:free",
        "options": {
          "baseURL": "https://openrouter.ai/api/v1"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1,
      "position": [
        1820,
        660
      ],
      "id": "7f76c8bd-2868-4180-aea4-dea3abda28d8",
      "name": "OpenRouter Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "fc941946-5c04-4d19-82b9-35a6df5e4bff",
              "name": "fileName",
              "value": "={{ $('Fetch Files Info').item.json.name }}",
              "type": "string"
            },
            {
              "id": "bee8e5ad-1dc9-44be-9401-7e8afd509111",
              "name": "content",
              "value": "={{ $json.data }}",
              "type": "string"
            },
            {
              "id": "ee3ef281-44d3-4531-a406-a7305ed643f2",
              "name": "branch",
              "value": "pullRequest",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1140,
        420
      ],
      "id": "c665e824-738a-46a5-94d3-c7930a4e095e",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "fc941946-5c04-4d19-82b9-35a6df5e4bff",
              "name": "fileName",
              "value": "={{ $('Download Destination branch files').item.json.name }}",
              "type": "string"
            },
            {
              "id": "bee8e5ad-1dc9-44be-9401-7e8afd509111",
              "name": "content",
              "value": "={{ $json.data }}",
              "type": "string"
            },
            {
              "id": "7cf116f7-6d6a-44fa-91c0-41f38f321a66",
              "name": "branch",
              "value": "destination",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1140,
        620
      ],
      "id": "5e0f7445-b2d3-4d7b-af5f-95989e36f239",
      "name": "Edit Fields1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1360,
        500
      ],
      "id": "f786d703-86b4-4c59-88a7-7f8daebe15a2",
      "name": "Merge"
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "review",
        "owner": {
          "__rl": true,
          "value": "durbaezgomez",
          "mode": "name"
        },
        "repository": {
          "__rl": true,
          "value": "={{ $('GitHub Trigger').all()[0].json.body.repository.name }}",
          "mode": "name"
        },
        "pullRequestNumber": "={{ $('GitHub Trigger').all()[0].json.body.number }}",
        "event": "comment",
        "body": "={{ 'AI REVIEW: '+ $json.output }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.github",
      "typeVersion": 1,
      "position": [
        2240,
        500
      ],
      "id": "55403194-5114-4446-a061-26d26a2dd0c1",
      "name": "GitHub",
      "credentials": {
        "githubOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst result = items.reduce((acc, item, index) => {\n  acc[`item${index + 1}`] = item; // \n  return acc;\n}, {});\n\nreturn result"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1540,
        500
      ],
      "id": "b09c0a23-2d58-4b5d-a4b3-f84f0cc75a4d",
      "name": "Code1"
    },
    {
      "parameters": {
        "content": "## GitHub trigger \n**on New Pull Request**",
        "height": 520,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        40,
        300
      ],
      "id": "26d43e22-25e4-4ea1-8435-a087ae8c8801",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Files extraction\n**Fetching info on edited files and their content**",
        "height": 520,
        "width": 800,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        280,
        300
      ],
      "id": "0a14d08e-20e3-4928-b5bf-23a60df25eb2",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## Data formatting\n**Format data to provide a pair of files to AI: 1 from pull request, another from the destination branch**",
        "height": 520,
        "width": 660
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1080,
        300
      ],
      "id": "3d1975a8-b6d9-4bbd-b716-3d8cca099f5f",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## AI Agent\n**Analyzes changes in files and provides feedback**",
        "height": 520,
        "width": 380,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1740,
        300
      ],
      "id": "85af26e7-9344-4435-b380-f45ab95f222e",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "## Output\n**Output AI Agent feedback as a comment on the PR**",
        "height": 520,
        "width": 340,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2120,
        300
      ],
      "id": "20051c78-bf4d-4092-a32e-1873399afcea",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "local data manipulation",
        "height": 80,
        "width": 150
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        200,
        180
      ],
      "id": "e1bca368-c82c-43df-8037-89fcd30632fe",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "HTTP requests",
        "height": 80,
        "width": 150,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        40,
        180
      ],
      "id": "2f014a0b-158a-4b0f-be3a-15a1cd5f8671",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "AI",
        "height": 80,
        "width": 150,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        360,
        180
      ],
      "id": "6f03602d-6180-4861-ac1d-a885470103cf",
      "name": "Sticky Note7"
    }
  ],
  "connections": {
    "GitHub Trigger": {
      "main": [
        [
          {
            "node": "Fetch Files Changed List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Files Info": {
      "main": [
        [
          {
            "node": "Download Changes Files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Download Destination branch files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Files Changed List": {
      "main": [
        [
          {
            "node": "Fetch Files Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Changes Files": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Destination branch files": {
      "main": [
        [
          {
            "node": "Download Destinatio Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Destinatio Files": {
      "main": [
        [
          {
            "node": "Edit Fields1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "GitHub",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Github-Ai-Code-Review. Uses githubTrigger, httpRequest, agent, lmChatOpenAi. Event-driven trigger; 21 nodes.

Source: https://github.com/caioross/n8n_Workflows/blob/1686b66af0462dfce267af508b0a487aa5f41e18/workflows/github-ai-code-review.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Code Review workflow. Uses lmChatOpenAi, githubTrigger, httpRequest, github. Event-driven trigger; 14 nodes.

OpenAI Chat, Github Trigger, HTTP Request +3
AI & RAG

PR_Automation. Uses githubTrigger, lmChatOpenAi, httpRequest, github. Event-driven trigger; 13 nodes.

Github Trigger, OpenAI Chat, HTTP Request +2
AI & RAG

My workflow 250630. Uses httpRequest, lmChatOpenAi, outputParserStructured, gmail. Event-driven trigger; 37 nodes.

HTTP Request, OpenAI Chat, Output Parser Structured +5
AI & RAG

Before adding a new npm package as a dependency, you should know if it's actively maintained, widely used, and safe to build on. This workflow does that analysis automatically.

@Mendable/N8N Nodes Firecrawl, OpenAI Chat, Form Trigger +6
AI & RAG

This workflow analyzes any npm package and delivers a data-driven recommendation using Firecrawl + APIs + AI reasoning.

Google Gemini Chat, @Mendable/N8N Nodes Firecrawl, OpenAI Chat +6