{
  "name": "AI Gmail Triage",
  "nodes": [
    {
      "parameters": {
        "content": "## AI Email Triage: Auto-Label Gmail + Urgent Alerts\n\nOpen your inbox to find everything pre-sorted: customer emails labeled, invoices filed, newsletters out of the way - and anything urgent already waiting in Slack.\n\n**Setup time:** 15 minutes  ·  **Level:** Intermediate\n\n**You'll need accounts/credentials for:** Gmail, OpenAI, Slack\n\n**Replace these before running:**\n- `REPLACE_WITH_URGENT_LABEL_ID`\n- `REPLACE_WITH_CUSTOMER_LABEL_ID`\n- `REPLACE_WITH_INVOICE_LABEL_ID`\n- `REPLACE_WITH_NEWSLETTER_LABEL_ID`\n- `REPLACE_WITH_CHANNEL`\n\n**Setup steps:**\n1. Connect Gmail (OAuth) in the trigger and the label node.\n2. In Gmail, create labels: AI/Urgent, AI/Customer, AI/Invoice, AI/Newsletter. Get their IDs from the n8n Gmail node's label dropdown and paste them into the Code node mapping.\n3. Add your OpenAI API key, and adjust the four category definitions in the prompt to your business.\n4. Connect Slack for urgent alerts. Activate and send yourself test emails.\n\nFree templates and updates: navkhan103.github.io",
        "height": 684,
        "width": 400,
        "color": 4
      },
      "id": "sticky-setup",
      "name": "Setup — read me first",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        -120
      ]
    },
    {
      "parameters": {
        "content": "### How it runs\n\nStarts from **New Email**.\n\n1. A Gmail Trigger polls for new inbox messages every few minutes.\n2. An OpenAI node classifies the email into one of four categories, replying with a single word.\n3. A Code node maps the category to your Gmail label ID.\n4. A Gmail node applies the label.\n5. An IF node routes Urgent emails to a Slack alert with sender and subject.",
        "height": 374,
        "width": 400,
        "color": 7
      },
      "id": "sticky-how",
      "name": "How it runs",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        604
      ]
    },
    {
      "parameters": {
        "content": "### If something breaks\n\nThe read and AI nodes here **retry 3× automatically** (5s apart), which absorbs rate limits and brief timeouts.\n\nNodes that **send or write deliberately do not retry** — a send that reached the far end but lost its response would otherwise fire twice, so you'd get duplicate messages or duplicate rows.\n\nTo be told when one of those fails, build a workflow starting with an **Error Trigger** node that posts to Slack or email, then set it under **three-dot menu > Settings > Error Workflow**. Do it once and point every workflow at it.",
        "height": 400,
        "width": 400,
        "color": 3
      },
      "id": "sticky-fail",
      "name": "If something breaks",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        1018
      ]
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyX",
              "value": 5,
              "unit": "minutes"
            }
          ]
        },
        "simple": true,
        "filters": {}
      },
      "id": "f9a0b1c2-0001-4000-8000-000000000001",
      "name": "New Email",
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.6-luna"
        },
        "messages": {
          "values": [
            {
              "content": "=Classify this email into exactly one category. Reply with ONLY the category word.\n\nCategories:\nURGENT - a customer or partner needs action today: outage, complaint, deadline, payment failure\nCUSTOMER - normal customer or prospect communication\nINVOICE - bills, receipts, payment confirmations\nNEWSLETTER - marketing, digests, notifications, anything automated\n\nFrom: {{ $json.from }}\nSubject: {{ $json.subject }}\n\n{{ ($json.textPlain || $json.snippet || '').slice(0, 2000) }}",
              "role": "user"
            }
          ]
        }
      },
      "id": "f9a0b1c2-0002-4000-8000-000000000002",
      "name": "Classify",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        220,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "jsCode": "const category = $input.first().json.message.content.trim().toUpperCase().replace(/[^A-Z]/g, '');\nconst labelMap = {\n  URGENT: 'REPLACE_WITH_URGENT_LABEL_ID',\n  CUSTOMER: 'REPLACE_WITH_CUSTOMER_LABEL_ID',\n  INVOICE: 'REPLACE_WITH_INVOICE_LABEL_ID',\n  NEWSLETTER: 'REPLACE_WITH_NEWSLETTER_LABEL_ID'\n};\nconst src = $('New Email').first().json;\nreturn [{ json: {\n  messageId: src.id,\n  category,\n  labelId: labelMap[category] || labelMap.CUSTOMER,\n  from: src.from, subject: src.subject\n} }];"
      },
      "id": "f9a0b1c2-0003-4000-8000-000000000003",
      "name": "Map to Label",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "operation": "addLabels",
        "messageId": "={{ $json.messageId }}",
        "labelIds": "={{ [$json.labelId] }}"
      },
      "id": "f9a0b1c2-0004-4000-8000-000000000004",
      "name": "Apply Gmail Label",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $('Map to Label').item.json.category }}",
              "rightValue": "URGENT",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "f9a0b1c2-0005-4000-8000-000000000005",
      "name": "Urgent?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_CHANNEL"
        },
        "text": "=:rotating_light: *Urgent email* from {{ $('Map to Label').item.json.from }}\n*{{ $('Map to Label').item.json.subject }}*",
        "otherOptions": {}
      },
      "id": "f9a0b1c2-0006-4000-8000-000000000006",
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1100,
        -80
      ]
    }
  ],
  "connections": {
    "New Email": {
      "main": [
        [
          {
            "node": "Classify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify": {
      "main": [
        [
          {
            "node": "Map to Label",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map to Label": {
      "main": [
        [
          {
            "node": "Apply Gmail Label",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Gmail Label": {
      "main": [
        [
          {
            "node": "Urgent?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Urgent?": {
      "main": [
        [
          {
            "node": "Slack Alert",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}