{
  "id": "HRyFjV8E0q8972jxLIpIE",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "LinkedIn Triage with Labels",
  "tags": [],
  "nodes": [
    {
      "id": "19cf7de1-76aa-4360-88c2-3d69f349c823",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "onError": "continueRegularOutput",
      "position": [
        752,
        384
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"required\": [\n    \"message_id\",\n    \"subject\",\n    \"action\",\n    \"relevancy_score\",\n    \"sales_likelihood\",\n    \"summary\"\n  ],\n  \"properties\": {\n    \"message_id\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 200 },\n    \"date_iso\": { \"type\": \"string\", \"minLength\": 0, \"maxLength\": 40 },\n    \"from_name\": { \"type\": \"string\", \"maxLength\": 120 },\n    \"subject\": { \"type\": \"string\", \"maxLength\": 200 },\n\n    \"action\": { \"type\": \"string\", \"enum\": [\"reply_quick\", \"review\", \"ignore\", \"block\"] },\n    \"relevancy_score\": { \"type\": \"integer\", \"minimum\": 0, \"maximum\": 100 },\n    \"sales_likelihood\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 },\n\n    \"summary\": { \"type\": \"string\", \"maxLength\": 220 },\n    \"reply_draft\": { \"type\": \"string\", \"maxLength\": 700 },\n    \"tags\": {\n      \"type\": \"array\",\n      \"maxItems\": 6,\n      \"items\": { \"type\": \"string\", \"maxLength\": 24 }\n    }\n  }\n}\n"
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 1.3,
      "alwaysOutputData": false
    },
    {
      "id": "bd362e1e-6945-43b1-9a9c-173a428c7518",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        752,
        592
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.2",
          "cachedResultName": "gpt-5.2"
        },
        "options": {},
        "builtInTools": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "2d0ec52f-4b29-443d-908e-33f37d061143",
      "name": "Daily Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -496,
        160
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "9e8cdc78-af9d-416c-b967-4a94c4d8e403",
      "name": "Pull Messages From with LinkedIn tags",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -272,
        160
      ],
      "parameters": {
        "limit": 500,
        "filters": {
          "labelIds": [
            "REPLACE_WITH_YOUR_GMAIL_LABEL_ID"
          ],
          "receivedAfter": "={{ $now.minus({ days: 1 }).startOf('day').toISO() }}\n"
        },
        "operation": "getAll"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0b144918-ad7e-40c2-9ecf-3bb29ff63754",
      "name": "First Filter for non direct messages or invites",
      "type": "n8n-nodes-base.filter",
      "position": [
        -48,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.From }}",
              "rightValue": "invitations"
            },
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.From }}",
              "rightValue": "messages"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "3193be9d-48df-4297-b6dc-0cc517aea00b",
      "name": "Second Filter for non direct messages or invites",
      "type": "n8n-nodes-base.filter",
      "position": [
        176,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.snippet }}",
              "rightValue": "You're getting noticed"
            },
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.Subject }}",
              "rightValue": "Welcome to"
            },
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.snippet }}",
              "rightValue": "LinkedIn Page admin"
            },
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.snippet }}",
              "rightValue": "company verification"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d9be4829-a33a-4ee4-b663-ff6e63dee4c6",
      "name": "Pull body of messages",
      "type": "n8n-nodes-base.gmail",
      "position": [
        400,
        160
      ],
      "parameters": {
        "simple": false,
        "options": {},
        "messageId": "={{ $json.id }}",
        "operation": "get"
      },
      "typeVersion": 2.2
    },
    {
      "id": "8c44d562-1c1f-4287-89fb-643edb8e20f3",
      "name": "Open AI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        624,
        384
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.2",
          "cachedResultName": "gpt-5.2"
        },
        "options": {
          "maxTokens": 6000
        },
        "builtInTools": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "8083ae5c-9dce-4309-a2e4-2e7aa48d7b52",
      "name": "LinkedIn Triage Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueRegularOutput",
      "position": [
        656,
        160
      ],
      "parameters": {
        "text": "=MessageID(DO NOT CHANGE):{{ $json.id }}\nSubject: {{ $json.subject }}\nDate: {{ $json.date }}\nSender: {{ $json.from.value[0].name }}\nBody: {{ ($json.text || '').slice(0, 4000) }}\n",
        "options": {
          "systemMessage": "You are triaging my LinkedIn related emails from the last 24 hours.\n\nGoal:\n- Surface messages worth my time\n- Filter out sales and spam aggressively\n- Suggest short replies when it looks like an actual person message or InMail content\n\nRules:\n- If it smells like outbound sales, set sales_likelihood high and action to ignore or block.\n- If it could be real business, action is reply_quick and include 1 to 3 suggested replies.\n- If it is interesting but not urgent, action is review.\n- If it is annoying, repetitive, irrelevant, or clearly automated, ignore.\n- Block only if it is clearly spammy, pushy sales, or deceptive.\n\nReturn ONLY valid JSON matching the schema.\n\nIf unsure, choose action ignore, sales_likelihood 0.5, relevancy_score 20, summary minimal"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "54068f8e-6b42-48a9-a99e-76872ddd4c35",
      "name": "Filter out Irrelevant and Sales heavy requests",
      "type": "n8n-nodes-base.filter",
      "position": [
        1120,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.output.sales_likelihood }}",
              "rightValue": 0.8
            },
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.output.relevancy_score }}",
              "rightValue": 40
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e75bc8d3-1c56-4564-8e5b-181848b252c9",
      "name": "Put into Ticketing System",
      "type": "n8n-nodes-base.notion",
      "position": [
        1344,
        160
      ],
      "parameters": {
        "simple": false,
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_YOUR_NOTION_DATABASE_ID"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "date_iso|rich_text",
              "textContent": "={{ $json.output.date_iso }}"
            },
            {
              "key": "from_name|rich_text",
              "textContent": "={{ $json.output.from_name }}"
            },
            {
              "key": "message_id|title",
              "title": "={{ $json.output.message_id }}"
            },
            {
              "key": "relevancy_score|number",
              "numberValue": "={{ $json.output.relevancy_score }}"
            },
            {
              "key": "reply_draft|rich_text",
              "textContent": "={{ $json.output.reply_draft || \"\" }}"
            },
            {
              "key": "sales_likelihood|number",
              "numberValue": "={{ $json.output.sales_likelihood }}"
            },
            {
              "key": "subject|rich_text",
              "textContent": "={{ $json.output.subject }}"
            },
            {
              "key": "summary|rich_text",
              "textContent": "={{ $json.output.summary }}"
            },
            {
              "key": "tags|multi_select",
              "multiSelectValue": "={{ $json.output.action }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ed407ae0-6888-4246-b5be-9da0c8a74524",
      "name": "Filter out reply quick tickets",
      "type": "n8n-nodes-base.filter",
      "position": [
        1568,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "REDACTED_CONDITION_ID",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.properties.tags.multi_select[0].name }}",
              "rightValue": "reply_quick"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "1c0c409b-508a-42a4-b9ce-8c15c2e9f6a2",
      "name": "Send Message to myself",
      "type": "n8n-nodes-base.slack",
      "position": [
        1792,
        160
      ],
      "parameters": {
        "text": "=Daily LinkedIn: \nSubject: {{ $json.properties.from_name.rich_text[0].text.content }}\nSummary: {{ $json.properties.summary.rich_text[0].text.content }}\n\nPossible drafts: \n{{ $json.properties.reply_draft.rich_text[0].text.content }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_YOUR_SLACK_USER_ID",
          "cachedResultName": "me"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "cf99bf36-e47f-4c52-89fc-8e2818c7d93d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        -432
      ],
      "parameters": {
        "width": 464,
        "height": 720,
        "content": "## LinkedIn notifications and InMails triage\n\nThis workflow runs daily and turns LinkedIn email noise into a short list of messages worth your attention. It pulls emails from Gmail using a label, filters out common automated notifications, fetches the full email body, and uses an AI agent to classify each message. The result is stored in Notion so you have a searchable inbox, and the most relevant items can trigger a Slack DM so you can reply quickly.\n\n## How it works\n* Trigger daily\n* Read Gmail messages from a LinkedIn label (last 24h)\n* Filter out invitations and automated notifications\n* Fetch full email body (not just the snippet)\n* AI triage returns structured fields like action, relevancy, and a reply draft\n* Save the result to Notion\n* Optionally notify you in Slack for items marked reply_quick\n\n## Setup steps\n* Create a Gmail label for LinkedIn emails and add the label id in the Gmail node\n* Connect Gmail, OpenAI, Notion, and Slack credentials\n* Replace the Notion database id and ensure properties match the mapped fields\n* Replace the Slack user id (or change to a channel)\n* Run once, check a few results, then activate the workflow\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6bdecd8d-871a-452d-a89f-de68d3a7034f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 816,
        "height": 352,
        "content": "## Gmail intake and noise filters\n* Pull messages from a Gmail label\n* Keep only real LinkedIn messages and InMails\n* Remove common automated notifications\nTip: update filter phrases to match your LinkedIn email language\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9da769c2-9ac6-4e2f-8f6b-6f9e8aefed6c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        592,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 784,
        "content": "## AI triage\n* Sends subject, sender, date, and a body excerpt to the model\n* Returns structured output for stable mapping\n* Produces action, relevancy, sales likelihood, summary, and optional reply draft\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e5f03d0a-bc28-4f9f-b11d-74ff675003b8",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        -288
      ],
      "parameters": {
        "color": 3,
        "width": 336,
        "height": 256,
        "content": "## Privacy note\nThis workflow sends email content to an LLM.\n\nDo not run this on sensitive mailboxes unless you are comfortable with that.\n\nIf needed:\n* reduce body length\n* redact content before the agent\n* store only summaries\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6a69872d-f2b0-4dd9-a609-d2cb771ec496",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1328,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 320,
        "content": "## Outputs\n* Notion stores every triaged message for later review\n* Slack notifies you only for reply_quick items\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c66580a6-5c86-4c39-8387-940109157b85",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2016,
        48
      ],
      "parameters": {
        "color": 3,
        "width": 336,
        "height": 224,
        "content": "## Cost and reliability\nNotes:\n* `maxTokens` is high, which can increase cost\n* If parsing fails, reduce body length or simplify the schema\n* Consider a fallback:\n  * if output invalid, set `action = review`\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "830e9afc-f6ac-4268-9c73-75d599ab5d70",
  "connections": {
    "Daily Trigger": {
      "main": [
        [
          {
            "node": "Pull Messages From with LinkedIn tags",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Structured Output Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Open AI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "LinkedIn Triage Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "LinkedIn Triage Agent": {
      "main": [
        [
          {
            "node": "Filter out Irrelevant and Sales heavy requests",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pull body of messages": {
      "main": [
        [
          {
            "node": "LinkedIn Triage Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "LinkedIn Triage Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Put into Ticketing System": {
      "main": [
        [
          {
            "node": "Filter out reply quick tickets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter out reply quick tickets": {
      "main": [
        [
          {
            "node": "Send Message to myself",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pull Messages From with LinkedIn tags": {
      "main": [
        [
          {
            "node": "First Filter for non direct messages or invites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter out Irrelevant and Sales heavy requests": {
      "main": [
        [
          {
            "node": "Put into Ticketing System",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "First Filter for non direct messages or invites": {
      "main": [
        [
          {
            "node": "Second Filter for non direct messages or invites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Second Filter for non direct messages or invites": {
      "main": [
        [
          {
            "node": "Pull body of messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}