AutomationFlowsAI & RAG › Leadinboxtriagebot

Leadinboxtriagebot

LeadInboxTriageBot. Uses gmailTrigger, openAi, gmail. Event-driven trigger; 21 nodes.

Event trigger★★★★☆ complexityAI-powered21 nodesGmail TriggerOpenAIGmail
AI & RAG Trigger: Event Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Gmail → Gmail Trigger 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": "LeadInboxTriageBot",
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "simple": false,
        "maxResults": 1,
        "filters": {
          "labelIds": [
            "INBOX"
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.4,
      "position": [
        256,
        272
      ],
      "id": "1846e42a-3a45-4b76-91ca-6f995781035d",
      "name": "Watch inbox",
      "retryOnFail": true,
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b689c1ae-5c5e-4987-a130-28914b8aea18",
              "name": "gmail_id",
              "value": "={{ $json.id || \"\" }}",
              "type": "string"
            },
            {
              "id": "c986fb8b-c6ff-4418-883c-a24058176c44",
              "name": "threadId",
              "value": "={{ $json.threadId || \"\" }}",
              "type": "string"
            },
            {
              "id": "2a1e0b09-39e8-4270-9547-9edb40246c8e",
              "name": "messageId",
              "value": "={{ $json.messageId || \"\" }}",
              "type": "string"
            },
            {
              "id": "4277a33b-9365-4105-9eff-169bde281708",
              "name": "subject",
              "value": "={{ $json.subject || \"\" }}",
              "type": "string"
            },
            {
              "id": "485b1e25-85c0-41aa-a189-d1d30946631a",
              "name": "body",
              "value": "={{ $json.text || \"\" }}",
              "type": "string"
            },
            {
              "id": "9c13aae8-5cee-4ea4-9291-eabbfc50db1e",
              "name": "from_email",
              "value": "={{ $json.from.value[0].address || \"\" }}",
              "type": "string"
            },
            {
              "id": "172aba08-06c0-4378-8672-40dd4d881aa5",
              "name": "from_name",
              "value": "={{ $json.from.value[0].name || \"\" }}",
              "type": "string"
            },
            {
              "id": "5835d429-7331-4851-ab41-a4b34c85690d",
              "name": "to_email",
              "value": "={{ $json.to.value[0].address || \"\" }}",
              "type": "string"
            },
            {
              "id": "923710f8-d8b0-411d-babd-97599d0f90d9",
              "name": "sender_domain",
              "value": "={{ ($json.from.value[0].address || \"\").split(\"@\")[1] || \"\" }}",
              "type": "string"
            },
            {
              "id": "a7f28ba7-337c-4e08-92a5-e1cce13b7a41",
              "name": "receivedAt",
              "value": "={{ new Date().toISOString() }}",
              "type": "string"
            },
            {
              "id": "91f9108a-c2ac-4695-b230-e29c64847d2e",
              "name": "raw_from",
              "value": "={{ $json.from.text || \"\" }}",
              "type": "string"
            }
          ]
        },
        "options": {
          "dotNotation": false
        }
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        528,
        272
      ],
      "id": "fe34b2f9-0465-406a-981d-b86d289d2390",
      "name": "Normalize email payload"
    },
    {
      "parameters": {
        "content": "## Gmail Watcher\n\n**\u2022 Polls inbox every minute\n\u2022 Detects new inbound emails\n\u2022 Filters INBOX messages only\n\u2022 Entry point for workflow execution\n\u2022 Controlled ingestion pipeline**",
        "height": 400,
        "width": 224
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        32
      ],
      "typeVersion": 1,
      "id": "8430a2f6-5863-4a5f-a04f-eab5d934f0d0",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Normalize & Extract Email\n**\u2022 Extracts structured email fields, Standardizes sender metadata\n\u2022 Builds internal processing schema\n\u2022 Cleans inconsistent Gmail payloads, Prepares data for downstream AI logic** ",
        "height": 400,
        "width": 224
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        32
      ],
      "typeVersion": 1,
      "id": "861ed6bc-8de7-4969-9310-426f40e19461",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "\n",
        "height": 560,
        "width": 656,
        "color": "#C17B7B"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        -80
      ],
      "typeVersion": 1,
      "id": "8fed81e1-a680-401a-bdc3-2a011031ff8b",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "## PHASE - 1 \n## Email Ingestion & Normalization Pipeline\n\n**\u2022 Gmail inbox polling trigger\n\u2022 Real-time inbound email ingestion\n\u2022 Metadata extraction & normalization\n\u2022 Stable internal payload schema\n\u2022 Sender/domain parsing\n\u2022 Automated message state handling\n\u2022 Preprocessing foundation for AI routing**",
        "height": 256,
        "width": 368,
        "color": "#C17B7B"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        -384
      ],
      "typeVersion": 1,
      "id": "fd4236e2-8132-4ee8-be40-30daea79dced",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "# \ud83d\udfe1 Trigger",
        "height": 80,
        "width": 200,
        "color": 5
      },
      "id": "c958fc98-1398-4c3c-9464-5e2a501fca9d",
      "name": "Section_Trigger",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        224,
        -64
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b0c22741-7a2e-4ebc-9bfb-bca23749232a",
              "name": "classification_system_prompt",
              "value": "You are an email classification engine for a business operations inbox. Your sole job is to read an incoming email and return a single JSON object \u2014 nothing else.  CATEGORIES: \n- LEAD: A potential customer expressing genuine interest in purchasing, evaluating, or learning more about products/services. Includes RFPs, demo requests, pricing inquiries, partnership enquiries. \n- SUPPORT: An existing customer reporting a bug, asking a how-to question, or requesting account help. \n- SPAM: Unsolicited mass email, cold sales pitches, newsletters, SEO offers, or automated promotional content. \n- OTHER: Internal forwards, calendar invites, automated system notifications, OOO replies, or anything that doesn't fit the above.  \nEXAMPLES:  \nExample 1 \u2014 LEAD: \nEmail: \"Hi, we're evaluating CRM tools for our 50-person sales team. Could you share pricing and arrange a demo?\" \nOutput: {\"category\":\"LEAD\",\"confidence\":0.97,\"reasoning\":\"Explicit demo and pricing request from a decision-maker evaluating tools for a team.\",\"suggested_priority\":\"HIGH\"}  \nExample 2 \u2014 SPAM: \nEmail: \"Boost your SEO rankings by 300%! Click here for our limited-time package.\" \nOutput: {\"category\":\"SPAM\",\"confidence\":0.99,\"reasoning\":\"Unsolicited promotional email with no genuine business intent.\",\n\"suggested_priority\":null}  \n\nOUTPUT RULES:\n1. Return raw valid JSON only. No markdown, no code fences, no explanation.\n2. The JSON must contain exactly these four fields:\n   - category\n   - confidence\n   - reasoning\n   - suggested_priority\n3. category must be exactly one of:\n   LEAD, SUPPORT, SPAM, OTHER\n4. confidence must be a float between 0.0 and 1.0\n5. reasoning must be one sentence maximum\n6. suggested_priority must be exactly one of:\n   HIGH, MEDIUM, LOW\n7. \nsuggested_priority must be null when category is not LEAD\n8. If unsure, default to OTHER with low confidence\n9. The response must be valid parsable JSON\n10. Never add extra fields\n11. CRITICAL: The JSON must start with { and end with }. \n    The field  \"suggested_priority\" must be with value exactly \n    one of these strings: HIGH, MEDIUM, LOW.\nmust be null when category is not LEAD.",
              "type": "string"
            },
            {
              "id": "0eb85692-b484-48e7-a66a-0f31711e99cd",
              "name": "classification_user_prompt",
              "value": "=Classify the following email.\nFrom domain: {{$json.sender_domain}} \nSubject: {{$json.subject_clean}} \nBody: {{$json.body_clean}}  \nReturn a single JSON object following the rules in the system prompt. \nReturn only: {\"category\":\"...\",\"confidence\":...,\"reasoning\":\"...\",\"suggested_priority\":...}\nNo other text.",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1232,
        288
      ],
      "id": "3f190471-445b-4e5c-9d5a-ebaf936223dc",
      "name": "Prompts"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $json;\n\n// 1. Clean Subject\nconst subject_clean = (item.subject || '')\n  .replace(/^(Re:|Fwd:|FW:|RE:|FWD:|AW:|Aw:)\\s*/gi, '').trim();\n\n// 2. Clean Body\nlet body = item.body || '';\n\n// Remove reply chains\nconst replyStopPatterns = [\n  /On .{5,130}(wrote:|\u00e9crit:)/s,\n  /-----+\\s*(Original Message|Forwarded Message|BEGIN)\\s*-----+/i,\n /^From:\\s.*$\\n^Sent:\\s.*$/gim\n];\nfor (const p of replyStopPatterns) {\n  const idx = body.search(p);\n  if (idx > 40) { body = body.substring(0, idx); break; }\n}\n\n// Remove signatures\nconst sigStopPatterns = [\n  /\\n--\\s*\\n/i,\n  /\\n(Best regards|Kind regards|Warm regards|Regards|Sincerely|Cheers)\\s*,?\\s*\\n/i,\n  /\\n[-\u2014]{3,}/\n];\nfor (const p of sigStopPatterns) {\n  const idx = body.search(p);\n  if (idx > 20) { body = body.substring(0, idx); break; }\n}\n\nconst body_clean = body\n// Normalize whitespace while preserving readability\n  .replace(/[ \\t]+/g, \" \")\n  .replace(/\\n{3,}/g, \"\\n\\n\")\n  .trim();\n\n\n\n// 3. Extract email/name from From field\nconst sender_email = (item.from_email || \"\").toLowerCase();\n\nconst sender_domain = sender_email.split(\"@\")[1] || \"\";\n\nconst sender_name = (item.from_name || \"\").trim();\n\nconst sender_first_name = sender_name.split(/\\s+/)[0] || \"\";\n\n// 4. Preview\nconst body_preview = body_clean.substring(0, 500);\n\nreturn {\n  ...item,\n  subject_clean,\n  body_clean,\n  body_preview,\n  sender_email,\n  sender_domain,\n  sender_name,\n  sender_first_name\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1008,
        288
      ],
      "id": "1bced48e-5dfe-42e1-8d0e-416fff85f4cf",
      "name": "Clean Email"
    },
    {
      "parameters": {
        "content": "",
        "height": 576,
        "width": 1200,
        "color": "#BFB5B5"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -80
      ],
      "typeVersion": 1,
      "id": "ac672e9f-c56c-4f9e-976e-0fc328688c01",
      "name": "Sticky Note8"
    },
    {
      "parameters": {
        "content": "## Parse Classification\n**\u2022 Parses AI-generated JSON safely\n\u2022 Validates categories & confidence ranges\n\u2022 Applies schema normalization rules\n\u2022 Prevents malformed downstream routing\n\u2022 Fallback protection for parsing failures**",
        "height": 416,
        "width": 256,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1776,
        32
      ],
      "typeVersion": 1,
      "id": "0f02fad7-a788-4b34-8c15-8464e851f8b8",
      "name": "Sticky Note7"
    },
    {
      "parameters": {
        "content": "## Classify Email\n**\u2022 LLM-based intent analysis\n\u2022 Categorizes emails into:\n  LEAD, SUPPORT, SPAM, OTHER\n\u2022 Generates confidence scoring\n\u2022 Infers operational lead priority\n\u2022 Optimized for structured automation workflows** ",
        "height": 416,
        "width": 304,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        32
      ],
      "typeVersion": 1,
      "id": "686c66e7-42f3-4884-b7e7-524049d68954",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $input.item.json;\nconst original = $('Clean Email').item.json;\nlet parse_failed = false;\nlet parsed;\n\ntry {\n  const raw =\n    item.output?.[1]?.content?.[0]?.text   // Responses API\n    ?? item.choices?.[0]?.message?.content  // Chat Completions API\n    ?? item.text\n    ?? \"\";\n  \n\n  const match = raw.match(/\\{[\\s\\S]*\\}/);\n  parsed = JSON.parse(match ? match[0] : raw);\n} catch {\n  parse_failed = true;\n  parsed = { category: \"OTHER\", confidence: 0, reasoning: \"Failed to parse model response.\", suggested_priority: null };\n}\n\nconst ALLOWED_CAT = [\"LEAD\", \"SUPPORT\", \"SPAM\", \"OTHER\"];\nconst ALLOWED_PRI = [\"LOW\", \"MEDIUM\", \"HIGH\"];\n\nif (!ALLOWED_CAT.includes(parsed.category)) { parsed.category = \"OTHER\"; parse_failed = true; }\n\nparsed.confidence = Math.max(0, Math.min(1, Number(parsed.confidence) || 0));\nparsed.reasoning = typeof parsed.reasoning === \"string\" ? parsed.reasoning.slice(0, 300) : \"No reasoning provided.\";\n\nif (parsed.category !== \"LEAD\") {\n  parsed.suggested_priority = null;\n} else if (!ALLOWED_PRI.includes(parsed.suggested_priority)) {\n  parsed.suggested_priority = \"MEDIUM\";\n}\nreturn {\n  ...original,\n  classification: {\n    category: parsed.category,\n    confidence: parsed.confidence,\n    reasoning: parsed.reasoning,\n    suggested_priority: parsed.suggested_priority\n  },\n  parse_failed,\n  classified_at: new Date().toISOString()\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1856,
        288
      ],
      "id": "d71ac091-f391-4a55-b8c2-c8f6b4ca1e75",
      "name": "Parse classification"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "llama-3.3-70b-versatile",
          "mode": "list",
          "cachedResultName": "LLAMA-3.3-70B-VERSATILE"
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "={{ $('Prompts').item.json.classification_system_prompt}}"
            },
            {
              "content": "={{ $('Prompts').item.json.classification_user_prompt }}"
            }
          ]
        },
        "simplify": false,
        "builtInTools": {},
        "options": {
          "instructions": "",
          "store": false,
          "temperature": 0
        }
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.3,
      "position": [
        1472,
        288
      ],
      "id": "74506c9e-67b6-4e1d-a5cc-0917ddeaa89f",
      "name": "Classify email",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## Prompts\n**\u2022 Centralized system & user prompts\n\u2022 Deterministic structured AI instructions\n\u2022 Strict JSON response enforcement\n\u2022 Category & priority constraints\n\u2022 Consistent downstream parsing behavior** ",
        "height": 416,
        "width": 224,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        32
      ],
      "typeVersion": 1,
      "id": "29125abc-d180-4f29-bf62-0ee6a2fc449c",
      "name": "Sticky Note9"
    },
    {
      "parameters": {
        "operation": "markAsRead",
        "messageId": "={{ $json.gmail_id }}"
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        1872,
        736
      ],
      "id": "130bd576-ad0d-4391-bea4-7a20cb830fd2",
      "name": "Mark a message as read1",
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## Mark a message as read\n**Marks successfully processed Gmail messages as read using the Gmail internal message ID** ",
        "height": 352,
        "width": 224
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1808,
        544
      ],
      "typeVersion": 1,
      "id": "b96c64c6-60b3-436e-9536-c71aedcc1844",
      "name": "Sticky Note13"
    },
    {
      "parameters": {
        "content": "## PHASE - 2\n\n## AI Classification & Semantic Processing Pipeline\n\n**\u2022 Email content sanitization\n\u2022 Semantic preprocessing & normalization\n\u2022 Centralized prompt orchestration\n\u2022 LLM-powered email classification\n\u2022 Structured JSON response enforcement\n\u2022 Confidence scoring & priority inference\n\u2022 Classification validation & fallback handling\n\u2022 Safe downstream AI routing preparation**",
        "height": 304,
        "width": 368,
        "color": "#BFB5B5"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1312,
        -400
      ],
      "typeVersion": 1,
      "id": "cb12479a-a27c-45c1-8387-631c9912e4c7",
      "name": "Sticky Note10"
    },
    {
      "parameters": {
        "content": "# \ud83d\udfe0 Pre-process",
        "height": 80,
        "width": 280,
        "color": 4
      },
      "id": "861b613d-9bfb-49ed-a81b-7175b7b37f38",
      "name": "Section_Preprocess",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        688,
        -64
      ]
    },
    {
      "parameters": {
        "content": "## Clean Email\n**\u2022 Removes reply chains & signatures\n\u2022 Sanitizes noisy email content\n\u2022 Extracts latest meaningful context\n\u2022 Reduces token usage & prompt noise\n\u2022 Improves downstream classification accuracy** ",
        "height": 416,
        "width": 224,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        32
      ],
      "typeVersion": 1,
      "id": "ba745542-b81e-4e95-8a7d-7b4cf41d86c3",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "# \ud83d\udfe6 Classify",
        "height": 80,
        "width": 232,
        "color": 6
      },
      "id": "95183737-8559-4f87-99f1-a82f580a8282",
      "name": "Section_Classify",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1648,
        -64
      ]
    }
  ],
  "connections": {
    "Watch inbox": {
      "main": [
        [
          {
            "node": "Normalize email payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize email payload": {
      "main": [
        [
          {
            "node": "Clean Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prompts": {
      "main": [
        [
          {
            "node": "Classify email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Email": {
      "main": [
        [
          {
            "node": "Prompts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse classification": {
      "main": [
        [
          {
            "node": "Mark a message as read1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify email": {
      "main": [
        [
          {
            "node": "Parse classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "98f89cfb-080f-4a0a-8363-99ff6a30dac7",
  "id": "frIKH7E4frasLmeS",
  "tags": [
    {
      "updatedAt": "2026-05-17T12:35:49.965Z",
      "createdAt": "2026-05-17T12:35:49.965Z",
      "id": "9DdkRio6FFt0KDAN",
      "name": "phase-1"
    },
    {
      "updatedAt": "2026-05-18T20:20:17.612Z",
      "createdAt": "2026-05-18T20:20:17.612Z",
      "id": "DwZiobfGzVfGQlJn",
      "name": "batch26_intern"
    },
    {
      "updatedAt": "2026-05-17T12:35:49.949Z",
      "createdAt": "2026-05-17T12:35:49.949Z",
      "id": "HP8bIX2EyHTE8tjn",
      "name": "training"
    },
    {
      "updatedAt": "2026-05-20T00:07:08.323Z",
      "createdAt": "2026-05-20T00:07:08.323Z",
      "id": "jbnaPX0FlZoNVGGj",
      "name": "LeadInbox"
    },
    {
      "updatedAt": "2026-05-20T00:07:08.303Z",
      "createdAt": "2026-05-20T00:07:08.303Z",
      "id": "sDZhwhPKimwdhRPb",
      "name": "Training"
    }
  ]
}

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

LeadInboxTriageBot. Uses gmailTrigger, openAi, gmail. Event-driven trigger; 21 nodes.

Source: https://github.com/tejash-sr/lead-triage-n8n/blob/31f4e4fec5564d3baa3887f747ebe9bd3afd12ef/workflows/v2-phase2.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

Openai Workflow. Uses openAi, gmailTrigger, gmail, crypto. Event-driven trigger; 49 nodes.

OpenAI, Gmail Trigger, Gmail +2
AI & RAG

Complete AI-powered sales system Automates lead capture, qualification, and follow-up from multiple channels. AI INTELLIGENCE:

Gmail Trigger, Google Sheets, OpenAI +3
AI & RAG

This workflow watches a Notion CRM for leads ready to contact, checks Gmail to avoid duplicate outreach, then sends or drafts an email with Google Drive PDF attachments and updates the lead status in

Notion Trigger, Gmail, Notion +4
AI & RAG

An automated quote generation system that monitors your inbox, classifies quote requests using AI, calculates intelligent pricing based on historical data, and provides a professional dashboard for re

Gmail Trigger, OpenAI, Supabase +2
AI & RAG

LeadInboxTriageBot_GT. Uses gmailTrigger, openAi, googleSheets, gmail. Event-driven trigger; 36 nodes.

Gmail Trigger, OpenAI, Google Sheets +2