AutomationFlowsAI & RAG › Triage and Route Support Emails with Gemini, Gmail, Sheets and Slack

Triage and Route Support Emails with Gemini, Gmail, Sheets and Slack

ByOka Hironobu @okp29 on n8n.io

This workflow monitors unread Gmail support emails, uses Google Gemini to classify and summarize each message and draft a reply, logs the ticket details to Google Sheets, creates a Gmail draft response, and sends a Slack alert when the ticket is marked high priority. Triggers…

Event trigger★★★★☆ complexity19 nodesGmail TriggerHTTP RequestGoogle SheetsGmailSlack
AI & RAG Trigger: Event Nodes: 19 Complexity: ★★★★☆ Added:

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

This workflow follows the Gmail → Gmail Trigger 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": "daPM9kpX3vinFIZP",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Triage and route support emails with Gemini, Gmail, Sheets and Slack",
  "tags": [],
  "nodes": [
    {
      "id": "efc608e4-078a-4dbf-8f3a-0761588e63b7",
      "name": "Fetch New Support Emails",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        48,
        48
      ],
      "parameters": {
        "simple": false,
        "filters": {
          "readStatus": "unread"
        },
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.4
    },
    {
      "id": "bd0b6d92-c910-4a52-9a80-77c3c49a37fd",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        272,
        48
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b",
              "name": "brandName",
              "type": "string",
              "value": "Acme Inc."
            },
            {
              "id": "g",
              "name": "supportGuidelines",
              "type": "string",
              "value": "Be friendly and concise. Never promise refunds."
            },
            {
              "id": "u",
              "name": "urgentKeywords",
              "type": "string",
              "value": "outage, refund, legal, cancel, urgent"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "fbacc3e2-8ad3-4f3b-9591-74940edcba48",
      "name": "Build Analysis Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        48
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const cfg = $('Set Configuration').item.json;\nconst email = $json;\nconst body = email.text || email.snippet || email.html || '';\nconst prompt = [\n  'You are a senior support agent for ' + cfg.brandName + '.',\n  cfg.supportGuidelines || '',\n  'Mark priority high if it mentions: ' + (cfg.urgentKeywords || 'outage, refund, legal'),\n  '',\n  'Respond ONLY with minified JSON:',\n  '{\"category\":\"billing\"|\"technical\"|\"account\"|\"general\",\"priority\":\"high\"|\"medium\"|\"low\",\"sentiment\":\"positive\"|\"neutral\"|\"negative\",\"reasoning\":string,\"summary\":string,\"suggested_reply\":string}',\n  '',\n  'Example -> {\"category\":\"technical\",\"priority\":\"high\",\"sentiment\":\"negative\",\"reasoning\":\"Outage reported\",\"summary\":\"Customer cannot access dashboard\",\"suggested_reply\":\"Hi, thanks for flagging this...\"}',\n  '',\n  'From: ' + (email.from||''),\n  'Subject: ' + (email.subject||''),\n  'Body:',\n  body\n].join('\\n');\nreturn { prompt, from: email.from, subject: email.subject, threadId: email.threadId, messageId: email.id };"
      },
      "typeVersion": 2
    },
    {
      "id": "6123f132-4e4b-47df-a7ef-b81ba77f7e22",
      "name": "Analyze Email with Gemini",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        848,
        48
      ],
      "parameters": {
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ { \"contents\": [ { \"parts\": [ { \"text\": $json.prompt } ] } ], \"generationConfig\": { \"temperature\": 0.1, \"responseMimeType\": \"application/json\" } } }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googlePalmApi"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "8c7bf65c-a35e-4aa3-8954-486ee9457b7d",
      "name": "Parse AI Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1136,
        32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const meta = $('Build Analysis Prompt').item.json;\nlet text = '';\ntry { text = $json.candidates[0].content.parts[0].text; } catch (e) { text = ''; }\nlet d = {};\ntry { d = JSON.parse(text); } catch (e) { d = { category:'general', priority:'medium', sentiment:'neutral', reasoning:'Parse failed', summary:(text||'').slice(0,200), suggested_reply:'' }; }\nreturn { from: meta.from, subject: meta.subject, threadId: meta.threadId, messageId: meta.messageId, category: String(d.category||'general').toLowerCase(), priority: String(d.priority||'medium').toLowerCase(), sentiment: String(d.sentiment||'neutral').toLowerCase(), reasoning: d.reasoning||'', summary: d.summary||'', suggested_reply: d.suggested_reply||'' };"
      },
      "typeVersion": 2
    },
    {
      "id": "9648bf39-88cb-4295-9424-9ddc31cf2fd4",
      "name": "Log Ticket to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1424,
        32
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Tickets"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "740207f7-f46d-46b2-a91f-2c3ff9ad45c0",
      "name": "Mark Email as Read",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1648,
        32
      ],
      "parameters": {
        "messageId": "={{ $(\"Parse AI Result\").item.json.messageId }}",
        "operation": "markAsRead"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "24f8a3dc-746b-45c0-ae61-8bf4fca64f26",
      "name": "Route by Priority",
      "type": "n8n-nodes-base.switch",
      "position": [
        2000,
        0
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse AI Result\").item.json.priority }}",
                    "rightValue": "high"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse AI Result\").item.json.priority }}",
                    "rightValue": "medium"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse AI Result\").item.json.priority }}",
                    "rightValue": "low"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Other"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "f1fc3b89-3298-47df-8b4e-c3e64b84d06a",
      "name": "Draft Priority Reply",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2240,
        -16
      ],
      "parameters": {
        "message": "={{ $(\"Parse AI Result\").item.json.suggested_reply }}",
        "options": {
          "sendTo": "={{ $(\"Parse AI Result\").item.json.from }}",
          "threadId": "={{ $(\"Parse AI Result\").item.json.threadId }}"
        },
        "subject": "={{ \"Re: \" + $(\"Parse AI Result\").item.json.subject }}",
        "resource": "draft"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5a6cae0f-fb23-48aa-a25a-ccb142e04c68",
      "name": "Escalate to On-call",
      "type": "n8n-nodes-base.slack",
      "position": [
        2464,
        -16
      ],
      "parameters": {
        "text": "=*:rotating_light: HIGH priority ticket*\n*From:* {{ $(\"Parse AI Result\").item.json.from }}\n*Subject:* {{ $(\"Parse AI Result\").item.json.subject }}\n*Category:* {{ $(\"Parse AI Result\").item.json.category }}\n*Summary:* {{ $(\"Parse AI Result\").item.json.summary }}\nA draft reply is ready in Gmail.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#support-urgent"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "dbd1eb88-d6bc-4c74-896d-377fd67a280d",
      "name": "Draft Standard Reply",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2240,
        128
      ],
      "parameters": {
        "message": "={{ $(\"Parse AI Result\").item.json.suggested_reply }}",
        "options": {
          "sendTo": "={{ $(\"Parse AI Result\").item.json.from }}",
          "threadId": "={{ $(\"Parse AI Result\").item.json.threadId }}"
        },
        "subject": "={{ \"Re: \" + $(\"Parse AI Result\").item.json.subject }}",
        "resource": "draft"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fcec7b83-25c6-40a4-8f0f-a3d79b0e112f",
      "name": "Draft Acknowledgement",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2240,
        304
      ],
      "parameters": {
        "message": "={{ \"Hi,\\n\\nThanks for reaching out - we have received your message and will get back to you shortly.\\n\\n\" + $(\"Parse AI Result\").item.json.suggested_reply }}",
        "options": {
          "sendTo": "={{ $(\"Parse AI Result\").item.json.from }}",
          "threadId": "={{ $(\"Parse AI Result\").item.json.threadId }}"
        },
        "subject": "={{ \"Re: \" + $(\"Parse AI Result\").item.json.subject }}",
        "resource": "draft"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "55c41233-49ec-48ac-a7df-aad979641b0f",
      "name": "Flag for Manual Review",
      "type": "n8n-nodes-base.slack",
      "position": [
        2240,
        496
      ],
      "parameters": {
        "text": "=*:mag: Ticket needs manual review (unclassified priority)*\n*From:* {{ $(\"Parse AI Result\").item.json.from }}\n*Subject:* {{ $(\"Parse AI Result\").item.json.subject }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#support-inbox"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "eba6a6ad-d466-4a7c-abab-52b128f1837d",
      "name": "Report Analysis Failure",
      "type": "n8n-nodes-base.slack",
      "position": [
        1136,
        208
      ],
      "parameters": {
        "text": "=*:x: Gemini analysis failed for a support email*\n*Subject:* {{ $(\"Build Analysis Prompt\").item.json.subject }}\nPlease review it manually.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#support-alerts"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "b51a0edf-8324-4554-bb6b-135898341ae0",
      "name": "Overview Sticky",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -240
      ],
      "parameters": {
        "width": 420,
        "height": 744,
        "content": "## Triage & route support emails with Gemini, Gmail, Sheets and Slack\n\n### How it works\nEvery new support email is analysed by Google Gemini for category, priority, sentiment and a drafted reply. The ticket is logged to Google Sheets and marked as read (so it is never processed twice). A Switch then routes each email by priority: high-priority tickets get an urgent draft plus an on-call Slack escalation, medium tickets get a standard draft, low tickets get an acknowledgement draft, and anything unclassified is flagged for manual review. If the AI call fails, the email is reported to Slack instead of being lost.\n\n### Setup\n1. Connect Gmail, Google Gemini (PaLM) API, Google Sheets and Slack.\n2. In **Set Configuration**, set your brand, guidelines and urgent keywords.\n3. Point **Log Ticket to Sheet** at your spreadsheet and pick your Slack channels.\n\n### Customization tips\nAdd categories, change the escalation channel, or auto-send low-priority acknowledgements."
      },
      "typeVersion": 1
    },
    {
      "id": "dbb25bb2-7128-47c1-8c94-79691ff74343",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 920,
        "content": "## 1. Trigger & configure\nFetch new unread support emails and set brand context + urgent keywords."
      },
      "typeVersion": 1
    },
    {
      "id": "3b8fa467-9fea-4953-85eb-f443f31c34be",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 920,
        "content": "## 2. AI analysis + error handling\nGemini classifies, prioritises and drafts a reply. If the call fails, Slack is notified instead of dropping the email."
      },
      "typeVersion": 1
    },
    {
      "id": "b07e5096-daee-408d-9b6e-6199f15e965c",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 920,
        "content": "## 3. Log & de-duplicate\nAppend the ticket to Sheets and mark the email as read so it is never processed twice."
      },
      "typeVersion": 1
    },
    {
      "id": "9fb2f6b8-b6ed-4c30-b946-6c5b52b29854",
      "name": "S4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1904,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 920,
        "content": "## 4. Route by priority & act\nHigh -> urgent draft + on-call escalation. Medium -> standard draft. Low -> acknowledgement draft. Unclassified -> manual review."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "f88ef9e7-175a-43c8-ab0b-609f6611ddc7",
  "nodeGroups": [],
  "connections": {
    "Parse AI Result": {
      "main": [
        [
          {
            "node": "Log Ticket to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Priority": {
      "main": [
        [
          {
            "node": "Draft Priority Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Draft Standard Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Draft Acknowledgement",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Flag for Manual Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Build Analysis Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Email as Read": {
      "main": [
        [
          {
            "node": "Route by Priority",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Ticket to Sheet": {
      "main": [
        [
          {
            "node": "Mark Email as Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft Priority Reply": {
      "main": [
        [
          {
            "node": "Escalate to On-call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Analysis Prompt": {
      "main": [
        [
          {
            "node": "Analyze Email with Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch New Support Emails": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Email with Gemini": {
      "main": [
        [
          {
            "node": "Parse AI Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Analysis Failure",
            "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

This workflow monitors unread Gmail support emails, uses Google Gemini to classify and summarize each message and draft a reply, logs the ticket details to Google Sheets, creates a Gmail draft response, and sends a Slack alert when the ticket is marked high priority. Triggers…

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

Overview

Gmail Trigger, Google Drive, OpenAI +4
AI & RAG

Automate your entire invoice processing pipeline with AI-powered OCR, validation, and approval workflows 📄🤖. This n8n automation monitors incoming Gmail invoices, extracts structured data using OCR an

Gmail Trigger, Gmail, OpenAI +3
AI & RAG

Small teams, solo operators, and security-conscious individuals who receive email attachments from external senders. Useful for freelancers, agencies, HR teams, and anyone handling CVs, invoices, or d

Gmail Trigger, HTTP Request, OpenAI +4
AI & RAG

This workflow polls Gmail for emails with the subject “Trade Instruction”, uses OpenAI Chat Completions to extract trade fields from the email body, logs valid and failed extractions to separate tabs

Gmail Trigger, HTTP Request, Google Sheets +1
AI & RAG

13. Insurance Pre-Authorization. Uses gmailTrigger, gmail, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 12 nodes.

Gmail Trigger, Gmail, N8N Nodes Pdfvector +2