AutomationFlowsEmail & Gmail › AI Email Triage Agent for Gmail

AI Email Triage Agent for Gmail

Original n8n title: Ntf 03: Email Triage Agent

NTF 03: Email Triage Agent. Uses gmailTrigger, lmChatAnthropic, chainLlm, gmail. Event-driven trigger; 9 nodes.

Event trigger★★★★☆ complexityAI-powered9 nodesGmail TriggerAnthropic ChatChain LlmGmailSlack
Email & Gmail Trigger: Event Nodes: 9 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Chainllm → 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": "NTF 03: Email Triage Agent",
  "tags": [
    {
      "name": "NTF-Playbook"
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "nodes": [
    {
      "id": "sticky-readme",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -520
      ],
      "parameters": {
        "content": "## NTF 03: Email Triage Agent\n\n**Trigger:** Gmail polling every 5 minutes (unread, inbox)\n\n**Flow:**\n1. Poll Gmail for unread emails\n2. Extract sender, subject, body\n3. Claude classifies category and drafts reply\n4. Create Gmail draft (ready to review)\n5. If priority is high, also send a Slack ping\n\n**Setup:**\n- Connect Gmail OAuth credential (read + draft + modify scopes only)\n- Set your Slack channel id for urgent alerts\n- Edit the Claude prompt categories to match your inbox types\n- Note: this template does not auto-mark emails as read or apply a label. Add an `addLabel` step downstream if you want once-only processing.",
        "height": 380,
        "width": 540,
        "color": 6
      }
    },
    {
      "id": "gmail-trigger",
      "name": "Gmail Poll Unread",
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyX",
              "value": 5,
              "unit": "minutes"
            }
          ]
        },
        "filters": {
          "readStatus": "unread",
          "includeSpamTrash": false
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "extract-email",
      "name": "Extract Email Fields",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "email_id",
              "name": "email_id",
              "value": "={{ $json.id }}",
              "type": "string"
            },
            {
              "id": "from",
              "name": "from",
              "value": "={{ $json.from }}",
              "type": "string"
            },
            {
              "id": "subject",
              "name": "subject",
              "value": "={{ $json.subject }}",
              "type": "string"
            },
            {
              "id": "body",
              "name": "body",
              "value": "={{ $json.text || $json.snippet || '' }}",
              "type": "string"
            },
            {
              "id": "date",
              "name": "date",
              "value": "={{ $json.date }}",
              "type": "string"
            }
          ]
        }
      }
    },
    {
      "id": "claude-llm",
      "name": "Claude Triage Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        440,
        0
      ],
      "parameters": {
        "model": "claude-haiku-4-5-20251001",
        "options": {
          "maxTokens": 800
        }
      },
      "credentials": {
        "anthropicApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "triage-chain",
      "name": "Triage + Draft Reply",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.4,
      "position": [
        440,
        0
      ],
      "parameters": {
        "promptType": "define",
        "text": "=You are an email triage assistant. Analyze this email and return a JSON object with:\n- category: one of \"support\", \"billing\", \"sales_inquiry\", \"partnership\", \"spam\", \"personal\", \"urgent\", \"newsletter\", \"other\"\n- priority: \"high\" | \"medium\" | \"low\"\n- one_line_summary: max 15 words describing what the email is about\n- draft_reply: a short, professional reply draft (2-4 sentences). Write in first person as the business owner. Leave [PLACEHOLDER] where personalization is needed.\n- label: the Gmail label to apply, same as category\n\nEmail:\nFrom: {{ $('Extract Email Fields').item.json.from }}\nSubject: {{ $('Extract Email Fields').item.json.subject }}\nBody: {{ $('Extract Email Fields').item.json.body }}\n\nReturn only valid JSON, no markdown fencing."
      }
    },
    {
      "id": "parse-triage",
      "name": "Parse Triage Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.text || '{}';\nlet parsed = {};\ntry {\n  parsed = JSON.parse(raw.replace(/```json|```/g, '').trim());\n} catch(e) {\n  parsed = { category: 'other', priority: 'medium', one_line_summary: 'Parse error', draft_reply: '', label: 'other' };\n}\nconst prev = $('Extract Email Fields').first().json;\nreturn [{ json: { ...prev, ...parsed } }];"
      }
    },
    {
      "id": "gmail-draft",
      "name": "Create Gmail Draft",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        880,
        -120
      ],
      "parameters": {
        "operation": "createDraft",
        "sendTo": "={{ $json.from }}",
        "subject": "=Re: {{ $json.subject }}",
        "message": "={{ $json.draft_reply }}",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "check-urgent",
      "name": "Is Urgent?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        880,
        80
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false
          },
          "conditions": [
            {
              "id": "priority-check",
              "leftValue": "={{ $json.priority }}",
              "rightValue": "high",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ]
        }
      }
    },
    {
      "id": "slack-urgent",
      "name": "Slack Urgent Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1100,
        0
      ],
      "parameters": {
        "operation": "post",
        "channel": "YOUR_SLACK_CHANNEL_ID",
        "text": "=*Urgent email needs your attention*\n*From:* {{ $json.from }}\n*Subject:* {{ $json.subject }}\n*Summary:* {{ $json.one_line_summary }}\n*Category:* {{ $json.category }}\n\nDraft reply is ready in Gmail."
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Gmail Poll Unread": {
      "main": [
        [
          {
            "node": "Extract Email Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Email Fields": {
      "main": [
        [
          {
            "node": "Triage + Draft Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude Triage Model": {
      "ai_languageModel": [
        [
          {
            "node": "Triage + Draft Reply",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Triage + Draft Reply": {
      "main": [
        [
          {
            "node": "Parse Triage Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Triage Response": {
      "main": [
        [
          {
            "node": "Create Gmail Draft",
            "type": "main",
            "index": 0
          },
          {
            "node": "Is Urgent?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Urgent?": {
      "main": [
        [
          {
            "node": "Slack Urgent Alert",
            "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

NTF 03: Email Triage Agent. Uses gmailTrigger, lmChatAnthropic, chainLlm, gmail. Event-driven trigger; 9 nodes.

Source: https://github.com/MinaSaad1/n8n-email-triage/blob/main/workflows/01-email-triage.json — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

OpenRouter Chat, Gmail, Gmail Trigger +2
Email & Gmail

This n8n template shows you how to automate customer support email triage with a sovereign AI. By combining Gmail for inbox monitoring and the IONOS AI Model Hub, every customer email is classified an

Gmail Trigger, Chain Llm, @Ionos Cloud/N8N Nodes Ionos Cloud +1
Email & Gmail

Professionals and individuals who receive high volumes of emails, those who want to automatically organize their Gmail inbox using AI classification.

OpenRouter Chat, Chain Llm, Gmail Trigger +1
Email & Gmail

This template is built to be customized for your specific needs. This template has the core logic and n8n node specific references sorted to work with dynamic file names throughout the workflow. Store

Gmail, Slack, Gmail Trigger +3
Email & Gmail

This is an elite enterprise-grade solution for Talent Acquisition and HR Ops teams. It automates the high-volume task of resume screening by transforming unstructured PDF applications into structured

N8N Nodes Htmlcsstopdf, Postgres, HubSpot +4