This workflow corresponds to n8n.io template #16434 — we link there as the canonical source.
This workflow follows the Gmail → Google Sheets 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 →
{
"id": "rdlr1EaEcjC8i1YY",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "N-0046 Exception Queue Smart Prioritization Engine",
"tags": [],
"nodes": [
{
"id": "7a608f87-b09c-4224-8464-c17ca80492c7",
"name": "Receive Exception Request",
"type": "n8n-nodes-base.webhook",
"position": [
-6224,
5600
],
"parameters": {
"path": "exception-trigger",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "22c1b9cb-ad0e-4f67-bdc0-0d9bd95e9768",
"name": "Read Exceptions from Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-5840,
5600
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc/edit?usp=drivesdk",
"cachedResultName": "Priority_Ranking"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "4114eb2b-5733-4031-ba55-98d83249fde0",
"name": "Format Data for AI",
"type": "n8n-nodes-base.code",
"position": [
-5360,
5600
],
"parameters": {
"jsCode": "// CODE 1 \u2014 Format rows into a clean text list for Gemini\nconst exceptions = $input.all().map(item => item.json);\n\nconst exceptionList = exceptions.map((ex, i) =>\n `[${i + 1}] ID: ${ex.ExceptionID || 'N/A'} | Title: ${ex.Title || 'Untitled'} | Severity: ${ex.Severity || 'Unknown'} | System: ${ex.System || 'N/A'} | Reported: ${ex.ReportedAt || 'N/A'}`\n).join('\\n');\n\nreturn [{\n json: {\n exceptionList,\n totalCount: exceptions.length\n }\n}];"
},
"typeVersion": 2
},
{
"id": "68fda6a3-1456-45e2-a9b0-1d533dbb0075",
"name": "AI \u2014 Rank & Prioritize",
"type": "n8n-nodes-base.httpRequest",
"position": [
-5184,
5600
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?",
"method": "POST",
"options": {},
"jsonBody": "={\n \"contents\": [{\n \"parts\": [{\n \"text\": {{ JSON.stringify(\"Analyze and rank these exceptions. Respond ONLY with a valid JSON object \u2014 no markdown, no backticks, no extra text.\\nRequired structure:\\n{\\n \\\"prioritized_exceptions\\\": [\\n {\\n \\\"exception_id\\\": \\\"EXC-001\\\",\\n \\\"title\\\": \\\"...\\\",\\n \\\"severity\\\": \\\"...\\\",\\n \\\"rank\\\": 1,\\n \\\"priority_score\\\": 95,\\n \\\"priority_label\\\": \\\"P0\\\",\\n \\\"estimated_impact\\\": \\\"...\\\",\\n \\\"reasoning\\\": \\\"...\\\",\\n \\\"recommended_action\\\": \\\"...\\\"\\n }\\n ],\\n \\\"summary\\\": \\\"...\\\",\\n \\\"critical_count\\\": 1,\\n \\\"high_count\\\": 1,\\n \\\"medium_count\\\": 1,\\n \\\"low_count\\\": 0\\n}\\n\\nExceptions:\\n\" + $json.exceptionList) }}\n }]\n }]\n}",
"sendBody": true,
"sendQuery": true,
"sendHeaders": true,
"specifyBody": "json",
"queryParameters": {
"parameters": [
{
"name": "key",
"value": "=<redacted-credential>"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "15f3b7cb-524e-4cf1-bf13-0c86b16128b4",
"name": "Save Summary to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-4784,
5600
],
"parameters": {
"columns": {
"value": {
"summary": "={{ $json.summary }}",
"low_count": "={{ $json.low_count }}",
"high_count": "={{ $json.high_count }}",
"totalCount": "={{ $json.totalCount }}",
"analyzed_at": "={{ $json.analyzed_at }}",
"medium_count": "={{ $json.medium_count }}",
"critical_count": "={{ $json.critical_count }}"
},
"schema": [
{
"id": "summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "critical_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "critical_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "high_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "high_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "medium_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "medium_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "low_count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "low_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "totalCount",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "totalCount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "analyzed_at",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "analyzed_at",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"summary"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1284297464,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc/edit#gid=1284297464",
"cachedResultName": "Sheet2"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc/edit?usp=drivesdk",
"cachedResultName": "Priority_Ranking"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "9ecf7b82-2699-4f8c-9f09-19974f0252dd",
"name": "Check Critical Alerts",
"type": "n8n-nodes-base.if",
"position": [
-4384,
5600
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-is-critical",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $('AI Results').first().json.critical_count }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2
},
{
"id": "281fe072-d909-4adf-bccd-bc0c47ecd60d",
"name": "Send Critical Email",
"type": "n8n-nodes-base.gmail",
"position": [
-4144,
5440
],
"parameters": {
"message": "={{ $('AI Results').first().json.emailBody }}",
"options": {},
"subject": "={{ $('AI Results').first().json.emailSubject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "963c2b82-5f6d-4b44-8e96-5dbc6b551c88",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-6240,
5040
],
"parameters": {
"width": 512,
"height": 368,
"content": "## Exception Queue Smart Prioritization Engine\n## How it works:\nThis workflow reads exception data from Google Sheets, sends it to AI (Gemini) for intelligent ranking, then generates Slack alerts, email notifications for critical issues, and saves summarized insights back to Sheets.\n\n## Setup steps:\n1. Connect Google Sheets, Slack, and Gmail credentials\n2. Update Sheet ID and Slack channel in Set node\n3. Add your Gemini API key\n4. Trigger via webhook to run workflow"
},
"typeVersion": 1
},
{
"id": "9055cb9d-bfa8-4093-a598-83be17d61ce1",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-6256,
5456
],
"parameters": {
"color": 7,
"width": 724,
"height": 416,
"content": "## Data Collection & Validation\nReads exceptions from Sheet1 and checks if data exists before processing."
},
"typeVersion": 1
},
{
"id": "5c555493-409a-427c-b366-d885f4857f3d",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-5392,
5472
],
"parameters": {
"color": 7,
"width": 528,
"height": 336,
"content": "## AI Processing\nFormats exception data and sends it to Gemini AI for ranking and prioritization."
},
"typeVersion": 1
},
{
"id": "ba1f66a9-978d-419a-9907-a370d82741fa",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4832,
5344
],
"parameters": {
"color": 7,
"width": 864,
"height": 512,
"content": "## Notifications & Storage\nSends Slack alerts, emails for critical issues, and saves results to Sheet2."
},
"typeVersion": 1
},
{
"id": "0a53df81-24b7-418a-a582-e8def02050ac",
"name": "Config Variables",
"type": "n8n-nodes-base.set",
"position": [
-6016,
5600
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1e221fc0-5259-42f6-a671-182ad0e555aa",
"name": "sheet1Name",
"type": "string",
"value": "Sheet1"
},
{
"id": "4d8509b5-4632-48d9-9f3a-aad73e166134",
"name": "sheet2Name",
"type": "string",
"value": "Sheet2"
},
{
"id": "a2b4a57f-ebf1-44ae-ae7c-c80bb569525e",
"name": "slackChannel",
"type": "string",
"value": "new-channel"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b269f347-7823-405c-9332-2dff72ba3992",
"name": "Exceptions Available?",
"type": "n8n-nodes-base.if",
"position": [
-5648,
5600
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-has-rows",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $input.all().length }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2
},
{
"id": "d8b66285-c478-4d50-a3ad-cc39d3d07628",
"name": "No Exceptions Found",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-5344,
5856
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={ \"success\": true, \"message\": \"No open exceptions found\" }"
},
"typeVersion": 1.1
},
{
"id": "70adccea-53cb-4f04-917f-10ae3ed59c3b",
"name": "AI Results",
"type": "n8n-nodes-base.code",
"position": [
-4992,
5600
],
"parameters": {
"jsCode": "// CODE 2 \u2014 Parse AI response + build Slack + email + sheet rows\n// OUTPUT: Always exactly ONE item.\n// Sheet2 node reads from sheetRows array embedded in that single item.\n\nconst response = $input.first().json;\nconst textContent = response.candidates?.[0]?.content?.parts?.[0]?.text || '';\nconst now = new Date();\nconst nowISO = now.toISOString();\nconst nowIN = now.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });\n\nconst totalCount = $('Format Data for AI').first().json.totalCount || 0;\n\n// Parse Gemini JSON\nlet parsed;\ntry {\n const cleaned = textContent\n .replace(/```json|```/g, '')\n .replace(/^[^{]*/, '')\n .replace(/[^}]*$/, '')\n .trim();\n parsed = JSON.parse(cleaned);\n} catch (e) {\n parsed = {};\n}\n\nconst exceptions = parsed.prioritized_exceptions || [];\nconst summary = parsed.summary || 'No summary provided';\nconst critical_count = parsed.critical_count || 0;\nconst high_count = parsed.high_count || 0;\nconst medium_count = parsed.medium_count || 0;\nconst low_count = parsed.low_count || 0;\n\nconst sorted = exceptions.sort((a, b) => (a.rank || 999) - (b.rank || 999));\n\n// Slack ranked list \u2014 full details per exception\nconst rankedList = sorted.slice(0, 10).map(ex =>\n `*${ex.rank}. [${ex.priority_label}] ${ex.exception_id}* \u2014 ${ex.title}\\n` +\n ` Severity: *${ex.severity}* | Score: ${ex.priority_score}\\n` +\n ` Impact: ${ex.estimated_impact}\\n` +\n ` Action: ${ex.recommended_action}`\n).join('\\n\\n') || 'No exceptions ranked.';\n\nconst slackBlocks = [\n { type: 'header', text: { type: 'plain_text', text: 'Exception Queue \u2014 AI Priority Report', emoji: true } },\n { type: 'section', text: { type: 'mrkdwn', text: `*Time:* ${nowIN}\\n*Total:* ${totalCount} | :red_circle: Critical: ${critical_count} | :large_orange_circle: High: ${high_count} | :large_yellow_circle: Medium: ${medium_count} | :white_circle: Low: ${low_count}` } },\n { type: 'divider' },\n { type: 'section', text: { type: 'mrkdwn', text: `*Ranked Exceptions (Top ${Math.min(sorted.length, 10)}):*\\n\\n${rankedList}` } },\n { type: 'divider' },\n { type: 'section', text: { type: 'mrkdwn', text: `*AI Summary:* ${summary}` } },\n { type: 'actions', elements: [{ type: 'button', text: { type: 'plain_text', text: 'View Full Sheet', emoji: true }, url: 'https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc', style: 'primary' }] }\n];\n\n// Critical email\nconst criticalList = sorted.filter(ex =>\n ex.priority_label?.toUpperCase() === 'P0' || ex.severity?.toLowerCase() === 'critical'\n);\nconst emailSubject = `[CRITICAL] ${criticalList.length} Exception(s) Need Immediate Action \u2014 ${nowIN}`;\nconst emailBody = `\n<h2>Critical Exceptions Report</h2>\n<p><strong>Time:</strong> ${nowIN}</p>\n<p><strong>Total analyzed:</strong> ${totalCount} | Critical: ${critical_count} | High: ${high_count} | Medium: ${medium_count} | Low: ${low_count}</p>\n<h3>Critical Items:</h3>\n<table border=\"1\" cellpadding=\"6\" cellspacing=\"0\" style=\"border-collapse:collapse;font-family:Arial,sans-serif;font-size:14px\">\n <tr style=\"background:#c0392b;color:#fff\"><th>ID</th><th>Title</th><th>Severity</th><th>Priority</th><th>Score</th><th>Recommended Action</th></tr>\n ${criticalList.map(ex => `<tr><td><strong>${ex.exception_id||'N/A'}</strong></td><td>${ex.title||'N/A'}</td><td>${ex.severity||'N/A'}</td><td>${ex.priority_label||'N/A'}</td><td>${ex.priority_score||'N/A'}</td><td>${ex.recommended_action||'N/A'}</td></tr>`).join('')}\n</table>\n<br/><p><strong>AI Summary:</strong> ${summary}</p>\n<p><a href=\"https://docs.google.com/spreadsheets/d/1prWm2iUrj63OWRHCJSSkCUqMH9l7A0KY6RLjFAGudmc\">View Full Report</a></p>`;\n\n// Sheet rows \u2014 stored as array inside the single output item\nconst sheetRows = (sorted.length > 0 ? sorted : [{\n exception_id: 'N/A', title: 'No exceptions returned', severity: 'Unknown',\n rank: 0, priority_score: 0, priority_label: 'N/A',\n estimated_impact: 'N/A', reasoning: summary, recommended_action: 'Check AI response'\n}]).map(ex => ({\n ExceptionID: ex.exception_id || 'N/A',\n Title: ex.title || 'No title',\n Severity: ex.severity || 'Unknown',\n Rank: ex.rank || 0,\n PriorityScore: ex.priority_score || 0,\n PriorityLabel: ex.priority_label || 'N/A',\n EstimatedImpact: ex.estimated_impact || 'N/A',\n Reasoning: ex.reasoning || 'No reasoning',\n RecommendedAction: ex.recommended_action || 'No action',\n AnalyzedAt: nowISO\n}));\n\n// Always return exactly ONE item \u2014 no more duplicate Slack/Gmail/Webhook runs\nreturn [{\n json: {\n summary,\n critical_count,\n high_count,\n medium_count,\n low_count,\n totalCount,\n analyzed_at: nowISO,\n slackText: `Exception Report \u2014 ${nowIN}`,\n slackBlocks: JSON.stringify(slackBlocks),\n emailSubject,\n emailBody,\n sheetRows: JSON.stringify(sheetRows)\n }\n}];"
},
"typeVersion": 2
},
{
"id": "2b5ebad0-60eb-4a35-bdb3-0de16c8246b8",
"name": "Slack Report",
"type": "n8n-nodes-base.slack",
"position": [
-4592,
5600
],
"parameters": {
"text": "={{ $('AI Results').item.json.slackText }}",
"select": "channel",
"blocksUi": "={{ $('AI Results').item.json.slackBlocks }}",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0AP86XGA78",
"cachedResultName": "new-channel"
},
"messageType": "block",
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "8e14fe90-1047-4ed4-bd88-18be32a52ce2",
"name": "Success",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-3952,
5616
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"message\": \"Done\",\n \"total_processed\": {{ $('Format Data for AI').first().json.totalCount }},\n \"critical_count\": {{ $('AI Results').first().json.critical_count }},\n \"analyzed_at\": \"{{ $('AI Results').first().json.analyzed_at }}\"\n}"
},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "7b1aef92-bf1e-4904-8ef3-e049eeefb0d5",
"connections": {
"AI Results": {
"main": [
[
{
"node": "Save Summary to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Slack Report": {
"main": [
[
{
"node": "Check Critical Alerts",
"type": "main",
"index": 0
}
]
]
},
"Config Variables": {
"main": [
[
{
"node": "Read Exceptions from Sheet",
"type": "main",
"index": 0
}
]
]
},
"Format Data for AI": {
"main": [
[
{
"node": "AI \u2014 Rank & Prioritize",
"type": "main",
"index": 0
}
]
]
},
"Send Critical Email": {
"main": [
[
{
"node": "Success",
"type": "main",
"index": 0
}
]
]
},
"Check Critical Alerts": {
"main": [
[
{
"node": "Send Critical Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Success",
"type": "main",
"index": 0
}
]
]
},
"Exceptions Available?": {
"main": [
[
{
"node": "Format Data for AI",
"type": "main",
"index": 0
}
],
[
{
"node": "No Exceptions Found",
"type": "main",
"index": 0
}
]
]
},
"Save Summary to Sheet": {
"main": [
[
{
"node": "Slack Report",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Notify Team3": {
"main": [
[
{
"node": "IF \u2014 Any Critical Exceptions?3",
"type": "main",
"index": 0
}
]
]
},
"AI \u2014 Rank & Prioritize": {
"main": [
[
{
"node": "AI Results",
"type": "main",
"index": 0
}
]
]
},
"Receive Exception Request": {
"main": [
[
{
"node": "Config Variables",
"type": "main",
"index": 0
}
]
]
},
"Read Exceptions from Sheet": {
"main": [
[
{
"node": "Exceptions Available?",
"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.
gmailOAuth2googleSheetsOAuth2ApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow receives a webhook trigger, reads exception records from Google Sheets, uses Google Gemini (Generative Language API) to rank and summarize them, posts a prioritized report to Slack, writes summary metrics back to Google Sheets, and emails a critical alert via Gmail…
Source: https://n8n.io/workflows/16434/ — 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 receives new Calendly meeting bookings, checks Google Sheets to prevent duplicate briefings, pulls contact and deal context from HubSpot, enriches company data with Clearbit, generates t
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.
Analyze website SEO issues and generate optimization actions with AI
Email Drafter. Uses gmail, slack, openAi, httpRequest. Webhook trigger; 15 nodes.