{
  "id": "Y5lQyQOD9nHhauxA",
  "name": "AI Gmail Inbox Triage Agent: Auto-Prioritise, Draft Replies and Alert with Claude",
  "tags": [],
  "nodes": [
    {
      "id": "9f2045ea-3ebe-4f2d-ad21-f970174e9df0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1824,
        -464
      ],
      "parameters": {
        "color": 0,
        "width": 480,
        "height": 1220,
        "content": "## AI Gmail Inbox Triage Agent using Claude and Slack\n\nYour inbox is the most expensive place you spend time. This workflow runs every 15 minutes, reads every new unread email, and handles it automatically -- so you only ever see what genuinely needs your eyes.\n\n### How it works\n\n1. Every 15 minutes, the workflow checks Gmail for new unread emails.\n2. Each email is passed to Claude Sonnet, which reads the subject and body and classifies it into one of five categories: Urgent, Needs Reply, FYI Only, Automated, or Spam.\n3. Urgent emails trigger an immediate Slack alert to you with the sender, subject, and a one-line summary.\n4. Needs Reply emails get a Claude-drafted reply saved as a Gmail draft -- ready for you to review and send in one click.\n5. FYI Only emails get labelled and marked as read automatically.\n6. Automated emails (newsletters, notifications, receipts) get labelled and archived so they never clutter your inbox.\n7. Spam emails get labelled and moved to trash.\n8. Every email processed is logged to Google Sheets with its category, sender, subject, and Claude reasoning so you have a full audit trail.\n\n### Setup steps\n\n- [ ] **Gmail trigger** -- Connect your Gmail account in the Check for New Emails node. The workflow polls every 15 minutes by default.\n- [ ] **Claude AI** -- Click the Claude Sonnet sub-node under Classify Email Intent, add a new Anthropic credential, and paste your API key from console.anthropic.com.\n- [ ] **Gmail labels** -- Create four labels in Gmail: AI-Urgent, AI-Needs-Reply, AI-FYI, AI-Automated. You will enter these label IDs in the label nodes after connecting your Gmail account.\n- [ ] **Draft replies** -- Connect your Gmail account in the Save Draft Reply node. Claude will write the draft, you approve before sending.\n- [ ] **Slack alerts** -- Connect your Slack account in Notify Urgent Email and set your preferred channel or DM. Right-click and Disable this node if you do not use Slack.\n- [ ] **Google Sheets** -- Create a sheet with columns: Timestamp, Sender, Subject, Category, Summary, Draft Saved. Connect your Google account in Log to Sheets.\n- [ ] **Customise the prompt** -- Open Classify Email Intent and update the prompt to list your name, role, and any senders or topics that should always be treated as urgent.\n- [ ] Activate the workflow. It will run automatically every 15 minutes.\n\n### Customization\n\nChange the polling interval in the Schedule Trigger from 15 minutes to any frequency you prefer. Add a VIP sender list to the Claude prompt so emails from specific people always route as Urgent. Extend the Needs Reply branch to auto-send low-stakes replies without saving a draft."
      },
      "typeVersion": 1
    },
    {
      "id": "c39b04fb-48e8-4364-897f-c4bdddd73373",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1296,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 472,
        "content": "## Fetch and prepare new emails\n\nPolls Gmail every 15 minutes for unread messages. Extracts the sender, subject, and first 2000 characters of the body -- enough for Claude to classify without burning tokens on long email chains."
      },
      "typeVersion": 1
    },
    {
      "id": "8a105f8a-2123-4851-82ac-beb5006c2d42",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 624,
        "content": "## Classify with Claude AI\n\nClaude Sonnet reads each email and returns a structured JSON with the category, a one-line summary, a suggested reply if needed, and its reasoning.\n\nEdit the system prompt in this node to add your name, your role, and any VIP senders or keywords that should always route as Urgent."
      },
      "typeVersion": 1
    },
    {
      "id": "6ed4b9d7-f56a-47c6-8216-f462d3bd852a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 520,
        "content": "## Route by category\n\nA Switch node sends each email to the correct branch: Urgent, Needs Reply, FYI Only, Automated, or Spam."
      },
      "typeVersion": 1
    },
    {
      "id": "53737f25-5017-4c75-aaae-da8a604d1fde",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -416
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 1128,
        "content": "## Take action on each category\n\nUrgent: Slack alert sent immediately. Needs Reply: Claude draft saved to Gmail drafts. FYI Only: labelled and marked read. Automated: labelled and archived. Spam: labelled and trashed. Every email is then logged to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "101dae6e-dadd-41c9-befb-345f72b3013f",
      "name": "Check for New Emails",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -1264,
        96
      ],
      "parameters": {
        "filters": {
          "readStatus": "unread"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyX",
              "unit": "minutes",
              "value": 15
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "06cb74c4-51ae-46c6-9ebd-00ba3d1a26fc",
      "name": "Extract Email Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -1024,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f32a5642-c744-47ba-bc27-f55ad5964edf",
              "name": "email_id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "0a58418f-888a-4675-88bf-255080570416",
              "name": "sender",
              "type": "string",
              "value": "={{ $json.from }}"
            },
            {
              "id": "e3c0ba7a-5adc-48aa-9c76-2e22603157ca",
              "name": "subject",
              "type": "string",
              "value": "={{ $json.subject }}"
            },
            {
              "id": "2cb877f5-01fe-4313-8b19-1379743bff40",
              "name": "body_snippet",
              "type": "string",
              "value": "={{ ($json.text || $json.snippet || '').slice(0, 2000) }}"
            },
            {
              "id": "3aa63f98-6335-41ac-a821-e3b9cda8089a",
              "name": "received_at",
              "type": "string",
              "value": "={{ $json.date }}"
            },
            {
              "id": "426f3983-bb0a-4aef-b4e8-b01e5aef75c9",
              "name": "thread_id",
              "type": "string",
              "value": "={{ $json.threadId }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "32bc6300-43d8-4b3b-929e-222388bfb2de",
      "name": "Classify Email Intent",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        -816,
        96
      ],
      "parameters": {
        "text": "=You are an expert email triage assistant for a busy business owner.\n\nRead the email below and classify it. Return ONLY valid JSON -- no extra text, no markdown, no explanation.\n\nEMAIL:\nFrom: {{ $json.sender }}\nSubject: {{ $json.subject }}\nBody: {{ $json.body_snippet }}\n\nClassify into exactly ONE of these categories:\n- URGENT: Needs the owner's attention today. Client issues, deal decisions, legal matters, anything time-sensitive.\n- NEEDS_REPLY: Requires a response but is not urgent. Questions, requests, follow-ups.\n- FYI_ONLY: Informational. No action needed. Updates, confirmations, read receipts.\n- AUTOMATED: System-generated. Newsletters, notifications, receipts, order confirmations, marketing emails.\n- SPAM: Unsolicited, irrelevant, or junk.\n\nReturn this exact JSON structure:\n{\n  \"category\": \"URGENT\",\n  \"summary\": \"One sentence describing what this email is about\",\n  \"suggested_reply\": \"A short professional reply if category is NEEDS_REPLY, otherwise leave empty string\",\n  \"reasoning\": \"One sentence explaining why you chose this category\"\n}",
        "promptType": "define"
      },
      "typeVersion": 1.4
    },
    {
      "id": "71f9b4df-05ca-4101-91b9-b47134a98dca",
      "name": "Claude Sonnet",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        -768,
        304
      ],
      "parameters": {
        "model": "claude-sonnet-4-5",
        "options": {
          "temperature": 0
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8e0da78b-739e-401d-8998-8a88be9492eb",
      "name": "Parse Classification",
      "type": "n8n-nodes-base.code",
      "position": [
        -528,
        96
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.text || '';\nconst emailData = $('Extract Email Data').first().json;\n\nlet parsed = {\n  category: 'FYI_ONLY',\n  summary: 'Could not parse classification',\n  suggested_reply: '',\n  reasoning: 'Parse error'\n};\n\ntry {\n  const match = text.match(/\\{[\\s\\S]*\\}/);\n  if (match) parsed = JSON.parse(match[0]);\n} catch(e) {}\n\nconst validCategories = ['URGENT','NEEDS_REPLY','FYI_ONLY','AUTOMATED','SPAM'];\nif (!validCategories.includes(parsed.category)) parsed.category = 'FYI_ONLY';\n\nreturn [{\n  json: {\n    email_id:        emailData.email_id,\n    thread_id:       emailData.thread_id,\n    sender:          emailData.sender,\n    subject:         emailData.subject,\n    body_snippet:    emailData.body_snippet,\n    received_at:     emailData.received_at,\n    category:        parsed.category,\n    summary:         parsed.summary,\n    suggested_reply: parsed.suggested_reply || '',\n    reasoning:       parsed.reasoning,\n    timestamp:       new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "6d9488e9-b9d0-49ca-a9aa-fd8a25c5ac76",
      "name": "Route by Category",
      "type": "n8n-nodes-base.switch",
      "position": [
        -288,
        96
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Urgent",
              "conditions": {
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.category }}",
                    "rightValue": "URGENT"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Needs Reply",
              "conditions": {
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.category }}",
                    "rightValue": "NEEDS_REPLY"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "FYI Only",
              "conditions": {
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.category }}",
                    "rightValue": "FYI_ONLY"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Automated",
              "conditions": {
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.category }}",
                    "rightValue": "AUTOMATED"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Spam",
              "conditions": {
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.category }}",
                    "rightValue": "SPAM"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "90116119-839b-4f54-9f61-e93e4e76b880",
      "name": "Notify Urgent Email",
      "type": "n8n-nodes-base.slack",
      "position": [
        112,
        -224
      ],
      "parameters": {
        "text": "URGENT EMAIL\n\nFrom: {{ $json.sender }}\nSubject: {{ $json.subject }}\nSummary: {{ $json.summary }}\nReceived: {{ $json.received_at }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#urgent-emails"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "a9c05db7-19ca-4399-bc57-7437b153ab8b",
      "name": "Label as Urgent",
      "type": "n8n-nodes-base.gmail",
      "position": [
        352,
        -224
      ],
      "parameters": {
        "labelIds": [
          "YOUR_AI_URGENT_LABEL_ID"
        ],
        "messageId": "={{ $json.email_id }}",
        "operation": "addLabels"
      },
      "typeVersion": 2.1
    },
    {
      "id": "c5141756-86c2-44bb-b200-177469ccfff1",
      "name": "Save Draft Reply",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        -16
      ],
      "parameters": {
        "operation": "createDraft"
      },
      "typeVersion": 2.1
    },
    {
      "id": "c540ac89-2ddc-40e0-b49c-d17e558e01a8",
      "name": "Label as Needs Reply",
      "type": "n8n-nodes-base.gmail",
      "position": [
        352,
        -16
      ],
      "parameters": {
        "labelIds": [
          "YOUR_AI_NEEDS_REPLY_LABEL_ID"
        ],
        "messageId": "={{ $json.email_id }}",
        "operation": "addLabels"
      },
      "typeVersion": 2.1
    },
    {
      "id": "8010e53c-a073-44ba-96e9-d85da00753bf",
      "name": "Label as FYI and Mark Read",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        176
      ],
      "parameters": {
        "messageId": "={{ $json.email_id }}",
        "operation": "markAsRead"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2fc1b416-95ed-4c62-aef0-f6afd2f68290",
      "name": "Label and Archive Automated",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        336
      ],
      "parameters": {
        "labelIds": [
          "YOUR_AI_AUTOMATED_LABEL_ID"
        ],
        "messageId": "={{ $json.email_id }}",
        "operation": "addLabels"
      },
      "typeVersion": 2.1
    },
    {
      "id": "57d56890-56eb-4a05-8053-34f46aef6cc4",
      "name": "Move Spam to Trash",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        528
      ],
      "parameters": {
        "messageId": "={{ $json.email_id }}",
        "operation": "delete"
      },
      "typeVersion": 2.1
    },
    {
      "id": "6462df1c-0d9b-413f-84bb-91da0ccef37b",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        592,
        160
      ],
      "parameters": {
        "columns": {
          "value": {
            "Sender": "={{ $json.sender }}",
            "Subject": "={{ $json.subject }}",
            "Summary": "={{ $json.summary }}",
            "Category": "={{ $json.category }}",
            "Reasoning": "={{ $json.reasoning }}",
            "Timestamp": "={{ $json.timestamp }}",
            "Draft Saved": "={{ $json.category === 'NEEDS_REPLY' ? 'Yes' : 'No' }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Email Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "2092cfba-e346-4e83-88d7-4c6ef8c8e7bb",
  "connections": {
    "Claude Sonnet": {
      "ai_languageModel": [
        [
          {
            "node": "Classify Email Intent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Label as Urgent": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Draft Reply": {
      "main": [
        [
          {
            "node": "Label as Needs Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Category": {
      "main": [
        [
          {
            "node": "Notify Urgent Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Save Draft Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Label as FYI and Mark Read",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Label and Archive Automated",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Move Spam to Trash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Email Data": {
      "main": [
        [
          {
            "node": "Classify Email Intent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move Spam to Trash": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Urgent Email": {
      "main": [
        [
          {
            "node": "Label as Urgent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for New Emails": {
      "main": [
        [
          {
            "node": "Extract Email Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Label as Needs Reply": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Classification": {
      "main": [
        [
          {
            "node": "Route by Category",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Email Intent": {
      "main": [
        [
          {
            "node": "Parse Classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Label as FYI and Mark Read": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Label and Archive Automated": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}