This workflow corresponds to n8n.io template #9581 — we link there as the canonical source.
This workflow follows the Agent → 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 →
{
"id": "gPmiDOmZMrVDuuV7",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Email support routing template V3",
"tags": [],
"nodes": [
{
"id": "1c626123-f1d6-45fd-8519-ac5342b4b38c",
"name": "Retrieve an existing dartboard",
"type": "n8n-nodes-dart.dart",
"position": [
880,
-96
],
"parameters": {
"id": "K7jRC0JC2Wxz",
"resource": "Dartboard",
"operation": "Get Dartboard",
"requestOptions": {}
},
"credentials": {
"dartApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "99aea42e-4e2f-476c-96b0-de382b83922e",
"name": "Create a new task",
"type": "n8n-nodes-dart.dart",
"position": [
1312,
32
],
"parameters": {
"item": "={\n \"title\": \"{{ $('Launch workflow on email receive').item.json.subject }}\",\n \"priority\": \"{{ $('Parsing stage for logic result').item.json.priority }}\",\n \"tags\": [\"{{ $('Parsing stage for logic result').item.json.category }}\"],\n\n \"description\": \"Rationale: {{ $('Parsing stage for logic result').item.json.rationale }}\\n\\n Confidence lvl: {{ $('Parsing stage for logic result').item.json.confidence }}\\n\\n Summary: {{ $('Parsing stage for logic result').item.json.summary }}\\n \\n Full email: \\n \\n {{ $('Cleaning up full text of email').item.json.cleanText }}\"\n}\n",
"resource": "Task",
"operation": "Create Task",
"requestOptions": {}
},
"credentials": {
"dartApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "6496bb73-0007-4b60-84cc-7e1268e85146",
"name": "Create a new comment",
"type": "n8n-nodes-dart.dart",
"position": [
1536,
32
],
"parameters": {
"item": "={ \"taskId\": \"{{ $json.item.id }}\",\n \"text\":\"Sender: {{ $('Launch workflow on email receive').item.json.from.value[0].name }} - {{ $('Launch workflow on email receive').item.json.from.value[0].address }}\"\n}",
"resource": "Comment",
"operation": "Add Task Comment",
"requestOptions": {}
},
"credentials": {
"dartApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "36935d91-24c5-4338-b766-5f58d092053e",
"name": "Cleaning up full text of email",
"type": "n8n-nodes-base.code",
"position": [
464,
-80
],
"parameters": {
"jsCode": "// Safely get the Gmail HTML body\nconst html = $('Launch workflow on email receive').first().json.textAsHtml || \"\";\n\n// --- CLEAN TEXT FROM HTML ---\n\n// Step 1: Normalize line breaks for <p>, <br>, and <div> tags\nlet clean = html\n .replace(/<(?:br|div)\\s*\\/?>/gi, '\\n')\n .replace(/<\\/p>/gi, '\\n');\n\n// Step 2: Remove anchor tags but keep inner text\nclean = clean.replace(/<a[^>]*>(.*?)<\\/a>/gi, '$1');\n\n// Step 3: Remove scripts, styles, and comments\nclean = clean\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<!--[\\s\\S]*?-->/g, '');\n\n// Step 4: Remove <img> tags and Gmail-style [image: ...] placeholders\nclean = clean\n .replace(/<img[^>]*>/gi, '')\n .replace(/\\[image:\\s*.*?\\]/gi, '');\n\n// Step 5: Strip remaining HTML tags\nclean = clean.replace(/<[^>]+>/g, ' ');\n\n// Step 6: Remove plain text URLs\nclean = clean.replace(/\\b(?:https?:\\/\\/|ftp:\\/\\/|www\\.|mailto:)\\S+\\b/gi, '');\n\n// Step 7: Decode basic HTML entities\nclean = clean\n .replace(/ /gi, ' ')\n .replace(/&/gi, '&')\n .replace(/</gi, '<')\n .replace(/>/gi, '>')\n .replace(/"/gi, '\"')\n .replace(/'/gi, \"'\");\n\n// Step 8: Clean up whitespace\nclean = clean\n .replace(/\\r/g, '')\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .replace(/\\s+/g, ' ')\n .trim();\n\n// Step 9: Remove potentially problematic symbols and quotes\nclean = clean\n .replace(/['\"`]/g, '') // remove single, double, and back quotes\n .replace(/[<>\\\\]/g, '') // remove angle brackets and backslashes\n .replace(/[{}[\\]]/g, '') // remove braces and brackets\n .replace(/[^\\x20-\\x7E\\n]/g, ''); // remove non-printable characters (safe ASCII only)\n\n// --- RETURN CLEAN TEXT AS OUTPUT ---\n\nreturn [\n {\n json: {\n cleanText: clean,\n },\n },\n];\n"
},
"typeVersion": 2
},
{
"id": "9e25bad8-5f56-49b8-aa69-42fa0faaf489",
"name": "Email triage assistant logic",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-352,
96
],
"parameters": {
"text": "=[System instruction]\nYou are a concise email triage assistant whose sole job is to read a user email and pick the best single category from {Billing, Feature Request, Support Help Request, App Feedback, Bug Report, Task Updates, Unrelated}. Use the definitions and output schema provided below. Output only valid JSON that matches the schema exactly.\n\nDefinitions\n- Billing: Questions or disputes about charges, invoices, subscriptions, refunds, payment failures, billing address, tax, pricing plan changes, or account credits.\n- Feature Request: Suggestions for new features, changes to product behavior, wishlist items, or requests to add/change functionality.\n- Support Help Request: User reports of problems, errors, account access issues, setup/installation help, crashes, or anything asking for a fix or step-by-step assistance.\n- App Feedback: General feedback about experience, UI/UX suggestions not asking for a new feature, praise, complaints about design/tone/performance that do not request a fix or new functionality.\n- Bug Report: Reports describing reproducible software defects, unexpected behavior, incorrect outputs, or developer-facing error traces that require debugging and may need code fixes.\n- Task Updates: Notifications or status updates related to tasks, assignments, or workflow progress\u2014especially from Dart or similar systems.\n- Unrelated: Emails that do not fit any of the above categories, such as promotions, marketing material, job applications, newsletters, or personal messages.\n\nRequired JSON output schema (must be followed exactly)\n{\n \"category\": \"<one of: Billing|Feature Request|Support Help Request|App Feedback|Bug Report|Task Updates|Unrelated>\",\n \"confidence\": <number between 0.0 and 1.0, strictly in numbers>,\n \"rationale\": \"<one-sentence explanation of why this category was chosen>\",\n \"summary\": \"<one-line summary of the user's request>\",\n \"priority\": \"<low|medium|high|critical>\"\n}\n\n\n\nExample 1\nEmail: \"I was charged twice this month for my subscription. Please refund the duplicate charge and confirm when it\u2019s processed.\"\nCategory: Billing\nConfidence: 0.96\nRationale: \"Mentions duplicate charge and explicitly requests a refund.\"\nSummary: \"User reports duplicate charge and requests refund confirmation.\"\nPriority: high\n\nExample 2\nEmail: \"It would be great if we could export project timelines as CSV and include custom fields.\"\nCategory: Feature Request\nConfidence: 0.92\nRationale: \"User asks for new export feature and specific fields to include.\"\nSummary: \"Request to add CSV export for timelines with custom fields.\"\nPriority: low\n\nExample 3\nEmail: \"App crashes every time I click Save on long tasks; I need help getting my data back.\"\nCategory: Support Help Request\nConfidence: 0.98\nRationale: \"Reports a reproducible crash and asks for help retrieving data.\"\nSummary: \"App crashes on Save for long tasks; user needs data recovery help.\"\nPriority: high\n\nExample 4\nEmail: \"Love the new color theme but the contrast on small text feels low; overall experience is much improved.\"\nCategory: App Feedback\nConfidence: 0.85\nRationale: \"Gives UI feedback and praise without requesting changes or fixes.\"\nSummary: \"Positive feedback on theme with a note about low contrast on small text.\"\nPriority: low\n\nExample 5\nEmail: \"When running the Code node, I get a stack trace: Error: Code doesn't return items properly at validateRunCodeAllItems ... Please advise.\"\nCategory: Bug Report\nConfidence: 0.95\nRationale: \"Provides a developer-facing stack trace and describes a reproducible failure in node execution.\"\nSummary: \"Code node throws validateRunCodeAllItems error with full stack trace.\"\nPriority: high\n\nExample 6\nEmail: \"Task #3421 has been marked complete. Please review the final notes and close the loop.\"\nCategory: Task Updates\nConfidence: 0.93\nRationale: \"Mentions a specific task ID and status update, typical of automated workflow notifications.\"\nSummary: \"Task #3421 marked complete; user asked to review and finalize.\"\nPriority: medium\n\nExample 7\nEmail: \"We\u2019re hiring! Check out our open roles and apply today to join our team.\"\nCategory: Unrelated\nConfidence: 0.90\nRationale: \"Promotional job application email not related to product, support, or user feedback.\"\nSummary: \"Marketing email promoting open job roles.\"\nPriority: low\n\nInstructions\n- Read the email and map it to exactly one category.\n\n- If the email contains both billing and a technical problem, prioritize Billing if a payment dispute or refund is explicitly requested; otherwise prioritize Support Help Request.\n\n- Confidence Calibration\n0.95\u20131.00: Explicit intent (e.g., \u201crefund,\u201d \u201cadd feature,\u201d \u201ccrash\u201d).\n0.85\u20130.94: Strongly implied intent with supporting context.\n0.75\u20130.84: Somewhat implied or ambiguous.\n<0.75: Weak or uncertain match.\n\n- Priority Rules\ncritical \u2013 Use only when the issue completely prevents the user (or all users) from accessing core features, causes total data loss, or exposes a severe security or privacy risk. Typically urgent and business-blocking.\nExamples \u2013 \u201cThe app won\u2019t load at all for any of our users.\u201d / \u201cAll my project data disappeared after the update.\u201d / \u201cSensitive user info is visible to others.\u201d\n\nhigh \u2013 The issue directly affects core functionality, payments, or productivity but does not fully block all access. Includes reproducible crashes, failed payments, or broken workflows with financial or time impact.\nExamples \u2013 \u201cI was charged twice this month for my subscription.\u201d / \u201cThe app crashes whenever I click Save.\u201d / \u201cCheckout form gives an error and I can\u2019t complete my purchase.\u201d\n\nmedium \u2013 The issue or update affects secondary features, task progress, or non-critical operations. The user can still perform main tasks but with inconvenience or delay. Also applies to workflow notifications and status updates.\nExamples \u2013 \u201cTask #2341 marked complete \u2014 please review.\u201d / \u201cThe report export takes longer than usual.\u201d / \u201cNotifications stopped appearing, but the app still works.\u201d\n\nlow \u2013 Minor or non-urgent matters that don\u2019t affect functionality or access. Includes suggestions, praise, design opinions, and promotional or unrelated content.\nExamples \u2013 \u201cLove the new theme, but text contrast is low.\u201d / \u201cIt would be great if you could add dark mode.\u201d / \u201cWe\u2019re hiring! Apply today.\u201d\n\n- Output only the JSON object and nothing else, matching the schema exactly.\n\nEmail: {{ $json.text }}",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "f0ff7c52-ab08-4179-a606-7c26dac2be67",
"name": "Parsing stage for logic result",
"type": "n8n-nodes-base.code",
"position": [
80,
-80
],
"parameters": {
"jsCode": "// Get raw input\nlet rawString = $input.first().json.output;\n\n// Clean up markdown formatting if present\nrawString = rawString\n .trim()\n .replace(/^```(json)?/i, '') // remove leading ``` or ```json\n .replace(/```$/i, '') // remove trailing ```\n .trim();\n\n// Try parsing the cleaned string\nlet parsed;\ntry {\n parsed = JSON.parse(rawString);\n} catch (error) {\n throw new Error(`Failed to parse JSON. Cleaned input was:\\n${rawString}\\n\\nError: ${error.message}`);\n}\n\nreturn parsed;"
},
"typeVersion": 2
},
{
"id": "f4494b77-af5f-491a-a879-35626a4a53c1",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-576,
-480
],
"parameters": {
"color": 7,
"width": 496,
"height": 880,
"content": "## 1. Workflow launch through email capture\nTriggered by a new support email via Gmail.\n\n### Email categorization\nAI routes each email into one of 7 categories:\n- Billing\n- Feature Request\n- Support Help Request\n- App Feedback\n- Bug Report\n- Task Updates\n- Unrelated\n\n### AI metadata assignment\nEach email gets:\n- **Confidence**: AI certainty score \n- **Priority**: Based on urgency and impact \n- **Rationale**: One-line reason for category \n- **Summary**: One-line digest of the message\n\n### Model selection\nTest and use any AI chat model. (Results could vary by model quality)"
},
"typeVersion": 1
},
{
"id": "6ee8c2c2-ae3e-4b3e-9c3c-64c22b75f575",
"name": "Launch workflow on email receive",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-528,
96
],
"parameters": {
"simple": false,
"filters": {},
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "4d05284b-c32c-4976-a288-eae436031618",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
-400
],
"parameters": {
"color": 7,
"width": 560,
"height": 592,
"content": "## 5. Create categorized task in Dart\nConvert parsed email data into actionable tasks.\n\n### Task creation includes\n- **Title:** Email subject \n- **Tag:** Category (Bug, Billing, Feature, etc.) \n- **Priority:** AI\u2011assigned based on urgency \n- **Description:** Confidence, rationale, summary, and cleaned email body \n\n### Sender context as comment\n- Add sender name and address as a comment \n- Keeps the task description focused while preserving context \n\n### Outcome\nEach email becomes a structured, actionable Dart task, ready for triage and resolution."
},
"typeVersion": 1
},
{
"id": "ab0ce8ce-5e7c-4ea1-884c-04e29e4085c0",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-384,
272
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "2511dbfe-0144-4732-a774-8aadeced4b3d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
-384
],
"parameters": {
"width": 400,
"height": 544,
"content": "## Support email routing template\nThis workflows acts as an AI-powered triage assistant. It reads each incoming email, classifies it into one of seven categories, and then automatically creates a task in the selected Dartboard.\n\n### Who's it for\nSupport and ops teams using Dart to manage diverse inbound requests from clients, partners, or systems.\n\n### How to setup\n- Import the workflow into n8n\n- [Connect your Dart](https://help.dartai.com/en/articles/12313191-n8n-integration) and Gmail account\n- Replace the dummy Dartboard ID with your actual board ID\n- Use your preferred AI chat model (Results could vary by model quality)\n- If your target email address is in a google group, use the **Filter: \"Sender\"** in the Gmail trigger\n\n### Customizing the workflow\n- You can modify the category list\n- Adjust AI classification prompt\n\n\n\n"
},
"typeVersion": 1
},
{
"id": "75fed5e4-c0c8-4ce8-a6a7-17802648187c",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-16,
-368
],
"parameters": {
"color": 7,
"width": 304,
"height": 448,
"content": "## 2. Parsing the AI output\nParse output into a usable format for the next nodes.\n\n### JSON formatting\n- **Parse:** AI output into structured JSON \n- **Extract:** Category, Priority, Confidence, Rationale, Summary \n- **Ensure:** Clean, consistent, taggable data"
},
"typeVersion": 1
},
{
"id": "3c97d14f-68a1-490a-8038-108067275ff9",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
352,
-336
],
"parameters": {
"color": 7,
"width": 320,
"height": 416,
"content": "## 3. Full email body cleanup\nThis node cleans the email body from the Gmail trigger by removing formatting noise and unnecessary content.\n\n### Email cleanup\n- **Strip:** HTML tags, inline styles, formatting noise \n- **Convert:** Plain text for easier processing and display"
},
"typeVersion": 1
},
{
"id": "ba98569a-e446-4aef-88c7-d529b233f180",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
-352
],
"parameters": {
"color": 7,
"width": 400,
"height": 448,
"content": "## 4. Retrieve target dartboard\nSelect the Dartboard in your workspace where new tasks will be created.\n\n### Dartboard targeting\n- Locate your Dartboard ID in the workspace \n- Replace the placeholder ID in this node\n- Confirms all generated tasks route to the correct board\n"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "27f135de-6b55-42ad-8a04-f8cc67fc925f",
"connections": {
"Create a new task": {
"main": [
[
{
"node": "Create a new comment",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Email triage assistant logic",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Email triage assistant logic": {
"main": [
[
{
"node": "Parsing stage for logic result",
"type": "main",
"index": 0
}
]
]
},
"Cleaning up full text of email": {
"main": [
[
{
"node": "Retrieve an existing dartboard",
"type": "main",
"index": 0
}
]
]
},
"Parsing stage for logic result": {
"main": [
[
{
"node": "Cleaning up full text of email",
"type": "main",
"index": 0
}
]
]
},
"Retrieve an existing dartboard": {
"main": [
[
{
"node": "Create a new task",
"type": "main",
"index": 0
}
]
]
},
"Launch workflow on email receive": {
"main": [
[
{
"node": "Email triage assistant logic",
"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.
dartApigmailOAuth2openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automatically turn incoming support emails into categorized, prioritized tasks in Dart—complete with AI-generated summaries, tags, and sender context.
Source: https://n8n.io/workflows/9581/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
> Note: This workflow uses sticky notes extensively to document each logical section of the automation. Sticky notes are mandatory and already included to explain OCR, AI parsing, folder logic, dup
This template and YouTube video goes over 5 different implementations of evaluations within n8n. Categorization Correctness Tools used String similarity Helpfulness
Automate your personal productivity with this intelligent n8n workflow that integrates Telegram, Google Sheets, and OpenAI (GPT-4o). This system uses multiple AI agents to manage work hours, tasks, fi
Stop manually sending follow-ups. This workflow automates your entire cold email outreach with AI-powered personalization, smart scheduling, and automatic reply detection.
This n8n workflow automates sales processes using AI agents integrated with Airtable as a CRM and Gmail for email handling. It consists of two main workflows: one for handling Airtable status changes