AutomationFlowsAI & RAG › AI Support Ticket Triage with OpenAI

AI Support Ticket Triage with OpenAI

Original n8n title: AI Support Ticket Triage

AI Support Ticket Triage. Uses agent, lmChatOpenAi, notion, slack. Webhook trigger; 13 nodes.

Webhook trigger★★★★☆ complexityAI-powered13 nodesAgentOpenAI ChatNotionSlackGmail
AI & RAG Trigger: Webhook Nodes: 13 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Gmail 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
{
  "name": "AI Support Ticket Triage",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "901ed2f2-7d68-4ff0-ab85-e3885f97607c",
  "nodes": [
    {
      "parameters": {
        "path": "support-ticket-v3",
        "httpMethod": "POST",
        "responseMode": "onReceived"
      },
      "id": "ticket_webhook",
      "name": "Ticket Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        220,
        320
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const subject = String(item.json.subject || 'No subject');\n  const message = String(item.json.message || item.json.description || 'No message');\n  return {\n    json: {\n      ...item.json,\n      subject,\n      message,\n      receivedAt: new Date().toISOString(),\n    },\n  };\n});"
      },
      "id": "normalize_ticket",
      "name": "Normalize Ticket",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        450,
        320
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const lowered = (String(item.json.subject || '') + ' ' + String(item.json.message || '')).toLowerCase();\n\n  let deterministicScore = 30;\n  if (lowered.includes('outage') || lowered.includes('down')) deterministicScore += 35;\n  if (lowered.includes('payment') || lowered.includes('billing')) deterministicScore += 20;\n  if (lowered.includes('security') || lowered.includes('breach')) deterministicScore += 25;\n\n  return {\n    json: {\n      ...item.json,\n      deterministicScore,\n      baselineQueue: deterministicScore >= 70 ? 'urgent-human' : 'ai-assisted',\n    },\n  };\n});"
      },
      "id": "deterministic_ticket_score",
      "name": "Deterministic Ticket Score",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        700,
        320
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{'You triage support tickets. Return strict JSON with keys aiScore (0-100), priority (urgent-human|human|ai-assisted), summary (string). Ticket payload: ' + JSON.stringify($json)}}",
        "options": {}
      },
      "id": "ai_ticket_triage_agent",
      "name": "AI Ticket Triage Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        940,
        220
      ]
    },
    {
      "parameters": {
        "model": {
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "id": "openai_chat_model",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        940,
        520
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const rawCandidate =\n    item.json.output ??\n    item.json.text ??\n    item.json.response ??\n    item.json.result ??\n    item.json;\n\n  let parsed = {};\n\n  if (typeof rawCandidate === 'string') {\n    try {\n      parsed = JSON.parse(rawCandidate);\n    } catch (error) {\n      parsed = { summary: rawCandidate };\n    }\n  } else if (rawCandidate && typeof rawCandidate === 'object') {\n    parsed = rawCandidate;\n  }\n\n  const pickNumber = (...keys) => {\n    for (const key of keys) {\n      const value = Number(parsed[key]);\n      if (Number.isFinite(value) && value > 0) return value;\n    }\n    return 0;\n  };\n\n  const pickString = (...keys) => {\n    for (const key of keys) {\n      const value = parsed[key];\n      if (typeof value === 'string' && value.trim()) return value.trim();\n    }\n    return '';\n  };\n\n  return {\n    json: {\n      aiScore: pickNumber('aiScore', 'score', 'riskScore', 'severityScore', 'readinessScore'),\n      aiPriority: pickString('priority', 'queue', 'recommendation', 'decision'),\n      aiSummary: pickString('summary', 'rationale', 'reason', 'triageSummary', 'recommendation') || 'ai_response_unavailable',\n      aiPayload: parsed,\n    },\n  };\n});"
      },
      "id": "parse_ai_output",
      "name": "Parse AI Output",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1160,
        220
      ]
    },
    {
      "parameters": {
        "mode": "combine"
      },
      "id": "merge_ai_with_rules",
      "name": "Merge AI with Rules",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1160,
        360
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const deterministicScore = Number(item.json.deterministicScore || 0);\n  const aiScore = Number(item.json.aiScore || 0);\n  const triageScore = aiScore > 0\n    ? Math.round((deterministicScore * 0.6) + (aiScore * 0.4))\n    : deterministicScore;\n\n  const queue = triageScore >= 70\n    ? 'urgent-human'\n    : (item.json.aiPriority || item.json.baselineQueue || 'ai-assisted');\n\n  return {\n    json: {\n      ...item.json,\n      triageScore,\n      queue,\n      summary: item.json.aiSummary || 'deterministic fallback used',\n    },\n  };\n});"
      },
      "id": "final_ticket_decision",
      "name": "Final Ticket Decision",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1380,
        360
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json.triageScore}}",
              "operation": "largerEqual",
              "value2": 70
            }
          ]
        }
      },
      "id": "human_escalation_check",
      "name": "Human Escalation?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1600,
        360
      ]
    },
    {
      "parameters": {
        "resource": "databasePage",
        "operation": "create",
        "databaseId": {
          "mode": "url",
          "value": "https://www.notion.so/00000000000000000000000000000000"
        },
        "title": "={{\"Ticket: \" + ($json.subject || \"No subject\") + \" | \" + ($json.queue || \"ai-assisted\")}}",
        "simple": true
      },
      "id": "notion_log_ticket",
      "name": "Notion Log Ticket",
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        1820,
        360
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "mode": "id",
          "value": "C01234567"
        },
        "messageType": "text",
        "text": "={{\"\ud83d\udea8 Urgent ticket: \" + ($json.subject || \"No subject\") + \" | score \" + ($json.triageScore || 0)}}"
      },
      "id": "slack_urgent_ticket",
      "name": "Slack Urgent Ticket",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.4,
      "position": [
        1820,
        180
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "mode": "id",
          "value": "C01234567"
        },
        "messageType": "text",
        "text": "={{\"Ticket triaged to \" + ($json.queue || \"ai-assisted\") + \" | \" + ($json.subject || \"No subject\")}}"
      },
      "id": "slack_standard_ticket",
      "name": "Slack Standard Ticket",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.4,
      "position": [
        1820,
        540
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "sendTo": "={{$json.email || \"customer@example.com\"}}",
        "subject": "Support Ticket Update",
        "message": "={{\"Queue: \" + ($json.queue || \"ai-assisted\") + \"\\nSummary: \" + ($json.summary || \"pending\")}}"
      },
      "id": "gmail_ticket_update",
      "name": "Gmail Ticket Update",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        2050,
        360
      ]
    }
  ],
  "connections": {
    "Ticket Webhook": {
      "main": [
        [
          {
            "node": "Normalize Ticket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Ticket": {
      "main": [
        [
          {
            "node": "Deterministic Ticket Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Deterministic Ticket Score": {
      "main": [
        [
          {
            "node": "AI Ticket Triage Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge AI with Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Ticket Triage Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Ticket Triage Agent": {
      "main": [
        [
          {
            "node": "Parse AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Output": {
      "main": [
        [
          {
            "node": "Merge AI with Rules",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge AI with Rules": {
      "main": [
        [
          {
            "node": "Final Ticket Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Final Ticket Decision": {
      "main": [
        [
          {
            "node": "Human Escalation?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Human Escalation?": {
      "main": [
        [
          {
            "node": "Slack Urgent Ticket",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notion Log Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack Standard Ticket",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notion Log Ticket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notion Log Ticket": {
      "main": [
        [
          {
            "node": "Gmail Ticket Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

AI Support Ticket Triage. Uses agent, lmChatOpenAi, notion, slack. Webhook trigger; 13 nodes.

Source: https://github.com/JefferyAddaeSecB/n8n-ai-support-ticket-triage/blob/1b4ab19261e01c40f56f7fa43f7ac06ffd6d9472/n8n/workflow.json — 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

This workflow automates the end-to-end employee onboarding process by provisioning new hires across multiple internal systems and delivering a personalized welcome experience.

HTTP Request, Slack, Notion +4
AI & RAG

🧾 An intelligent automation system that turns Google Meet recordings into structured meeting notes — integrating Fireflies.ai, OpenAI GPT-4.1-mini, Notion, Slack, Google Drive, and Gmail via n8n.

Google Drive, OpenAI Chat, Output Parser Structured +8
AI & RAG

A high-fidelity employee onboarding engine: Intake → Role-Based Enrichment → AI Personalization → IT Provisioning.

Notion, Jira, Slack +5
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
AI & RAG

Enhance your support, onboarding, and internal knowledge workflows with an intelligent RAG-powered chatbot that responds using live data stored in Google Sheets. 🤖📚 Built for teams that rely on struct

Chat Trigger, Output Parser Structured, Memory Buffer Window +6