{
  "meta": {
    "instanceId": "e4f10bef48753951b827b1628c136c25720855dd405c916d09e788211699198e",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "f0a11df0-de9f-477d-b486-bec8c815060f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1360,
        -80
      ],
      "parameters": {
        "width": 624,
        "height": 848,
        "content": "# 🚀 Slack AI Summary & History Archiver — Quick Start Guide\n\n## 📋 Workflow Overview\nThis workflow manages Slack communications in two ways: interactive AI assistance and automated compliance archiving.\n\n### AI Summarization Assistant\n- 🤖 Get **AI chat summaries** by @mentioning a bot in any channel\n- 👥 Convert Slack user IDs into readable @names in summaries\n### Monthly Compliance Backup\n- 🗄️ **Archive channel history** (e.g. last 30 days) to Google Drive every month\n- 📚 Turn messy chat into clean, structured recap messages\n\n## 🔄 How it works\n### 1️⃣ AI summary flow\n1) You @mention the bot in a channel (e.g.  `@(your bot name) summarize past 3days`)\n2) The workflow reads the request text and decides the time range\n3) It fetches channel history + user info via Slack tools\n4) The AI Agent generates a summary\n5) The summary is sent back to the same Slack channel\n### 2️⃣ Scheduled history archiving flow\n1) On a schedule (e.g. monthly), the workflow loops through channels, exports the last 30 days of messages, converts them to files, and uploads them to a **Slack History** folder in Google Drive\n\n## ✅ Prerequisites\n- A running **n8n** instance (self-hosted or cloud)\n- A configured **Slack App/Bot** with:\n  - Permissions to read channel history & post messages\n  - The bot invited to the channels you want to summarize/archive\n- A **Google Drive** account and a folder for storing archives\n- A configured **DeepSeek (or other LLM)** API key for the AI Agent\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f74fdfac-a014-4cef-bde9-560ffeef8a86",
      "name": "On Slack App Mention Trigger",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -560,
        112
      ],
      "webhookId": "3146a42e-ce91-4867-ae05-5cdbe4f68bee",
      "parameters": {
        "options": {},
        "trigger": [
          "app_mention"
        ],
        "watchWorkspace": true
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "47c73cd6-db74-4f70-acae-f667967351cd",
      "name": "Extract User Prompt Text from Slack Event",
      "type": "n8n-nodes-base.set",
      "position": [
        -336,
        112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4d8c3e47-da48-48a5-9e85-170729682e9f",
              "name": "input",
              "type": "string",
              "value": "={{ $json.blocks[0].elements[0].elements[1].text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "0e0b0b7b-9256-4715-b9a1-2322b7652835",
      "name": "Slack Channel Summary AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        0,
        0
      ],
      "parameters": {
        "text": "={{ $json.input }}",
        "options": {
          "systemMessage": "=You are a “channel message summarization assistant” that works inside Slack. The current time is {{$now}}.\n\nYour goal: Based on commands where users @mention you in a channel, automatically fetch channel messages within a specified time range, organize and summarize them, and output in a format that is easy to read in Slack so the team can quickly grasp the key points.\n\n=====================\n[Tool capability: Slack channel history]\n=====================\n\nYou can call the tool named “Get the history of a channel in Slack” to read messages from the current channel within a specified time range:\n\n- `channelId`: Already preset to the channel that triggered you and usually does not need to be changed.\n- `Return_All`: When you need to summarize a whole period of time, set this to true (returns all messages in the specified time range).\n- `Oldest`: The earliest time (start time) to read from, used to limit the time range.\n- `Latest`: The latest time (end time) to read until, usually set to the current time or a specific cutoff time.\n\nWhen the user @mentions you in the channel and says, for example:\n- “Summarize the last 3 days of discussion”\n- “Show me the key points for this week”\n- “Organize yesterday’s meeting content”\n- “Summarize what everyone talked about in the past week”\n\nYou should follow these steps:\n\n1. Based on the current time {{$now}}, parse the time range described by the user:\n   - “Last X days” → From the current time going back X days up to now;\n   - “Today” → From today’s 00:00 up to now;\n   - “Yesterday” → From yesterday’s 00:00 to the end of yesterday;\n   - “This week” → From Monday 00:00 of the current week up to now;\n   - “Last week” → From Monday 00:00 of last week to the end of last Sunday;\n   - For other similar relative time expressions, do your best to convert them into concrete start and end timestamps.\n\n2. Set the parsed start time as `Oldest` and the end time as `Latest`, then call the “Get the history of a channel in Slack” tool to retrieve channel messages within that time range.\n\n3. Use the messages returned by the tool to perform structured organization and summarization.\n\nIf the user does not clearly specify a time range:\n- By default, interpret it as “the last 1 day” of messages, and set `Oldest` and `Latest` accordingly.\n- If the user only says “Help me summarize the recent messages”, you can briefly explain in your output that you processed it as “the last 1 day”.\n\n=====================\n[Tool capability: User information lookup]\n=====================\n\nYou can call the tool named “Get information about a user in Slack” to look up user information (including id, real_name, display_name, etc.) based on a Slack user ID:\n\n- When you only have user IDs from channel history (for example: `U123ABC456`, `U789DEF012`), but you need to show responsible persons or speakers in the summary, please use this tool according to the rules below:\n  1. Pass the user ID from the message (from the `user` field or from a mention like `<@U123ABC456>`) into this tool.\n  2. In the tool’s response, prefer `profile.display_name`; if that is not available, fall back to `real_name`.\n  3. In the summary, show them in the form `@Name`, for example: `@User_A`, `@User_B`.\n\n- If the tool call fails or there is no suitable name field:\n  - Fall back to Slack’s mention syntax `<@UserID>`, for example: `<@U123ABC456>`.\n  - Do not output a raw bare ID (for example just `U123ABC456`) unless the user explicitly requests it.\n\n=====================\n[Input and context]\n=====================\n\n- `{{$json.input}}` is the original text from the user when they @mention you in Slack; you must use this text to decide whether you need to summarize channel history, and which time range and focus areas to use.\n- Use the conversation memory provided by Simple Memory to keep context consistent within the same channel:\n  - Do not repeatedly ask the user questions if the information can be inferred from memory.\n  - For follow-up questions on the same topic, you can reuse the previously inferred time range or project background.\n\n=====================\n[Summary output requirements: Topic number + Summary + More details + Divider]\n=====================\n\nWhen the user asks you to “summarize / organize / review” channel messages, follow the structure below for your output. The example is purely abstract and must not be copied literally; it only illustrates the layout.\n\nExample format (structure only; do not copy the content literally):\n\n`1. Project planning and deadlines\nA short summary sentence describing the key decisions, agreements, or outcomes related to this topic.\n\nMore details\n• @User_A Short description of an important message related to the deadline\n• @User_B Short description of a key decision or agreement\n• @User_C Short description of an action item or follow-up task\n\n=========================\n\n2. Internal communication process\nA short summary sentence describing the main discussion points and any new rules or processes agreed on.\n\nMore details\n• @User_D Short description of a proposal or suggestion\n• @User_E Short description of a confirmation or agreement`\n\nPlease strictly follow the structure and layout style from the example above, and comply with the following specific rules:\n\n1. Group by topic and label with a sequence number\n- Group related messages into several “topic blocks”, and add an incrementing number in front of each topic title, for example:\n  - `1. Project planning and deadlines`\n  - `2. Internal communication process`\n  - `3. Marketing strategy updates`\n  - `4. Tooling and automation`\n  - `5. Documentation and knowledge base`\n- The sequence number uses Arabic numerals + a dot + a space (for example: `1. `).\n\n2. Topic summary\n- On the line under each “number + title”, write 1–2 sentences summarizing the main points that happened under this topic within the specified time range.\n- Try to include: what happened, which people or teams were involved, and any time information if relevant.\n- You must use at least one emoji per topic to enhance readability.\n\n3. “More details” subsection\n- Below the summary, write a separate line with `More details`.\n- Under that, list key facts related to the topic line by line, one fact per line. The recommended format is:\n  - `• @Name + short description`\n  - Example: `• @User_A Short description of an important message related to this topic`\n- If a topic has very little information (for example, a single sentence is enough to explain it), you may omit the “More details” part.\n\n4. Divider\n- After each topic block, output a single line:\n  - `=====================`\n- Leave one blank line above and below the divider to make it easy to scan inside Slack.\n- After the last topic block, you may choose whether or not to output the divider; both are acceptable, but be consistent in formatting within the same response.\n\n5. Rules for displaying names and responsible persons\n- Prefer to use the retrieved `display_name` or `real_name`, displayed as `@Name`, for example: `@User_A`.\n- If no name can be obtained, use `<@UserID>`, for example: `<@U123ABC456>`.\n- Avoid outputting bare IDs (such as `U123ABC456`) unless the user explicitly requests it.\n\n6. Content selection and filtering\n- Focus on: project collaboration, decisions, task assignments, communication mechanisms, tool usage, training, meetings, and any other work-related information.\n- You may ignore: obvious chit-chat, pure emojis, and content clearly unrelated to work.\n- If there is no content for some potential topic, you do not need to fabricate that topic or add “none”.\n\n7. Formatting details\n- Do not use Markdown syntax such as `**bold**`, `## headings`, or similar.\n- Use plain text, blank lines, and bullet characters (such as `•` or `-`) to structure the content so it is easy to read in Slack.\n\n=====================\n[Other behavioral guidelines]\n=====================\n\n- When critical information is missing and cannot be reasonably inferred (for example, you have no idea which time range to summarize), you may politely ask the user one follow-up question; keep it clear and avoid multiple rounds of questioning.\n- For uncertain or missing information, state directly that something is unclear or needs confirmation; do not fabricate facts.\n- If the user explicitly asks you to respond in a specific language, follow that instruction; otherwise, use the main language used in the channel messages."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "eb49cf72-19b4-444f-a66c-7275a3cb03ed",
      "name": "LLM for Message Summaries",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -144,
        208
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "id": "credential-id",
          "name": "googlePalmApi Credential"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2d1d4e1b-22a6-4aa3-834d-fb36df70a4b9",
      "name": "Channel Conversation Memory Buffer",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        16,
        224
      ],
      "parameters": {
        "sessionKey": "={{ $('On Slack App Mention Trigger').item.json.channel }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 10
      },
      "typeVersion": 1.3
    },
    {
      "id": "7b325314-ea0d-45c4-9082-4e38840b5bc3",
      "name": "Get Slack Channel History for Summaries",
      "type": "n8n-nodes-base.slackTool",
      "position": [
        144,
        224
      ],
      "webhookId": "6754da65-d31c-470b-b345-41f47889f5e7",
      "parameters": {
        "filters": {
          "latest": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Latest', ``, 'string') }}",
          "oldest": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Oldest', ``, 'string') }}"
        },
        "resource": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('On Slack App Mention Trigger').item.json.channel }}"
        },
        "operation": "history",
        "returnAll": true
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b1a5b8f3-806b-431d-84b3-23553f45b2d7",
      "name": "Get Slack User Profile by ID",
      "type": "n8n-nodes-base.slackTool",
      "position": [
        272,
        224
      ],
      "webhookId": "cd2d1c3a-4ec0-4f6b-a47a-856410b20520",
      "parameters": {
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('User', `Slack user ID to look up, for example \"U09MA9742LW\".\nUse the raw ID from messages (the \"user\" field or the ID inside a mention like \"<@U09MA9742LW>\").\nDo NOT pass the person’s name or \"@name\" text here – only the user ID string.`, 'string') }}"
        },
        "resource": "user"
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "9a98ec13-55c3-47ea-b403-67cb99e9c358",
      "name": "Send Summary Message to Slack Channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        480,
        112
      ],
      "webhookId": "afbbbbb2-1aa2-4364-bcb3-6b920a91e46f",
      "parameters": {
        "text": "={{ $json.output }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('On Slack App Mention Trigger').item.json.channel }}"
        },
        "otherOptions": {
          "mrkdwn": true
        }
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c9cb3f44-b909-42c3-9c2b-a92606935d44",
      "name": "Monthly Export Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -608,
        816
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months",
              "triggerAtHour": 1
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f05f4d47-ba61-43ad-8e77-f6ee6a19051f",
      "name": "Get All Slack Channels in Workspace",
      "type": "n8n-nodes-base.slack",
      "position": [
        -384,
        816
      ],
      "webhookId": "80342357-c2c7-4cc7-b4ea-aeda81d76a5c",
      "parameters": {
        "filters": {},
        "resource": "channel",
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "970fdccf-4978-4ea3-955c-bcd4b8936190",
      "name": "Loop Over Slack Channels",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -160,
        816
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "0019590c-c742-46ed-ad69-4b8261d499b5",
      "name": "Get Slack Channel History for Export",
      "type": "n8n-nodes-base.slack",
      "onError": "continueErrorOutput",
      "position": [
        64,
        672
      ],
      "webhookId": "91ded22c-05c3-4a73-8953-0ccba9fcaa5d",
      "parameters": {
        "filters": {
          "latest": "={{ $now.format('yyyy-MM-dd HH:mm:ss') }}",
          "oldest": "={{ $now.minus({ months: 1 }).format('yyyy-MM-dd HH:mm:ss') }}"
        },
        "resource": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "operation": "history",
        "returnAll": true
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "bb8ff412-c751-4393-9e47-3d8c7089e73b",
      "name": "Convert Channel History JSON to ",
      "type": "n8n-nodes-base.convertToFile",
      "disabled": true,
      "position": [
        288,
        672
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "80ca7a42-9d8e-4829-982f-84e5f1642d89",
      "name": "Upload Channel History File to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        512,
        752
      ],
      "parameters": {
        "name": "={{ $('Loop Over Slack Channels').item.json.name_normalized }}_{{ $('Monthly Export Schedule Trigger').item.json['Readable date'] }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1HC2J0qPAtDimKCnJik3LYL3aV67z6SsP",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1HC2J0qPAtDimKCnJik3LYL3aV67z6SsP",
          "cachedResultName": "Slack histroy"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "bc2dc562-0e05-4222-b1b5-f2503e011539",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -224
      ],
      "parameters": {
        "color": 6,
        "width": 464,
        "height": 640,
        "content": "## 👂 Event & Context Extraction\n\nCaptures the `app_mention` event from Slack and extracts the user's clean text prompt from the complex message payload to prepare it for the AI."
      },
      "typeVersion": 1
    },
    {
      "id": "173235bc-cbfe-4374-9653-55a2583b3794",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -224
      ],
      "parameters": {
        "color": 3,
        "width": 560,
        "height": 640,
        "content": "## 🧠 AI Agent & Tooling\n\nThe core logic center. The Agent uses Gemini to interpret the request, calls Slack tools to fetch message history and resolve user IDs, and maintains conversation context."
      },
      "typeVersion": 1
    },
    {
      "id": "c9910627-1634-4234-8e85-e6081904f6bf",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        512
      ],
      "parameters": {
        "color": 6,
        "width": 688,
        "height": 496,
        "content": "## 🔄 Scheduling & Iteration\n\nInitiates the workflow on a monthly schedule, retrieves a complete list of workspace channels, and manages the loop to process them one by one."
      },
      "typeVersion": 1
    },
    {
      "id": "91cad3ea-def3-4c84-9a64-96bd802526b8",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        512
      ],
      "parameters": {
        "color": 4,
        "width": 624,
        "height": 496,
        "content": "## 💾 Fetch & Archive\n\nInside the loop, this section retrieves the last month's raw message data for the current channel, converts it into a JSON file, and uploads it to Google Drive."
      },
      "typeVersion": 1
    },
    {
      "id": "41085f58-2ab0-43fe-91f2-9288da9b4594",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 288,
        "height": 640,
        "content": "## 💬 Replay Result\n\nReplay AI summary as like slack pro."
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Loop Over Slack Channels": {
      "main": [
        [],
        [
          {
            "node": "Get Slack Channel History for Export",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM for Message Summaries": {
      "ai_languageModel": [
        [
          {
            "node": "Slack Channel Summary AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Slack User Profile by ID": {
      "ai_tool": [
        [
          {
            "node": "Slack Channel Summary AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "On Slack App Mention Trigger": {
      "main": [
        [
          {
            "node": "Extract User Prompt Text from Slack Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Channel Summary AI Agent": {
      "main": [
        [
          {
            "node": "Send Summary Message to Slack Channel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monthly Export Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get All Slack Channels in Workspace",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Channel History JSON to ": {
      "main": [
        [
          {
            "node": "Upload Channel History File to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Channel Conversation Memory Buffer": {
      "ai_memory": [
        [
          {
            "node": "Slack Channel Summary AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Get All Slack Channels in Workspace": {
      "main": [
        [
          {
            "node": "Loop Over Slack Channels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Slack Channel History for Export": {
      "main": [
        [
          {
            "node": "Convert Channel History JSON to ",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Slack Channels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Slack Channel History for Summaries": {
      "ai_tool": [
        [
          {
            "node": "Slack Channel Summary AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Extract User Prompt Text from Slack Event": {
      "main": [
        [
          {
            "node": "Slack Channel Summary AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Channel History File to Google Drive": {
      "main": [
        [
          {
            "node": "Loop Over Slack Channels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}