{
  "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
          }
        ]
      ]
    }
  }
}