AutomationFlowsAI & RAG › Route Support Messages with Gpt-4.1-mini, Slack, Email and Human Review

Route Support Messages with Gpt-4.1-mini, Slack, Email and Human Review

ByOneclick AI Squad @oneclick-ai on n8n.io

This workflow classifies incoming support messages from email or Slack, drafts AI-generated replies for routine queries, and automatically pauses to notify a human agent for sensitive topics such as complaints, emotional distress, billing disputes, legal concerns, or escalation…

Webhook trigger★★★★☆ complexityAI-powered21 nodesAgentHTTP RequestOpenAI Chat
AI & RAG Trigger: Webhook Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → 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 →

Download .json
{
  "id": "amip0qiSwBAX6Zvs",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Ethical AI Customer Support Router with Human-in-the-Loop",
  "tags": [],
  "nodes": [
    {
      "id": "979f659c-0305-4b00-875f-ae248a7f1b54",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -160
      ],
      "parameters": {
        "width": 980,
        "height": 984,
        "content": "## Ethical AI Customer Support Router with Human-in-the-Loop\n\nThis workflow classifies incoming support messages from email or Slack, drafts AI-generated replies for routine queries, and automatically pauses to notify a human agent for sensitive topics such as complaints, emotional distress, billing disputes, legal concerns, or escalation requests.\n\n### Who's it for\n\u2022 Customer support teams handling 50+ messages per day\n\u2022 SaaS companies needing compliant, empathetic AI responses\n\u2022 E-commerce brands managing returns, refunds, and complaints\n\u2022 Any team that wants AI speed with human oversight on sensitive issues\n\n### How it works / What it does\n1. Captures incoming messages from Email (webhook) or Slack\n2. Normalizes message context (sender, channel, body, urgency signals)\n3. AI classifies the message into a category and sensitivity tier\n4. Routine queries \u2192 AI drafts reply \u2192 sent automatically\n5. Sensitive queries \u2192 AI drafts reply \u2192 paused for human review\n6. Human approves, edits, or rejects the draft via webhook resume\n7. Final reply sent to customer via email or Slack\n8. All interactions logged to Google Sheet with category, tier, and resolution\n\n### How to set up\n1. Import this workflow\n2. Configure credentials (Gmail/IMAP, Slack, OpenAI/Anthropic, Google Sheets)\n3. Update your support tone, escalation keywords, and team Slack channel\n4. Activate workflow\n\n### Requirements\n\u2022 Gmail or IMAP webhook / Slack Events API\n\u2022 OpenAI / Anthropic / Grok API\n\u2022 Slack Bot Token (for human notifications)\n\u2022 Google Sheets for audit logging\n\u2022 HTTP endpoint for human approval webhook\n\n### How to customize the workflow\n\u2022 Edit sensitivity tiers in the Python classification node\n\u2022 Change escalation keywords list\n\u2022 Update Slack notification channel and message template\n\u2022 Modify AI tone and persona in the AI draft node\n\u2022 Adjust wait timeout for human review window"
      },
      "typeVersion": 1
    },
    {
      "id": "38bdbc05-cabc-4822-bc36-dc31212f60de",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        -48
      ],
      "parameters": {
        "color": 4,
        "width": 780,
        "height": 520,
        "content": "## 1. Trigger & Message Intake"
      },
      "typeVersion": 1
    },
    {
      "id": "6a9ad606-cf79-46af-a3f3-b9eef12818a1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2048,
        -32
      ],
      "parameters": {
        "color": 3,
        "width": 1268,
        "height": 532,
        "content": "## 2. AI Classification & Draft Generation"
      },
      "typeVersion": 1
    },
    {
      "id": "a1c950e0-c7db-4dfb-94cb-4ebd7902807f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        560
      ],
      "parameters": {
        "color": 3,
        "width": 552,
        "height": 300,
        "content": "## 3. Human-in-the-Loop Review"
      },
      "typeVersion": 1
    },
    {
      "id": "b2d96e33-4a7f-41b8-a732-268668f563d7",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1760,
        528
      ],
      "parameters": {
        "color": 2,
        "width": 860,
        "height": 356,
        "content": "## 4. Send Reply & Audit Log"
      },
      "typeVersion": 1
    },
    {
      "id": "83e8538d-12e1-4e5e-a726-81671d8737c4",
      "name": "Webhook - New Support Message",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1312,
        128
      ],
      "parameters": {
        "path": "support-message-inbound",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 1.1
    },
    {
      "id": "37986229-181b-4a93-82b3-de31e69f0723",
      "name": "Poll Support Inbox",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1296,
        304
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/10 * * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b638936b-78eb-4f68-9fee-9a611baca3b0",
      "name": "Normalize Message Context",
      "type": "n8n-nodes-base.set",
      "position": [
        1584,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "name": "sender",
              "type": "string",
              "value": "={{ $json.from || $json.body?.from || $json.event?.user || '' }}"
            },
            {
              "name": "channel",
              "type": "string",
              "value": "={{ $json.channel || $json.body?.channel || 'email' }}"
            },
            {
              "name": "subject",
              "type": "string",
              "value": "={{ $json.subject || $json.body?.subject || $json.event?.text?.substring(0, 60) || 'Support Request' }}"
            },
            {
              "name": "body",
              "type": "string",
              "value": "={{ $json.text || $json.body?.text || $json.event?.text || $json.body || '' }}"
            },
            {
              "name": "messageId",
              "type": "string",
              "value": "={{ $json.messageId || $json.event?.ts || Date.now().toString() }}"
            },
            {
              "name": "threadId",
              "type": "string",
              "value": "={{ $json.threadId || $json.event?.thread_ts || '' }}"
            },
            {
              "name": "customerName",
              "type": "string",
              "value": "={{ $json.name || $json.body?.name || 'Customer' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "66f2889d-4460-4d7a-a800-192fdf29f93b",
      "name": "Python - Classify Sensitivity Tier",
      "type": "n8n-nodes-base.code",
      "position": [
        1792,
        144
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "language": "python"
      },
      "typeVersion": 2
    },
    {
      "id": "805271d3-c352-431d-a367-53ec9cc83a4c",
      "name": "AI - Classify and Draft Reply",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2112,
        112
      ],
      "parameters": {
        "text": "=You are an expert, empathetic customer support AI for a SaaS company. Your job is to:\n1. Classify the support message into one category.\n2. Assign a sensitivity tier.\n3. Draft a professional, warm, and helpful reply.\n\nMessage Details:\nFrom: {{ $json.customerName }} <{{ $json.sender }}>\nChannel: {{ $json.channel }}\nSubject: {{ $json.subject }}\nMessage Body:\n{{ $json.body }}\n\nPre-classified Sensitivity Tier (from keyword scan): {{ $json.sensitivityTier }}\nDetected Signals: {{ $json.detectedSignals }}\n\nClassification Categories:\n- billing_issue\n- technical_bug\n- feature_request\n- general_inquiry\n- complaint\n- emotional_distress\n- legal_or_compliance\n- escalation_request\n- account_access\n- refund_request\n\nSensitivity Tiers:\n- ROUTINE: Safe to auto-send\n- SENSITIVE: Requires human review before sending\n\nRespond ONLY in this exact JSON format:\n{\n  \"category\": \"...\",\n  \"sensitivityTier\": \"ROUTINE\" or \"SENSITIVE\",\n  \"sentimentScore\": -1.0 to 1.0,\n  \"urgencyLevel\": \"low\" or \"medium\" or \"high\",\n  \"draftReply\": \"...\",\n  \"internalNote\": \"...\"\n}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "8461b7fe-e4fa-4d36-bc91-4e66a8f60319",
      "name": "JS - Parse AI Classification",
      "type": "n8n-nodes-base.code",
      "position": [
        2368,
        336
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $input.item.json;\nlet aiOutput = {};\ntry {\n  const raw = item.output || item.response || item.text || '{}';\n  const clean = raw.replace(/```json|```/g, '').trim();\n  aiOutput = JSON.parse(clean);\n} catch (e) {\n  aiOutput = {\n    category: 'general_inquiry',\n    sensitivityTier: 'SENSITIVE',\n    sentimentScore: 0,\n    urgencyLevel: 'medium',\n    draftReply: 'Thank you for reaching out. A member of our team will be in touch shortly.',\n    internalNote: 'AI parsing failed \u2014 manual review required.'\n  };\n}\nreturn {\n  json: {\n    ...item,\n    category: aiOutput.category || 'general_inquiry',\n    sensitivityTier: aiOutput.sensitivityTier || 'SENSITIVE',\n    sentimentScore: aiOutput.sentimentScore || 0,\n    urgencyLevel: aiOutput.urgencyLevel || 'medium',\n    draftReply: aiOutput.draftReply || '',\n    internalNote: aiOutput.internalNote || '',\n    processedAt: new Date().toISOString(),\n    processedDate: new Date().toISOString().split('T')[0]\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e72e3356-4280-48fb-9a72-87ca9514521e",
      "name": "Route - Sensitive or Routine?",
      "type": "n8n-nodes-base.filter",
      "position": [
        2592,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.sensitivityTier }}",
              "rightValue": "SENSITIVE"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0401c70d-f1c9-4695-bea7-ac1c9d6c51ba",
      "name": "Notify Human via Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2816,
        336
      ],
      "parameters": {
        "url": "https://slack.com/api/chat.postMessage",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"channel\": \"#support-escalations\",\n  \"text\": \":rotating_light: *Human Review Required* :rotating_light:\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \":rotating_light: *Human Review Required*\\n*From:* {{ $json.customerName }} ({{ $json.sender }})\\n*Category:* `{{ $json.category }}`  |  *Urgency:* `{{ $json.urgencyLevel }}`  |  *Sentiment:* `{{ $json.sentimentScore }}`\\n*Subject:* {{ $json.subject }}\"\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*Original Message:*\\n{{ ($json.body || '').substring(0, 300) }}\"\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*AI Draft Reply:*\\n{{ ($json.draftReply || '').substring(0, 400) }}\"\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*Internal Note:* {{ $json.internalNote }}\"\n      }\n    },\n    {\n      \"type\": \"actions\",\n      \"elements\": [\n        {\n          \"type\": \"button\",\n          \"text\": { \"type\": \"plain_text\", \"text\": \":white_check_mark: Approve & Send\" },\n          \"style\": \"primary\",\n          \"url\": \"https://your-n8n-instance.com/webhook/support-human-approve?messageId={{ $json.messageId }}&action=approve\"\n        },\n        {\n          \"type\": \"button\",\n          \"text\": { \"type\": \"plain_text\", \"text\": \":x: Reject Draft\" },\n          \"style\": \"danger\",\n          \"url\": \"https://your-n8n-instance.com/webhook/support-human-approve?messageId={{ $json.messageId }}&action=reject\"\n        }\n      ]\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2a293d14-3039-477f-82aa-afb4d1ed5078",
      "name": "Webhook - Human Approval Response",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1344,
        656
      ],
      "parameters": {
        "path": "support-human-approve",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 1.1
    },
    {
      "id": "e65ce847-f9fa-4b1b-815f-96f8dec5eade",
      "name": "Filter - Approved by Human?",
      "type": "n8n-nodes-base.filter",
      "position": [
        1568,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.query?.action || $json.action }}",
              "rightValue": "approve"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "dc549605-d971-4ff1-b42f-7d43a9670d52",
      "name": "Wait - Human Review Window",
      "type": "n8n-nodes-base.wait",
      "position": [
        3040,
        336
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "3b5fc712-148d-450c-9491-10b48aa0dcb8",
      "name": "Send Reply to Customer",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1792,
        656
      ],
      "parameters": {
        "url": "https://api.sendgrid.com/v3/mail/send",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"personalizations\": [{\"to\": [{\"email\": \"{{ $json.sender }}\", \"name\": \"{{ $json.customerName }}\"}]}],\n  \"from\": {\"email\": \"support@yourcompany.com\", \"name\": \"Your Company Support\"},\n  \"subject\": \"Re: {{ $json.subject }}\",\n  \"content\": [{\"type\": \"text/plain\", \"value\": \"{{ $json.draftReply }}\"}]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ad03c847-6ca9-475b-9908-5c83e63fb4d7",
      "name": "Send Slack Reply (if Slack channel)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2016,
        656
      ],
      "parameters": {
        "url": "https://slack.com/api/chat.postMessage",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"channel\": \"{{ $json.threadId || '#support-escalations' }}\",\n  \"text\": \"{{ $json.draftReply }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "b37fab44-0047-414b-ba94-a70cf6d34058",
      "name": "Log to Support Audit Sheet",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2448,
        656
      ],
      "parameters": {
        "url": "https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/Support_Log!A1:append?valueInputOption=USER_ENTERED",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"values\": [[\"{{ $json.processedDate }}\", \"{{ $json.messageId }}\", \"{{ $json.sender }}\", \"{{ $json.customerName }}\", \"{{ $json.channel }}\", \"{{ $json.subject }}\", \"{{ $json.category }}\", \"{{ $json.sensitivityTier }}\", \"{{ $json.urgencyLevel }}\", \"{{ $json.sentimentScore }}\", \"{{ $json.internalNote }}\", \"Replied\", \"{{ $json.processedAt }}\"]]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c3df3076-0919-45ba-bf0c-8750ced7aeab",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2128,
        352
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "ccedf4ee-90f8-47e6-b0cb-12ccb9260ce3",
      "name": "Wait For Result",
      "type": "n8n-nodes-base.wait",
      "position": [
        2224,
        656
      ],
      "parameters": {},
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "355b759a-c25f-4bd6-bc30-05ed88fb7ecf",
  "connections": {
    "Wait For Result": {
      "main": [
        [
          {
            "node": "Log to Support Audit Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI - Classify and Draft Reply",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Poll Support Inbox": {
      "main": [
        [
          {
            "node": "Normalize Message Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Human via Slack": {
      "main": [
        [
          {
            "node": "Wait - Human Review Window",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Reply to Customer": {
      "main": [
        [
          {
            "node": "Send Slack Reply (if Slack channel)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Message Context": {
      "main": [
        [
          {
            "node": "Python - Classify Sensitivity Tier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter - Approved by Human?": {
      "main": [
        [
          {
            "node": "Send Reply to Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JS - Parse AI Classification": {
      "main": [
        [
          {
            "node": "Route - Sensitive or Routine?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI - Classify and Draft Reply": {
      "main": [
        [
          {
            "node": "JS - Parse AI Classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route - Sensitive or Routine?": {
      "main": [
        [
          {
            "node": "Notify Human via Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - New Support Message": {
      "main": [
        [
          {
            "node": "Normalize Message Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Human Approval Response": {
      "main": [
        [
          {
            "node": "Filter - Approved by Human?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Python - Classify Sensitivity Tier": {
      "main": [
        [
          {
            "node": "AI - Classify and Draft Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Slack Reply (if Slack channel)": {
      "main": [
        [
          {
            "node": "Wait For Result",
            "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 classifies incoming support messages from email or Slack, drafts AI-generated replies for routine queries, and automatically pauses to notify a human agent for sensitive topics such as complaints, emotional distress, billing disputes, legal concerns, or escalation…

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

⏺ 🚀 How it works

Agent, Anthropic Chat, Output Parser Structured +6
AI & RAG

L&D_AgentsAI_ATIVO. Uses httpRequest, agent, googleCalendarTool, toolSerpApi. Webhook trigger; 93 nodes.

HTTP Request, Agent, Google Calendar Tool +9
AI & RAG

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14
AI & RAG

Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.

OpenAI Chat, Memory Postgres Chat, OpenAI +7
AI & RAG

This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La

Google Sheets, HTTP Request, Slack +10