This workflow corresponds to n8n.io template #13874 — we link there as the canonical source.
This workflow follows the Google Sheets → 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "82242ae4-4639-484b-8e48-c5f9e7fc56f1",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
528
],
"parameters": {
"width": 500,
"height": 644,
"content": "### GitHub issue triage with Gemini AI\nAutomatically classifies new issues, adds labels, and routes alerts by priority.\n\n### How it works\n1. A **webhook** fires when a new issue is opened on your repo\n2. **Gemini AI** reads the title and body, then classifies the type (Bug, Feature, Question, etc.) and priority (Critical \u2192 Low)\n3. Labels are added to the issue via the GitHub API, and an AI summary is posted as a comment\n4. A **Switch** routes Critical/High to #urgent-issues and Medium/Low to #issue-tracker on Slack\n5. Every triaged issue is logged to **Google Sheets** for tracking\n\n### Setup steps\n1. Set the webhook URL in your GitHub repo \u2192 Settings \u2192 Webhooks \u2192 select \"Issues\" events\n2. Add your Gemini API key as HTTP Header Auth credentials (`x-goog-api-key`)\n3. Create a GitHub personal access token with `issues:write` scope and add as HTTP Header Auth\n4. Connect Slack and Google Sheets OAuth2 credentials\n5. Create Slack channels: `#urgent-issues` and `#issue-tracker`\n\n### Customization\n- Edit the categories in the Gemini prompt to fit your project\n- Change the priority threshold in the Switch node\n- Add more Slack channels for different teams"
},
"typeVersion": 1
},
{
"id": "44b185f3-6481-4b5e-8e4a-434cfb73dd58",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
112,
528
],
"parameters": {
"color": 7,
"width": 480,
"height": 480,
"content": "## Capture new issues\nWebhook receives the GitHub event payload. The Set node picks out the fields we actually need for classification."
},
"typeVersion": 1
},
{
"id": "9cedae3f-f26f-4ff6-9665-edc6f42ef497",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
624,
528
],
"parameters": {
"color": 7,
"width": 480,
"height": 480,
"content": "## AI classification\nGemini reads the issue and returns type, priority, and a one-line summary as JSON. The next node parses the response."
},
"typeVersion": 1
},
{
"id": "23b154fe-a09a-4999-be47-91e8f261a8a4",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1136,
528
],
"parameters": {
"color": 7,
"width": 480,
"height": 480,
"content": "## Update the issue\nPOSTs labels and an AI analysis comment back to GitHub via the REST API."
},
"typeVersion": 1
},
{
"id": "3f1e5df5-a57e-42b6-9ecb-1c8ee53959e2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1632,
528
],
"parameters": {
"color": 7,
"width": 784,
"height": 480,
"content": "## Route alerts & log\nCritical/High \u2192 #urgent-issues, Medium/Low \u2192 #issue-tracker. Everything gets appended to Sheets for analytics."
},
"typeVersion": 1
},
{
"id": "14c49277-33b1-49d0-8d7d-51fab0f4da98",
"name": "GitHub Issue Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
176,
704
],
"parameters": {
"path": "github-issue-webhook",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "cd56005c-66c3-4926-b4bb-f7337c548e16",
"name": "Extract Issue Data",
"type": "n8n-nodes-base.set",
"position": [
416,
704
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f1",
"name": "issue_title",
"type": "string",
"value": "={{ $json.body.issue.title }}"
},
{
"id": "f2",
"name": "issue_body",
"type": "string",
"value": "={{ $json.body.issue.body }}"
},
{
"id": "f3",
"name": "issue_number",
"type": "number",
"value": "={{ $json.body.issue.number }}"
},
{
"id": "f4",
"name": "issue_url",
"type": "string",
"value": "={{ $json.body.issue.html_url }}"
},
{
"id": "f5",
"name": "author",
"type": "string",
"value": "={{ $json.body.issue.user.login }}"
},
{
"id": "f6",
"name": "repo_name",
"type": "string",
"value": "={{ $json.body.repository.name }}"
},
{
"id": "f7",
"name": "repo_owner",
"type": "string",
"value": "={{ $json.body.repository.owner.login }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "12c0d793-057d-4a50-a206-f96ca89eb865",
"name": "Classify with Gemini AI",
"type": "n8n-nodes-base.httpRequest",
"position": [
704,
704
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
"method": "POST",
"options": {},
"jsonBody": "={\n \"contents\": [{\n \"parts\": [{\n \"text\": \"Classify this GitHub issue. Return ONLY valid JSON, no markdown.\\n\\nTitle: {{ $json.issue_title }}\\n\\nBody: {{ $json.issue_body }}\\n\\nReturn JSON with:\\n- type: one of Bug, Feature Request, Documentation, Enhancement, Question\\n- priority: one of Critical, High, Medium, Low\\n- summary: one sentence analysis\"\n }]\n }],\n \"generationConfig\": {\n \"responseMimeType\": \"application/json\",\n \"responseSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": { \"type\": \"string\" },\n \"priority\": { \"type\": \"string\" },\n \"summary\": { \"type\": \"string\" }\n },\n \"required\": [\"type\", \"priority\", \"summary\"]\n }\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googlePalmApi"
},
"typeVersion": 4.2
},
{
"id": "b7877b46-2d2b-4e76-ad27-294df27845dd",
"name": "Parse AI Response",
"type": "n8n-nodes-base.set",
"position": [
944,
704
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "p1",
"name": "ai_type",
"type": "string",
"value": "={{ JSON.parse($json.candidates[0].content.parts[0].text).type }}"
},
{
"id": "p2",
"name": "ai_priority",
"type": "string",
"value": "={{ JSON.parse($json.candidates[0].content.parts[0].text).priority }}"
},
{
"id": "p3",
"name": "ai_summary",
"type": "string",
"value": "={{ JSON.parse($json.candidates[0].content.parts[0].text).summary }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "7eb88821-1f42-499a-a92a-4e525e509824",
"name": "Add Labels to Issue",
"type": "n8n-nodes-base.httpRequest",
"position": [
1216,
704
],
"parameters": {
"url": "=https://api.github.com/repos/{{ $json.repo_owner }}/{{ $json.repo_name }}/issues/{{ $json.issue_number }}/labels",
"method": "POST",
"options": {},
"jsonBody": "={ \"labels\": [\"{{ $json.ai_type.toLowerCase() }}\", \"priority:{{ $json.ai_priority.toLowerCase() }}\"] }",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "ba10d179-0e6f-44d2-b4fa-d9d10e998296",
"name": "Post AI Comment",
"type": "n8n-nodes-base.httpRequest",
"position": [
1456,
704
],
"parameters": {
"url": "=https://api.github.com/repos/{{ $json.repo_owner }}/{{ $json.repo_name }}/issues/{{ $json.issue_number }}/comments",
"method": "POST",
"options": {},
"jsonBody": "={ \"body\": \"\ud83e\udd16 **AI Triage**\\n\\n**Type:** {{ $json.ai_type }}\\n**Priority:** {{ $json.ai_priority }}\\n**Summary:** {{ $json.ai_summary }}\\n\\n_Auto-generated. Adjust labels if needed._\" }",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "5f35a814-66d9-4e83-927a-ba173d620177",
"name": "Is Critical or High?",
"type": "n8n-nodes-base.if",
"position": [
1744,
704
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "priority-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.ai_priority }}",
"rightValue": "Critical"
}
]
}
},
"typeVersion": 2
},
{
"id": "8fc8e6c9-ed0b-4cae-a11b-ba9336fcfa85",
"name": "Alert Urgent Issues",
"type": "n8n-nodes-base.slack",
"position": [
1984,
608
],
"parameters": {
"text": "=\ud83d\udea8 *URGENT: {{ $json.ai_type }}* in `{{ $json.repo_name }}`\n*Priority:* {{ $json.ai_priority }}\n*Issue:* {{ $json.issue_title }}\n*Author:* {{ $json.author }}\n*Analysis:* {{ $json.ai_summary }}\n<{{ $json.issue_url }}|View Issue>",
"otherOptions": {}
},
"typeVersion": 2.2
},
{
"id": "42f4e44f-5c7d-4411-a765-588bd563ceea",
"name": "Log to Issue Tracker",
"type": "n8n-nodes-base.slack",
"position": [
1984,
816
],
"parameters": {
"text": "=\ud83d\udcdd *New Issue Triaged:* {{ $json.ai_type }} ({{ $json.ai_priority }})\n*Issue:* {{ $json.issue_title }} by {{ $json.author }}\n*Summary:* {{ $json.ai_summary }}\n<{{ $json.issue_url }}|View Issue>",
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "60306f05-211d-46f8-b5b3-1a81b9f43eef",
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2192,
704
],
"parameters": {
"columns": {
"value": {
"URL": "={{ $json.issue_url }}",
"Date": "={{ $now.toISO() }}",
"Type": "={{ $json.ai_type }}",
"Issue": "={{ $json.issue_title }}",
"Author": "={{ $json.author }}",
"Summary": "={{ $json.ai_summary }}",
"Priority": "={{ $json.ai_priority }}",
"Repository": "={{ $json.repo_name }}"
},
"schema": [
{
"id": "Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Repository",
"type": "string",
"display": true,
"required": false,
"displayName": "Repository",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Issue",
"type": "string",
"display": true,
"required": false,
"displayName": "Issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Author",
"type": "string",
"display": true,
"required": false,
"displayName": "Author",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Type",
"type": "string",
"display": true,
"required": false,
"displayName": "Type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Priority",
"type": "string",
"display": true,
"required": false,
"displayName": "Priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Summary",
"type": "string",
"display": true,
"required": false,
"displayName": "Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "URL",
"type": "string",
"display": true,
"required": false,
"displayName": "URL",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": ""
}
},
"typeVersion": 4.5
}
],
"connections": {
"Post AI Comment": {
"main": [
[
{
"node": "Is Critical or High?",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Response": {
"main": [
[
{
"node": "Add Labels to Issue",
"type": "main",
"index": 0
}
]
]
},
"Extract Issue Data": {
"main": [
[
{
"node": "Classify with Gemini AI",
"type": "main",
"index": 0
}
]
]
},
"Add Labels to Issue": {
"main": [
[
{
"node": "Post AI Comment",
"type": "main",
"index": 0
}
]
]
},
"GitHub Issue Webhook": {
"main": [
[
{
"node": "Extract Issue Data",
"type": "main",
"index": 0
}
]
]
},
"Is Critical or High?": {
"main": [
[
{
"node": "Alert Urgent Issues",
"type": "main",
"index": 0
},
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Log to Issue Tracker",
"type": "main",
"index": 0
},
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Classify with Gemini AI": {
"main": [
[
{
"node": "Parse AI Response",
"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.
slackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Development teams and project maintainers who receive high volumes of GitHub issues and want to automate classification and team notifications. Perfect for open source projects, product teams, and DevOps engineers managing multiple repositories.
Source: https://n8n.io/workflows/13874/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates the initial screening process for new job applications, freeing up your recruitment team to focus on qualified candidates. It receives applications from a webhook, uses OpenAI
This system meticulously guides each lead through a fully automated journey, from initial contact to a personalized follow-up and CRM integration.
Automate your landscaping business’s lead follow-up and booking with this AI-powered GoHighLevel workflow. Designed by Hyrum Hurst, AI Automation Engineer at QuarterSmart, this template takes every ne
A smart, fully automated coding pipeline built inside n8n that leverages Cursor AI to write, refactor, review, and optimize code projects — triggered by a webhook, schedule, or manual prompt. Every ou
Consulting firms in strategy, management, or IT who want to automate client onboarding and internal task assignment.