AutomationFlowsAI & RAG › Convert Github Commits Into Review-ready Pull Requests with Google Gemini

Convert Github Commits Into Review-ready Pull Requests with Google Gemini

ByAhmed Salama @ahmedsalama on n8n.io

Categories Developer Automation, AI Agents, GitHub Automation, DevOps Productivity

Event trigger★★★★☆ complexityAI-powered19 nodesGoogle Gemini ChatOutput Parser StructuredMcp TriggerTool WorkflowExecute Workflow TriggerAgentGithub ToolHTTP Request
AI & RAG Trigger: Event Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #13118 — we link there as the canonical source.

This workflow follows the Agent → Chainllm 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
{
  "id": "Y6oy5VN_oASw3lZR2RpMk",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Agent to respond to github repo issues",
  "tags": [],
  "nodes": [
    {
      "id": "1e461404-a788-40d5-8c41-e2f24e062cd0",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        272,
        624
      ],
      "parameters": {
        "options": {
          "temperature": 0.5
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3ff48ae4-f4a8-4ed4-a878-caf91b19338d",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        544,
        624
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"owner\": \"GitHub repository owner username\",\n\t\"repo\": \"GitHub repository name\",\n\t\"branch_name\": \"Source branch name for the pull request\",\n\t\"base_branch\": \"Target branch name (usually main or master)\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "a79a9efb-4269-44ad-a33b-3cb0d9f1a54b",
      "name": "Check for Repository error",
      "type": "n8n-nodes-base.if",
      "position": [
        992,
        272
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "335ff773-f79e-4c59-99bd-7f617bc00b06",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.message }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "0c9f5f07-8059-48d7-aa97-9ea45d64dd8d",
      "name": "MCP Server Trigger for Github",
      "type": "@n8n/n8n-nodes-langchain.mcpTrigger",
      "position": [
        128,
        -352
      ],
      "parameters": {
        "path": "a2c1b2dd-32ed-463a-97c0-0f7139719c3c"
      },
      "typeVersion": 2
    },
    {
      "id": "c96743bb-f689-4aa4-a365-35c2b918b9be",
      "name": "create_github_pr",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        464,
        -80
      ],
      "parameters": {
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "Y6oy5VN_oASw3lZR2RpMk",
          "cachedResultUrl": "/workflow/Y6oy5VN_oASw3lZR2RpMk",
          "cachedResultName": "My workflow"
        },
        "description": "Creates a GitHub Pull Request. IMPORTANT: You must provide the full repository owner and name (e.g., 'AhmedSAAhmed/Example-Auth-service') even if you have a local git context, so the backend API can route the request correctly.",
        "workflowInputs": {
          "value": {},
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8def05a1-46d6-42d7-8039-a25340c0438f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -320
      ],
      "parameters": {
        "width": 576,
        "height": 800,
        "content": "## How it works\n\nA GitHub issue triggers the MCP server.\n\nMCP forwards the issue context to this workflow.\n\nRepository details are extracted using AI.\n\nCommits from the target branch are fetched.\n\nCommit messages are summarized into intent.\n\nAn LLM generates a PR title and description.\n\nA pull request is created via GitHub API.\n\n## Setup steps\n\nEnable MCP and connect it to your GitHub repo.\n\nConfigure GitHub API credentials with PR access.\n\nSet default base branch, for example main.\n\nConnect an LLM, such as Google Gemini.\n\nEnsure the sub-workflow is callable and active.\n\n## Customization\n\nModify prompts to align with your issue template.\n\nEnforce branch or naming rules before PR creation.\n\nAdd guards to skip draft or WIP issues."
      },
      "typeVersion": 1
    },
    {
      "id": "92915031-6779-4b8a-bef5-ba27acac07f5",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -496
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 576,
        "content": "## MCP Issue Trigger\n\nListens for new or updated GitHub issues via MCP and starts the automation flow."
      },
      "typeVersion": 1
    },
    {
      "id": "89bb2592-02bd-4345-ae79-39bd4f8862a5",
      "name": "Subworkflow Entry Point",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -16,
        368
      ],
      "parameters": {
        "inputSource": "passthrough"
      },
      "typeVersion": 1.1
    },
    {
      "id": "336cb283-c4ff-4c00-852e-d8d8a0ab1ed3",
      "name": "Extract Repo & Branch Context",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        320,
        368
      ],
      "parameters": {
        "text": "You are a data extraction assistant. Your task is to extract structured repository information from natural language queries about GitHub pull requests. Always provide all four fields: owner, repo, branch_name, and base_branch. Use the defaults provided when information is not explicitly mentioned in the query.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "7f6cb32c-7363-4fa4-b01f-55ca9ee4344d",
      "name": "Fetch GitHub Issues",
      "type": "n8n-nodes-base.githubTool",
      "position": [
        112,
        -80
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/AhmedSAAhmed"
        },
        "resource": "repository",
        "returnAll": true,
        "repository": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/AhmedSAAhmed/Dog-Classifier-CNN"
        },
        "authentication": "oAuth2",
        "descriptionType": "manual",
        "toolDescription": "Fetch GitHub issue details including the full comment thread, so Cursor can understand complete context and requirements from discussions.",
        "getRepositoryIssuesFilters": {}
      },
      "credentials": {
        "githubOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "c4a0643f-433f-440e-a37b-edfe2ebd7c34",
      "name": "Repo or Branch Validation",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        784,
        368
      ],
      "parameters": {
        "url": "={{ 'https://api.github.com/repos/' + $json.output.owner + '/' + $json.output.repo + '/commits' }}",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "sha",
              "value": "={{ $json.output.branch_name }}"
            }
          ]
        },
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "a2d1a0b6-f3d4-4dc1-83d2-9c68b05b89e6",
      "name": "Build Error Response",
      "type": "n8n-nodes-base.set",
      "position": [
        1424,
        288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a2b9ef40-b4b2-41f6-b038-1d0a800fd3fa",
              "name": "result",
              "type": "string",
              "value": "=Error: I couldn't find the repository \"{{ $('Extract Repository Info').item.json.output.owner }}/{{ $('Extract Repository Info').item.json.output.repo }}\" or branch \"{{ $('Extract Repository Info').item.json.output.branch_name }}\". Please double-check the spelling or ensure the repo is public and the branch exists."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8703f716-6780-44ed-a195-c71e7ce3658c",
      "name": "Prepare PR Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        1424,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9f397f03-26a2-4561-ad25-0251a43c21f3",
              "name": "owner",
              "type": "string",
              "value": "={{ $('Extract Repository Info').item.json.output.owner }}"
            },
            {
              "id": "a19746d8-c346-4c32-a2b5-91035fed234e",
              "name": "repo",
              "type": "string",
              "value": "={{ $('Extract Repository Info').item.json.output.repo }}"
            },
            {
              "id": "5425ce9e-24fa-4680-bd5c-a1e4955dfa56",
              "name": "branch_name",
              "type": "string",
              "value": "={{ $('Extract Repository Info').item.json.output.branch_name }}"
            },
            {
              "id": "3f5ae6c9-9d61-424a-9e31-dc29d35bd195",
              "name": "base_branch",
              "type": "string",
              "value": "={{ $('Extract Repository Info').item.json.output.base_branch }}"
            },
            {
              "id": "11cd1a81-d84d-4138-9c5c-d11a6231e7ff",
              "name": "message",
              "type": "string",
              "value": "={{ $json.commit.message }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e66b73c9-e51b-4db2-a63f-d665f152e516",
      "name": "Create Pull Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2192,
        288
      ],
      "parameters": {
        "url": "={{ 'https://api.github.com/repos/' + $('Extract Repository Info').item.json.output.owner + '/' + $('Extract Repository Info').item.json.output.repo + '/pulls' }}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $('Generate PR Title & Description').item.json.text.split('Title:')[1].split('Description:')[0].trim() }}"
            },
            {
              "name": "head",
              "value": "={{ $('Extract Repository Info').item.json.output.branch_name }}"
            },
            {
              "name": "base",
              "value": "={{ $('Extract Repository Info').item.json.output.base_branch }}"
            },
            {
              "name": "body",
              "value": "={{ $('Generate PR Title & Description').item.json.text.split('Description:')[1].trim() }}"
            }
          ]
        },
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "5607aebb-6cb5-43e3-8c3a-8034bca002c1",
      "name": "Generate PR Title & Description",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1840,
        288
      ],
      "parameters": {
        "text": "=Here are all the commit messages for this branch:\n{{ $('summarize_commits').first().json.concatenated_message }}\n\nPlease write a professional Pull Request:\n1. A Title that summarizes the overall goal of these changes (max 72 characters).\n2. A Description that lists the key changes in bullet points.\n\nIMPORTANT: Return ONLY plain text without any markdown formatting. Do not use asterisks (**), bold, italics, or any other markdown syntax.\n\nFormat your response as:\nTitle: [your title here]\nDescription:\n[your description here]",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "d32a4f90-f1f7-46a6-a64e-643ce2711624",
      "name": "Aggregate Commit Messages",
      "type": "n8n-nodes-base.summarize",
      "position": [
        1632,
        288
      ],
      "parameters": {
        "options": {},
        "fieldsToSummarize": {
          "values": [
            {
              "field": "message",
              "separateBy": "\n",
              "aggregation": "concatenate"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "e08a9e7a-7a99-4278-b80d-4c60fae0dbdb",
      "name": "LLM PR Writer Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1936,
        480
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ab4b402d-e845-4dfa-84da-ae6d02956754",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 1184,
        "height": 608,
        "content": "## Context & Intelligence\n\nReceives data from MCP, extracts repository and branch context, fetches commits, and prepares structured input for AI reasoning."
      },
      "typeVersion": 1
    },
    {
      "id": "55f95864-7bf0-48aa-b47f-3bf315649e9f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 1232,
        "height": 608,
        "content": "## PR Generation & Execution\n\nTransforms commit context into a PR title and description, validates output, and creates the pull request via GitHub API."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "a5e92d5b-f4e0-43de-acce-d71e4d849e24",
  "connections": {
    "create_github_pr": {
      "ai_tool": [
        [
          {
            "node": "MCP Server Trigger for Github",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GitHub Issues": {
      "ai_tool": [
        [
          {
            "node": "MCP Server Trigger for Github",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "LLM PR Writer Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate PR Title & Description",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Build Error Response": {
      "main": [
        [
          {
            "node": "Aggregate Commit Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Subworkflow Entry Point": {
      "main": [
        [
          {
            "node": "Extract Repo & Branch Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Repo & Branch Context",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Extract Repo & Branch Context",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Commit Messages": {
      "main": [
        [
          {
            "node": "Generate PR Title & Description",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Repo or Branch Validation": {
      "main": [
        [
          {
            "node": "Check for Repository error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Repository error": {
      "main": [
        [
          {
            "node": "Prepare PR Payload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Repo & Branch Context": {
      "main": [
        [
          {
            "node": "Repo or Branch Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate PR Title & Description": {
      "main": [
        [
          {
            "node": "Create Pull Request",
            "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

Categories Developer Automation, AI Agents, GitHub Automation, DevOps Productivity

Source: https://n8n.io/workflows/13118/ — 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

The AI-Powered Shopify SEO Content Automation is an enterprise-grade workflow that transforms product content creation for e-commerce stores. This sophisticated multi-agent system integrates GPT-4o, C

Perplexity Tool, Memory Buffer Window, Agent +15
AI & RAG

How it Works

Memory Buffer Window, Agent, Output Parser Structured +9
AI & RAG

The best content automation template in the market is now even better—with “deep research” on time-sensitive topics\! Unlike most n8n content automation templates that are mainly for “demo purposes,”

OpenAI, HTTP Request, XML +11
AI & RAG

Typeform IA - YT. Uses typeformTrigger, agent, lmChatOpenAi, toolWorkflow. Event-driven trigger; 75 nodes.

Typeform Trigger, Agent, OpenAI Chat +7
AI & RAG

🤖🧑‍💻 AI Agent for Top n8n Creators Leaderboard Reporting. Uses httpRequest, lmChatOpenAi, executeWorkflowTrigger, toolWorkflow. Event-driven trigger; 49 nodes.

HTTP Request, OpenAI Chat, Execute Workflow Trigger +8