AutomationFlowsAI & RAG › LLM Code Review in Github Mr

LLM Code Review in Github Mr

LLM Code Review in GitHub MR. Uses httpRequest, lmChatOpenAi, chainLlm. Webhook trigger; 14 nodes.

Webhook trigger★★★★☆ complexityAI-powered14 nodesHTTP RequestOpenAI ChatChain Llm
AI & RAG Trigger: Webhook Nodes: 14 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Chainllm → 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
{
  "name": "LLM Code Review in GitHub MR",
  "nodes": [
    {
      "parameters": {
        "content": "## Edit your own prompt \u2b07\ufe0f\n"
      },
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        460
      ],
      "typeVersion": 1,
      "id": "ff91ffff-cb3c-4921-8073-c3adee4e76c8"
    },
    {
      "parameters": {
        "content": "## Filter comments and customize your trigger words \u2b07\ufe0f"
      },
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        500
      ],
      "typeVersion": 1,
      "id": "9c7d250f-77c0-490f-a221-760ffadb4532"
    },
    {
      "parameters": {
        "content": "## Replace your github URL and token \u2b07\ufe0f"
      },
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -200,
        480
      ],
      "typeVersion": 1,
      "id": "e8b8a21e-d934-4ed7-af3f-a9cb689cce08"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// \u89e3\u6790 patch \u7684\u51fd\u6570\nfunction parsePatch(patch) {\n    const lines = patch.split('\\n');\n    let lastOldLine = 0;\n    let lastNewLine = 0;\n    let positionLine = 0;\n    const originalLines = [];\n    const newLines = [];\n\n    lines.forEach((line, index) => {\n        const match = line.match(/^@@ -(\\d+),\\d+ \\+(\\d+),\\d+ @@/);\n        if (match) {\n            lastOldLine = parseInt(match[1]);\n            lastNewLine = parseInt(match[2]);\n            positionLine = lastNewLine + 1;\n        } else if (line.startsWith('-')) {\n            originalLines.push(line);\n        } else if (line.startsWith('+')) {\n            newLines.push(line);\n        } else if (!line.startsWith('\\\\ No newline at end of file')) {\n            originalLines.push(line);\n            newLines.push(line);\n        }\n    });\n\n    return {\n        lastOldLine: lastOldLine,\n        lastNewLine: lastNewLine,\n        positionLine: positionLine,\n        originalCode: originalLines.join('\\n'),\n        newCode: newLines.join('\\n')\n    };\n}\n\n// \u4ece\u8f93\u5165\u4e2d\u63d0\u53d6\u4fe1\u606f\nconst input = $json[\"patch\"];\nconst parsedData = parsePatch(input);\n\n// \u8f93\u51fa\nreturn {\n    originalCode: parsedData.originalCode,\n    newCode: parsedData.newCode\n};\n"
      },
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        460
      ],
      "typeVersion": 2,
      "id": "4dc1b952-2822-4a00-b3fb-382998e63ef5"
    },
    {
      "parameters": {
        "content": "## Replace your github URL and token \u2b07\ufe0f"
      },
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        460
      ],
      "typeVersion": 1,
      "id": "644b5f17-2728-4503-be94-a49df5c96376"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.pull_request.comments }}",
              "rightValue": 0
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "name": "Need Review",
      "type": "n8n-nodes-base.if",
      "position": [
        -400,
        680
      ],
      "typeVersion": 2,
      "id": "5f93b317-3f3b-4bae-8941-74180c5c24c1"
    },
    {
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $json[\"body\"][\"repository\"][\"full_name\"] }}/pulls/{{ $json[\"body\"][\"pull_request\"][\"number\"] }}/files",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "token YOUR_TOKEN"
            }
          ]
        },
        "options": {}
      },
      "name": "Get Changes",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -140,
        660
      ],
      "typeVersion": 4.1,
      "id": "298b696b-7bbf-4306-8b63-61f3a3f2b0ac"
    },
    {
      "parameters": {
        "fieldToSplitOut": "changes",
        "include": "selectedOtherFields",
        "fieldsToInclude": "patch",
        "options": {
          "disableDotNotation": false,
          "destinationFieldName": "changes",
          "includeBinary": false
        }
      },
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        60,
        660
      ],
      "typeVersion": 1,
      "id": "3db26038-4d63-43cf-8e19-55b121d57318"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.changes }}",
              "rightValue": 0
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "name": "Skip File Change",
      "type": "n8n-nodes-base.if",
      "position": [
        260,
        660
      ],
      "typeVersion": 2,
      "id": "939f3c1d-505b-4643-a6f4-9a80429aeb3e"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// \u89e3\u6790 patch \u7684\u51fd\u6570\nfunction parsePatch(patch) {\n    const lines = patch.split('\\n');\n    let lastOldLine = 0;\n    let lastNewLine = 0;\n    let positionLine = 0;\n    const filteredLines = [];\n\n    lines.forEach((line, index) => {\n        // \u67e5\u627e @@ -17,6 +17,20 @@ \u5f62\u5f0f\u7684\u884c\uff0c\u5e76\u63d0\u53d6\u4fe1\u606f\n        const match = line.match(/^@@ -(\\d+),\\d+ \\+(\\d+),\\d+ @@/);\n        if (match) {\n            lastOldLine = parseInt(match[1]);\n            lastNewLine = parseInt(match[2]);\n            positionLine = lastNewLine + 1;\n        }\n        // \u8fc7\u6ee4\u6389\u201cNo newline at end of file\u201d\u884c\n        if (line.trim() !== '\\\\ No newline at end of file') {\n            filteredLines.push(line);\n        }\n    });\n\n    return {\n        lastOldLine: lastOldLine,\n        lastNewLine: lastNewLine,\n        positionLine: positionLine,\n        patch: filteredLines.join('\\n') // \u8fd4\u56de\u53bb\u6389\u591a\u4f59\u884c\u7684patch\n    };\n}\n\n// \u4ece\u8f93\u5165\u4e2d\u63d0\u53d6\u4fe1\u606f\nconst input = $json[\"patch\"];\nconst changes = $json[\"changes\"];\nconst parsedData = parsePatch(input);\n\n// \u8f93\u51fa\nreturn {\n    lastOldLine: parsedData.lastOldLine,\n    lastNewLine: parsedData.lastNewLine,\n    positionLine: changes,  // \u786e\u4fdd positionLine \u7b49\u4e8e changes\n    patch: parsedData.patch\n};\n"
      },
      "name": "Parse Last Diff Line",
      "type": "n8n-nodes-base.code",
      "position": [
        460,
        460
      ],
      "typeVersion": 2,
      "id": "e6e66503-6867-4266-8050-5ae3d938cd18"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.github.com/repos/{{$('Webhook').item.json['body'].repository.full_name}}/pulls/{{ $('Webhook').item.json.body.pull_request.number }}/comments",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "token YOUR_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": " application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n    \"body\": {{ JSON.stringify($('Basic LLM Chain').item.json[\"text\"]); }},\n     \"commit_id\": {{ JSON.stringify($('Need Review').item.json.body.pull_request.head.sha); }},\n  \"path\": {{ JSON.stringify($('Get Changes').item.json.filename); }},\n  \"position\": {{ $('Parse Last Diff Line').item.json.positionLine }}\n}",
        "options": {}
      },
      "name": "Post Discussions",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1200,
        640
      ],
      "typeVersion": 4.1,
      "id": "31b93a2e-bf75-4dc3-bb9b-0de3b1d43c3a"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "4b8de672-fbc8-41c9-a4b4-a218579206cc",
        "options": {}
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -620,
        680
      ],
      "typeVersion": 1.1,
      "id": "a6e39d35-7114-43bf-903b-b33ede1f3796"
    },
    {
      "parameters": {
        "model": "=GLM-4-Plus",
        "options": {
          "baseURL": "https://open.bigmodel.cn/api/paas/v4/"
        }
      },
      "name": "big model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        820,
        780
      ],
      "typeVersion": 1,
      "id": "725bf6fb-0b89-496a-ab81-8a23d1091d42",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "prompt": "=\n\n```Original code\n {{ $json.originalCode }}\n```\nchange to\n```New code\n {{ $json.newCode }}\n```\nPlease review the code changes in this section:",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "type": "AIMessagePromptTemplate",
              "message": "# Overview:| \u60a8\u662f\u9ad8\u7ea7\u7f16\u7a0b\u4e13\u5bb6Bot\uff0c\u8d1f\u8d23\u5ba1\u67e5\u4ee3\u7801\u66f4\u6539\u5e76\u63d0\u4f9b\u5ba1\u67e5\u5efa\u8bae\u3002\u5728\u5efa\u8bae\u4e4b\u521d\uff0c\u9700\u8981\u660e\u786e\u505a\u51fa\u201c\u62d2\u7edd\u201d\u6216\u201c\u63a5\u53d7\u201d\u4ee3\u7801\u53d8\u66f4\u7684\u51b3\u5b9a\uff0c\u5e76\u4ee5\u201c\u53d8\u66f4\u5f97\u5206:\u5b9e\u9645\u5f97\u5206\u201d\u7684\u5f62\u5f0f\u5bf9\u53d8\u66f4\u8fdb\u884c\u8bc4\u5206\uff0c\u8bc4\u5206\u8303\u56f4\u4e3a0-100\u5206\u3002\u7136\u540e\uff0c\u4ee5\u7b80\u6d01\u7684\u8bed\u8a00\u548c\u4e25\u5389\u7684\u8bed\u6c14\u6307\u51fa\u5b58\u5728\u7684\u95ee\u9898\u3002\u5982\u679c\u60a8\u89c9\u5f97\u6709\u5fc5\u8981\uff0c\u53ef\u4ee5\u76f4\u63a5\u63d0\u4f9b\u4fee\u6539\u540e\u7684\u5185\u5bb9\u3002\u4f60\u7684\u8bc4\u5ba1\u63d0\u6848\u5fc5\u987b\u4f7f\u7528\u4e25\u683c\u7684Markdown\u683c\u5f0f"
            }
          ]
        }
      },
      "name": "Basic LLM Chain",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        800,
        640
      ],
      "typeVersion": 1.2,
      "id": "db38a0e7-4c12-45eb-9cb5-f473441be4f9"
    }
  ],
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Need Review": {
      "main": [
        [
          {
            "node": "Get Changes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Changes": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Skip File Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip File Change": {
      "main": [
        [
          {
            "node": "Parse Last Diff Line",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Last Diff Line": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Need Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "big model": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "Post Discussions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "4988315a-70cd-43b4-9f91-85408f6c5dc9",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "YCTsv5Aohm9hZO3I",
  "tags": [
    {
      "createdAt": "2024-10-31T11:12:04.946Z",
      "updatedAt": "2024-10-31T11:12:04.946Z",
      "id": "qFI4u1x8MkoOs1vC",
      "name": "share"
    }
  ]
}

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

LLM Code Review in GitHub MR. Uses httpRequest, lmChatOpenAi, chainLlm. Webhook trigger; 14 nodes.

Source: https://gist.github.com/JeaNile/0ee00f3a855385b4e60f50bf686695b3 — 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

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14
AI & RAG

This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La

Google Sheets, HTTP Request, Slack +10
AI & RAG

The "Short Content" automation is a powerful, all-in-one solution designed to streamline the creation of short videos for social media, marketing, or personal projects. Leveraging cutting-edge AI tool

Chain Llm, Output Parser Structured, OpenAI Chat +4
AI & RAG

🔥 LIMITED-TIME OFFER: AI Video Automation (Previously \$59) Previously Template

Chain Llm, Output Parser Structured, OpenAI Chat +4
AI & RAG

leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.

Supabase, Gmail, Form Trigger +13