{
  "name": "Review GitLab merge requests with parallel Azure OpenAI reviewers",
  "nodes": [
    {
      "id": "7b4c951f-df41-479b-894b-a2807530a58f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3120,
        -384
      ],
      "parameters": {
        "width": 768,
        "height": 848,
        "content": "## How it works\n\nThis workflow runs an AI-assisted review for GitLab merge requests.\n\nWhen a reviewer posts the trigger comment in a merge request discussion, the workflow fetches the changed files, f"
      }
    },
    {
      "id": "e8c95236-4071-43ce-926f-4fa1a7c50dd1",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2256,
        0
      ],
      "parameters": {
        "width": 880,
        "height": 448,
        "content": "## Trigger the review\n\nPost the configured trigger comment in a GitLab merge request discussion to start the workflow.\n\nDefault trigger: `+0`\nChange it in **Workflow Configuration**."
      }
    },
    {
      "id": "3529266d-af18-4585-989b-01af994b9c18",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1312,
        -112
      ],
      "parameters": {
        "width": 800,
        "height": 560,
        "content": "## Fetch and filter changed files\n\nLoad the merge request changes, split them into one file per item, and skip unsupported diffs such as renamed, deleted, or non-commentable files."
      }
    },
    {
      "id": "a3ada654-1ded-4275-8d84-ed3b6e5b3f61",
      "name": "GitLab Discussion Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2160,
        240
      ]
    },
    {
      "id": "8dbf3590-f83f-437e-bcca-88846af6ff2c",
      "name": "Check Review Trigger Comment",
      "type": "n8n-nodes-base.if",
      "position": [
        -1648,
        240
      ]
    },
    {
      "id": "4a7768fd-9c71-4e5c-ae77-06395b94d044",
      "name": "Post Review Started Reply",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1232,
        48
      ]
    },
    {
      "id": "ced91e4b-aea1-48d5-baca-11e61cf53e11",
      "name": "Fetch Merge Request Changes",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1232,
        224
      ]
    },
    {
      "id": "bb0320ac-0086-484f-aba4-812dd83ada77",
      "name": "Split Changed Files",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -960,
        224
      ]
    },
    {
      "id": "eb1c3141-4dbc-44e5-b232-2b96c6aca112",
      "name": "Filter Supported Diffs",
      "type": "n8n-nodes-base.if",
      "position": [
        -720,
        224
      ]
    },
    {
      "id": "3e8222aa-d68a-4366-9167-f039831d8ed5",
      "name": "Prepare Review Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -288,
        208
      ]
    },
    {
      "id": "f979e02c-9f39-41ac-80af-5b02b7735101",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -288
      ],
      "parameters": {
        "width": 608,
        "height": 1184,
        "content": "## Run parallel AI reviewers\n\nAnalyze each changed file with bug, security, and maintainability reviewers.\nEach reviewer returns structured findings for final verification."
      }
    },
    {
      "id": "e2045ae9-9360-4b10-84ba-001dbfe67613",
      "name": "Merge Reviewer Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        928,
        192
      ]
    },
    {
      "id": "833740be-aae9-45e3-ba88-9d326cfb0cb9",
      "name": "Combine Findings",
      "type": "n8n-nodes-base.code",
      "position": [
        1184,
        208
      ]
    },
    {
      "id": "90de14bc-3f94-44bd-95c3-9ffbf2840ee4",
      "name": "Analyze Bugs",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        288,
        -128
      ]
    },
    {
      "id": "d8a1225a-8bfc-4973-9374-7aed82883310",
      "name": "Bug Reviewer Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        208,
        48
      ]
    },
    {
      "id": "109ef89e-9a1b-44fd-a002-8e8bb6ae7c19",
      "name": "Parse Bug Review Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        528,
        48
      ]
    },
    {
      "id": "222b4278-17ea-4390-aed2-48c8d72e4282",
      "name": "Analyze Security Risks",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        288,
        208
      ]
    },
    {
      "id": "2e4fe6a8-ed29-41f2-9987-73e9d45028eb",
      "name": "Security Reviewer Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        208,
        384
      ]
    },
    {
      "id": "7810d8b4-07d2-4eda-8e61-7a7d855e0645",
      "name": "Parse Security Review Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        528,
        384
      ]
    },
    {
      "id": "a91382fc-e303-4dff-91f8-1cd15d2de5c5",
      "name": "Analyze Maintainability Risks",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        288,
        560
      ]
    },
    {
      "id": "6ce560ca-d1b0-450d-ab26-f1aa13f5b7ba",
      "name": "Maintainability Reviewer Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        208,
        736
      ]
    },
    {
      "id": "bf350a82-ed47-425c-ab99-0da161717062",
      "name": "Parse Maintainability Review Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        512,
        736
      ]
    },
    {
      "id": "3d6a3c26-9f14-4f61-bc1f-20d6f0186575",
      "name": "Verify Findings",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1632,
        208
      ]
    },
    {
      "id": "800ab383-e391-407a-85ec-8dc5b8361974",
      "name": "Verifier Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        1552,
        416
      ]
    },
    {
      "id": "c424f47a-cbe8-41bd-bcd5-83f7b1793fde",
      "name": "Parse Verification Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1840,
        416
      ]
    },
    {
      "id": "3ee34738-ec78-48ff-b1f3-b257c2a0929a",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        -16
      ],
      "parameters": {
        "width": 752,
        "height": 592,
        "content": "## Verify and normalize findings\n\nRe-check each finding against the diff, remove weak or duplicate issues, and normalize the final severity and confidence."
      }
    },
    {
      "id": "24d31f5a-dbf6-448f-9141-d562b336813b",
      "name": "Normalize Verified Findings",
      "type": "n8n-nodes-base.code",
      "position": [
        2000,
        208
      ]
    },
    {
      "id": "2d6de0fe-3507-470c-bd76-df6365079d53",
      "name": "Check Findings Exist",
      "type": "n8n-nodes-base.if",
      "position": [
        2416,
        352
      ]
    },
    {
      "id": "35f1a3ee-f0bf-42a6-a0a9-193a477708ef",
      "name": "Build Summary Comment",
      "type": "n8n-nodes-base.code",
      "position": [
        3360,
        432
      ]
    },
    {
      "id": "5ac8e5c4-d800-4f15-9ced-1bc334832716",
      "name": "Build No-Issues Comment",
      "type": "n8n-nodes-base.code",
      "position": [
        3360,
        640
      ]
    },
    {
      "id": "26500903-ef4a-42d8-bdb0-9b50504d1dd9",
      "name": "Post Summary Reply",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3664,
        544
      ]
    },
    {
      "id": "a6977948-6c59-4b2a-a609-61a2b18e9b91",
      "name": "Split Verified Findings",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2704,
        208
      ]
    },
    {
      "id": "d01239bd-af12-48f5-b5eb-d7ef74889886",
      "name": "Filter Publishable Findings",
      "type": "n8n-nodes-base.if",
      "position": [
        2944,
        208
      ]
    },
    {
      "id": "1a91dabf-b880-4c18-b97c-bc6cb1ff764a",
      "name": "Build Inline Comment",
      "type": "n8n-nodes-base.code",
      "position": [
        3616,
        -224
      ]
    },
    {
      "id": "0ed853a6-492a-4a20-aacf-d07c6c46e9a1",
      "name": "Post Inline Review Comment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4192,
        -400
      ]
    },
    {
      "id": "726cc9e8-312f-4bac-b824-c0019a54cabe",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2320,
        -16
      ],
      "parameters": {
        "width": 848,
        "height": 592,
        "content": "## Decide what to publish\n\nPost only findings with `status = keep` and confidence at or above the configured threshold.\n\nIf a valid diff position is found, post an inline comment.\nOtherwise, post a re"
      }
    },
    {
      "id": "49308ef9-c8a9-4480-9bf7-cb76200dc741",
      "name": "Resolve GitLab Diff Position",
      "type": "n8n-nodes-base.code",
      "position": [
        3344,
        -224
      ]
    },
    {
      "id": "77fb631b-0c24-4bf4-a115-77b420b407ac",
      "name": "Check Inline Position",
      "type": "n8n-nodes-base.if",
      "position": [
        3872,
        -224
      ]
    },
    {
      "id": "05e25cbd-06e6-44e9-a33f-3269835c552d",
      "name": "Workflow Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -1904,
        240
      ]
    },
    {
      "id": "b3812b08-44e5-48dc-9e52-1c885051b13d",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -112
      ],
      "parameters": {
        "width": 464,
        "height": 560,
        "content": "## Prepare review context\n\nConvert each diff into a clean review payload with file paths, code snippets, merge request metadata, and diff SHAs needed later for GitLab comments."
      }
    },
    {
      "id": "1d5b16f8-004b-4040-b426-751ebad11b7c",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3248,
        -592
      ],
      "parameters": {
        "width": 1408,
        "height": 656,
        "content": "## Publish review comments\n\nResolve the GitLab diff position for each verified finding and post the final review comment.\n\nIf a valid inline position is available, create an inline diff discussion.\nOt"
      }
    },
    {
      "id": "e877d584-a678-4c86-9645-dcb0872dd440",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3248,
        224
      ],
      "parameters": {
        "width": 656,
        "height": 608,
        "content": "## Post a summary reply\n\nAlways reply to the trigger discussion with either a completion message or a no-issues message.\nInline and fallback review comments are posted separately."
      }
    },
    {
      "id": "5653a6fb-b1a1-4e70-bbf5-6bb8d709fa0d",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -112
      ],
      "parameters": {
        "width": 592,
        "height": 576,
        "content": "## Merge reviewer outputs\n\nCombine findings from all reviewers, remove obvious duplicates, and keep the file and merge request context for final verification."
      }
    },
    {
      "id": "17e3c9d5-0f05-4b66-adb5-7da2d903a8c1",
      "name": "Post Fallback Reply",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4416,
        -160
      ]
    },
    {
      "id": "8300ae3d-115d-44d3-8717-fa123959d1ba",
      "name": "Build Fallback Comment",
      "type": "n8n-nodes-base.code",
      "position": [
        4192,
        -160
      ]
    }
  ],
  "connections": {
    "Analyze Bugs": {
      "main": [
        [
          {
            "node": "Merge Reviewer Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verifier Model": {
      "ai_languageModel": [
        [
          {
            "node": "Verify Findings",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Verify Findings": {
      "main": [
        [
          {
            "node": "Normalize Verified Findings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Findings": {
      "main": [
        [
          {
            "node": "Verify Findings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Bug Reviewer Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Bugs",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Split Changed Files": {
      "main": [
        [
          {
            "node": "Filter Supported Diffs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Inline Comment": {
      "main": [
        [
          {
            "node": "Check Inline Position",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Findings Exist": {
      "main": [
        [
          {
            "node": "Build Summary Comment",
            "type": "main",
            "index": 0
          },
          {
            "node": "Split Verified Findings",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build No-Issues Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Summary Comment": {
      "main": [
        [
          {
            "node": "Post Summary Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Inline Position": {
      "main": [
        [
          {
            "node": "Post Inline Review Comment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Fallback Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Security Risks": {
      "main": [
        [
          {
            "node": "Merge Reviewer Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Build Fallback Comment": {
      "main": [
        [
          {
            "node": "Post Fallback Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Supported Diffs": {
      "main": [
        [
          {
            "node": "Prepare Review Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Reviewer Results": {
      "main": [
        [
          {
            "node": "Combine Findings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Review Context": {
      "main": [
        [
          {
            "node": "Analyze Security Risks",
            "type": "main",
            "index": 0
          },
          {
            "node": "Analyze Bugs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Analyze Maintainability Risks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Configuration": {
      "main": [
        [
          {
            "node": "Check Review Trigger Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build No-Issues Comment": {
      "main": [
        [
          {
            "node": "Post Summary Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Bug Review Output": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Bugs",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Security Reviewer Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Security Risks",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Split Verified Findings": {
      "main": [
        [
          {
            "node": "Filter Publishable Findings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitLab Discussion Webhook": {
      "main": [
        [
          {
            "node": "Workflow Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Verification Output": {
      "ai_outputParser": [
        [
          {
            "node": "Verify Findings",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Post Inline Review Comment": {
      "main": [
        []
      ]
    },
    "Fetch Merge Request Changes": {
      "main": [
        [
          {
            "node": "Split Changed Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Publishable Findings": {
      "main": [
        [
          {
            "node": "Resolve GitLab Diff Position",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Verified Findings": {
      "main": [
        [
          {
            "node": "Check Findings Exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Review Trigger Comment": {
      "main": [
        [
          {
            "node": "Fetch Merge Request Changes",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post Review Started Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Security Review Output": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Security Risks",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Resolve GitLab Diff Position": {
      "main": [
        [
          {
            "node": "Build Inline Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Maintainability Risks": {
      "main": [
        [
          {
            "node": "Merge Reviewer Results",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Maintainability Reviewer Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Maintainability Risks",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Maintainability Review Output": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Maintainability Risks",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}