This workflow corresponds to n8n.io template #13180 — we link there as the canonical source.
This workflow follows the Agent → Datatable 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": "d56BKcKZud3ENFsPn3BYS",
"name": "Triage requests from Slack and Gmail with a plug and play intake layer",
"tags": [],
"nodes": [
{
"id": "a47f4fcc-9504-4f2d-8a43-2fdb6580d1df",
"name": "LLM for message normalization",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1008,
448
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {},
"builtInTools": {}
},
"typeVersion": 1.3
},
{
"id": "c45714d0-0805-49ab-af7f-57befcc7d38a",
"name": "LLM for triage agent",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1760,
480
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5.2",
"cachedResultName": "gpt-5.2"
},
"options": {},
"builtInTools": {}
},
"typeVersion": 1.3
},
{
"id": "c05ed7f5-fc0e-45e0-978f-d05cca2fc949",
"name": "Parse triage JSON",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1888,
480
],
"parameters": {
"autoFix": true,
"schemaType": "manual",
"inputSchema": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://example.com/hr-triage.schema.json\",\n \"title\": \"HR Triage Classification Output\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"ticket_title\",\n \"summary\",\n \"category\",\n \"eisenhower_quadrant\",\n \"urgency\",\n \"importance\",\n \"effort\",\n \"risk\",\n \"confidence\",\n \"should_create_ticket\",\n \"suggested_assignee_role\",\n \"suggested_due_date\",\n \"draft_reply\"\n ],\n \"properties\": {\n \"ticket_title\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 90,\n \"description\": \"Short ticket title, ideally 6 to 10 words.\"\n },\n \"summary\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 140,\n \"description\": \"Short summary, max about 20 words.\"\n },\n \"category\": {\n \"type\": \"string\",\n \"enum\": [\"Payroll\", \"Time off\", \"Contract\", \"Hiring\", \"IT\", \"Facilities\", \"Finance\", \"Other\"]\n },\n \"eisenhower_quadrant\": {\n \"type\": \"string\",\n \"enum\": [\"DoNow\", \"Plan\", \"Delegate\", \"Defer\"]\n },\n \"urgency\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 10\n },\n \"importance\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 10\n },\n \"effort\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 10\n },\n \"risk\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 10,\n \"description\": \"Risk includes legal, compliance, reputation, escalation potential.\"\n },\n \"confidence\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n \"should_create_ticket\": {\n \"type\": \"boolean\"\n },\n \"suggested_assignee_role\": {\n \"type\": \"string\",\n \"enum\": [\"HR Ops\", \"Recruiter\", \"People Lead\", \"IT\", \"Finance\"]\n },\n \"suggested_due_date\": {\n \"type\": \"string\",\n \"format\": \"date\",\n \"description\": \"ISO 8601 date, for example 2026-01-25.\"\n },\n \"draft_reply\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 600,\n \"description\": \"One short reply suitable for Slack or email.\"\n }\n }\n}\n"
},
"typeVersion": 1.3
},
{
"id": "3f36efad-c273-406f-b14b-dcef692a84d2",
"name": "LLM for structured parsing",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1888,
656
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5.2",
"cachedResultName": "gpt-5.2"
},
"options": {},
"builtInTools": {}
},
"typeVersion": 1.3
},
{
"id": "9e078e3d-3947-4063-a819-bd9d1919843e",
"name": "Notify in Slack",
"type": "n8n-nodes-base.slack",
"position": [
2480,
160
],
"parameters": {
"text": "={{ $('Triage and prioritize request').item.json.output.summary }}",
"user": {
"__rl": true,
"mode": "list",
"value": "REPLACE_WITH_SLACK_USER_ID"
},
"select": "user",
"otherOptions": {},
"authentication": "oAuth2"
},
"typeVersion": 2.4
},
{
"id": "bd0bd87f-ffaf-477f-a695-ae2c5acfb18c",
"name": "Run every minute",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
320,
176
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "896e927d-47b1-408c-a32b-622bd8791678",
"name": "Fetch recent Slack messages",
"type": "n8n-nodes-base.slack",
"position": [
544,
176
],
"parameters": {
"options": {},
"resource": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": ""
},
"operation": "get",
"authentication": "oAuth2"
},
"typeVersion": 2.4
},
{
"id": "221a8952-07aa-4c9a-91ab-110a0390bfad",
"name": "Watch inbound Gmail messages",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
544,
368
],
"parameters": {
"simple": false,
"filters": {
"sender": ""
},
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "ac6b1a3c-221a-48f7-b653-3f01a013407e",
"name": "Skip already processed items",
"type": "n8n-nodes-base.dataTable",
"position": [
1312,
256
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "uniqueID",
"keyValue": "={{ $json.output.source_id + $json.output.source }}"
}
]
},
"operation": "rowNotExists",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 1.1
},
{
"id": "c34eef0e-60f9-4b90-8d3d-f078dde3a1b3",
"name": "Store processed IDs",
"type": "n8n-nodes-base.dataTable",
"position": [
1536,
256
],
"parameters": {
"columns": {
"value": {
"uniqueID": "={{ $json.output.source + $json.output.source_id }}"
},
"schema": [
{
"id": "uniqueID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "uniqueID",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"uniqueID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 1.1
},
{
"id": "f0cd3b01-eeb4-45f0-aefa-49e0e83183f5",
"name": "Triage and prioritize request",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1792,
256
],
"parameters": {
"text": "=Input item JSON: {{ JSON.stringify($('Universal intake normalizer').item.json.output) }}\n\nClassify it and return:\n\nsummary (max 20 words)\n\ncategory (Payroll, Time off, Contract, Hiring, IT, Facilities, Finance, Other)\n\neisenhower_quadrant (DoNow, Plan, Delegate, Defer)\n\nurgency 0-10\n\nimportance 0-10\n\neffort 0-10\n\nrisk 0-10\n\nconfidence 0-1\n\nshould_create_ticket true or false\n\nsuggested_assignee_role (HR Ops, Recruiter, People Lead, IT, Finance)\n\nsuggested_due_date (ISO date)\n\ndraft_reply (one short reply for Slack or email)\n\ntoday is {{ $now }}",
"options": {
"systemMessage": "System message\n\nYou are an HR operations triage assistant.\n\nYour job is to read a single inbound item and return structured JSON only.\n\nIf you are not confident, set confidence low and recommend human review.\n\nNever invent facts. Use only the given text."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "117965c8-6d91-4366-bd5b-b5f30d275b06",
"name": "Create Notion ticket",
"type": "n8n-nodes-base.notion",
"position": [
2256,
352
],
"parameters": {
"simple": false,
"options": {},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "REPLACE_WITH_NOTION_DATABASE_ID"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Description|rich_text",
"textContent": "={{ $json.output.summary }}"
},
{
"key": "Assignee Role|rich_text",
"textContent": "={{ $json.output.suggested_assignee_role }}"
},
{
"key": "confidence_score|number",
"numberValue": "={{ $json.output.confidence }}"
},
{
"key": "Due Date|date",
"date": "={{ $json.output.suggested_due_date }}"
},
{
"key": "effort|number",
"numberValue": "={{ $json.output.effort }}"
},
{
"key": "Helpful other things|rich_text",
"textContent": "={{ $json.output.draft_reply }}"
},
{
"key": "importance|number",
"numberValue": "={{ $json.output.importance }}"
},
{
"key": "risk|number",
"numberValue": "={{ $json.output.risk }}"
},
{
"key": "Status|status",
"statusValue": "Backlog"
},
{
"key": "urgency|number",
"numberValue": "={{ $json.output.urgency }}"
},
{
"key": "Priority|select",
"selectValue": "={{ $json.output.eisenhower_quadrant }}"
},
{
"key": "Name|title",
"title": "={{ $json.output.ticket_title }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "80284d99-b8b0-4dba-abbd-943a7efa63e7",
"name": "Only high importance items",
"type": "n8n-nodes-base.filter",
"position": [
2256,
160
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "7620c1d1-cf9a-47ca-b451-c98154644b0e",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.output.importance }}",
"rightValue": 9
}
]
}
},
"typeVersion": 2.3
},
{
"id": "f6a969ab-16ba-4348-835d-2f5e78fb9828",
"name": "Main sticky note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-352,
32
],
"parameters": {
"width": 528,
"height": 592,
"content": "## How it works\n* This workflow collects inbound requests from Slack and Gmail.\n* Each item is normalized into a consistent JSON structure.\n* A data table is used to dedupe items so the same request is not processed twice.\n* An AI agent classifies the request, scores urgency and importance, and suggests a reply.\n* A Notion ticket is created for tracking, and very important items can trigger a Slack alert.\n\nSafety note: This workflow sends content to LLMs. Keep third party terms in mind and avoid processing restricted or sensitive data.\n\n## Setup steps\n* Connect Slack, Gmail, Notion, and OpenAI credentials in n8n.\n* Select a Slack channel to read from and a Slack user to notify.\n* Point the Notion node to your own database and confirm the property names match.\n* Create or select a data table and map the uniqueID column.\n* Tune the filter threshold and consider truncating message text to control cost.\n\n## Extending\n* Just connect a trigger from any source at the beginning and connect to normalize node"
},
"typeVersion": 1
},
{
"id": "9b78ff76-f0b6-45c6-801d-02bbd336df26",
"name": "Group sticky note: Collect items",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
32
],
"parameters": {
"color": 7,
"width": 528,
"height": 560,
"content": "### Collect items\n* Schedule trigger polls a Slack channel.\n* Gmail trigger watches for new messages.\n* Configure the Slack channel and Gmail sender filter before enabling."
},
"typeVersion": 1
},
{
"id": "4a383452-73df-4d85-a7aa-113aa976ca4e",
"name": "Group sticky note: Extract content",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
64
],
"parameters": {
"color": 7,
"width": 704,
"height": 544,
"content": "### Normalize and dedupe\n* Normalizes sources into one schema.\n* Uses a data table to skip repeats.\n* Ensure the data table exists and has a uniqueID column.\n* Makes it possible to add a new source as plug-and-play"
},
"typeVersion": 1
},
{
"id": "255cabc3-d456-4e95-b312-cdab31ff4f1b",
"name": "Group sticky note: Analyze and send",
"type": "n8n-nodes-base.stickyNote",
"position": [
1696,
64
],
"parameters": {
"color": 7,
"width": 976,
"height": 736,
"content": "### Analyze and send\n* AI agent outputs structured fields.\n* Notion ticket is created for tracking.\n* Slack notification is sent only when the filter matches.\n* Adjust the importance threshold as needed."
},
"typeVersion": 1
},
{
"id": "1a8c48ce-65b9-4a00-a11e-6ffc9459072a",
"name": "Universal intake normalizer",
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
"position": [
1008,
256
],
"parameters": {
"text": "={{ JSON.stringify($json) }}",
"options": {},
"schemaType": "fromJson",
"jsonSchemaExample": "{\n \"source\": \"gmail|slack|form|other\",\n \"source_id\": \"unique-id-from-source\",\n \"timestamp\": \"2026-01-25T10:15:00Z\",\n \"author\": {\n \"name\": \"\u2026\",\n \"handle\": \"\u2026\",\n \"email\": \"\u2026\"\n },\n \"context\": {\n \"channel\": \"\u2026\",\n \"thread_ts\": \"\u2026\",\n \"email_subject\": \"\u2026\"\n },\n \"text\": \"raw message text\",\n \"links\": [\"permalink or gmail thread url\"],\n \"attachments\": [\n {\"type\": \"file|image|pdf\", \"name\": \"\u2026\", \"url\": \"\u2026\"}\n ]\n}\n"
},
"typeVersion": 1.2
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "52058187-82fd-4d8d-8c5b-51f9e99232bb",
"connections": {
"Run every minute": {
"main": [
[
{
"node": "Fetch recent Slack messages",
"type": "main",
"index": 0
}
]
]
},
"Parse triage JSON": {
"ai_outputParser": [
[
{
"node": "Triage and prioritize request",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Store processed IDs": {
"main": [
[
{
"node": "Triage and prioritize request",
"type": "main",
"index": 0
}
]
]
},
"LLM for triage agent": {
"ai_languageModel": [
[
{
"node": "Triage and prioritize request",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"LLM for structured parsing": {
"ai_languageModel": [
[
{
"node": "Parse triage JSON",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Only high importance items": {
"main": [
[
{
"node": "Notify in Slack",
"type": "main",
"index": 0
}
]
]
},
"Fetch recent Slack messages": {
"main": [
[
{
"node": "Universal intake normalizer",
"type": "main",
"index": 0
}
]
]
},
"Universal intake normalizer": {
"main": [
[
{
"node": "Skip already processed items",
"type": "main",
"index": 0
}
]
]
},
"Skip already processed items": {
"main": [
[
{
"node": "Store processed IDs",
"type": "main",
"index": 0
}
]
]
},
"Watch inbound Gmail messages": {
"main": [
[
{
"node": "Universal intake normalizer",
"type": "main",
"index": 0
}
]
]
},
"LLM for message normalization": {
"ai_languageModel": [
[
{
"node": "Universal intake normalizer",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Triage and prioritize request": {
"main": [
[
{
"node": "Only high importance items",
"type": "main",
"index": 0
},
{
"node": "Create Notion ticket",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template helps you turn inbound messages into a clean, deduped queue of actionable tickets.
Source: https://n8n.io/workflows/13180/ — 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.
This workflow automates end-to-end sustainability lifecycle management for corporate sustainability teams, ESG governance officers, and circular economy programme leads. It addresses the challenge of
This workflow automates end-to-end ESG (Environmental, Social, and Governance) sustainability reporting for enterprise sustainability teams, compliance officers, and green governance leads. It solves
This workflow automates semiconductor board-level reliability monitoring using AI agents. It targets reliability engineers, manufacturing teams, and quality analysts. The system collects capacity, his
This workflow automates procurement fraud detection and supplier compliance monitoring for organizations managing complex purchasing operations. Designed for procurement teams, audit departments, and
This workflow automates end-to-end recruitment operations for HR teams, talent acquisition specialists, and hiring managers facing high-volume candidate processing challenges. It solves the critical p