n8n AI Workflow 实战:Slack 每日摘要机器人
这篇文章记录了我在贵阳实验室的实战过程。我坚信,在技术下行的时代,程序员唯一的护城河就是通过 AI 建立属于自己的数字资产。
本文解决的问题
- ● 解决了多频道、多线程消息爆炸时,团队成员需要耗费数小时肉眼回溯历史消息的低效问题。
- ● 解决了普通关键字监控频繁误报,无法从日常闲聊中提炼核心决策和待办事项的工程难题。
- ● 提供了完整的 Slack API 授权映射、n8n 消息聚类算法以及防止重复推送的去重设计方案。
适合谁读
- 每天需要跟进多个 Slack 频道、被几百条聊天消息刷屏,急需通过自动化手段解放注意力的项目经理和团队 TL。
- 想要利用开源工具和 AI 落地业务流,但又对商业 API 计费极其敏感,要求极致控制成本的独立项目经理。
- 希望学习如何将自托管 n8n、OpenAI 接口与企业级即时通讯工具进行深度编排的全栈开发者。
协作的本质是异步摘要的艺术
实时在线并不是高效协作的代名词。如果一个团队要求所有成员实时响应各种聊天消息,这实际上是在用碎片化的时间换取虚假的即时感。真正的生产力应该建立在异步信息流之上,即一整天产生的海量讨论,压缩为几分钟就能看完的决策简报。
通过使用自托管 n8n 和 OpenAI 搭建的 Slack 每日摘要机器人,我们实际上是在为团队的沟通链路安装一个语义过滤器。我们将聊天记录视作非结构化数据,用 OpenAI 的推理能力作为事实提炼引擎,而 n8n 则作为编排工具,自动化拉取、清洗、整合、并最终向团队推送今日决策摘要。这样一来,团队成员就不必再去爬几百层的信息楼。
架构设计:信息漏斗与处理管道
在这个实战项目中,我们设计了一个三阶段的处理漏斗,将杂乱的群聊历史转化为结构化的卡片简报:
- 收集阶段:使用定时触发器(Schedule Trigger,例如每天傍晚 6 点)拉取过去 24 小时内指定 Slack 频道的聊天记录。
- 提炼阶段:利用 JavaScript 节点进行噪点清洗,丢弃无意义的简短回复(如 OK、收到等),过滤机器人发送的系统部署通知,并按照频道和 Thread(讨论线索)进行聚合重整。
- 推送阶段:将排版完毕的上下文递给大模型,通过结构化 Prompts 提取出今日决策、待办事项和遗留疑问,最后重新包装为 Slack Block Kit 卡片,发送到专门的通知频道中。
定时拉取与前置噪点清洗
第一步我们需要在 Slack Developer Portal 中创建一个 App,并为其配置 OAuth 凭证。确保拥有 channels:history 和 users:read 等基础权限。
我们在 n8n 中通过 Schedule Trigger 设定每天定时触发。然后,引入 Slack 节点的 History 方法拉取指定频道的数据。
由于原始消息流中包含了大量的系统自动通知(如部署日志、CI 运行成功等)以及一两个字的水群回复,如果直接送入大模型,不仅会浪费大量的 Token,还会干扰模型的提炼精准度。因此,我们需要在 Slack 节点之后,插入一个 Code 节点(使用 JavaScript 语言)进行物理过滤:
const items = $input.all();
const filteredItems = items.filter(item => {
const text = item.json.text || "";
const userId = item.json.user || "";
// 1. 过滤掉长度太短的无意义回复 (如 OK, 1, 收到, get)
if (text.trim().length < 5) return false;
// 2. 过滤掉特定系统账号发送的消息 (根据你的机器人 ID 自行替换)
if (userId === "USYSTEM_BOT_ID") return false;
// 3. 过滤包含典型 CI/CD 部署日志特征的消息
if (text.includes("deployment successful") || text.includes("Build completed")) return false;
return true;
});
return filteredItems;
这段前置过滤在物理层面上帮我们拦截了大约百分之六十的无价值噪音,大大降低了后置大模型的推理负担。
多线程聚合与上下文排序
在 Slack 的聊天场景中,大量的讨论是基于某个特定 Thread(回复线程)进行的。如果我们将消息按时间戳线性平铺送给大模型,模型会丢失对话的归属关系,误以为不相干的消息具有上下文关联。
因此,我们需要在进入大模型前,通过 JavaScript 将零散的消息流聚合为「频道 - 主讨论 - 回复线程」的嵌套树状结构,以保持上下文的连续性:
const messages = $input.all().map(i => i.json);
const threads = {};
// 将属于同一个 parent_message_ts 的消息聚合到一起
messages.forEach(msg => {
const threadTs = msg.thread_ts || msg.ts;
if (!threads[threadTs]) {
threads[threadTs] = [];
}
threads[threadTs].push(`${msg.user_name || msg.user}: ${msg.text}`);
});
// 格式化输出为适合大模型阅读的文本块
const formattedContext = Object.keys(threads).map((threadTs, index) => {
return `[Thread #${index + 1}]\n${threads[threadTs].join('\n')}`;
}).join('\n\n');
return { json: { chat_history: formattedContext } };
经过处理后,非结构化的消息变为了逻辑分明的对话单元,方便大模型精准跟踪讨论的演进过程。
大模型决策提炼与 JSON 格式化
我们将提炼整理好的格式化文本传入 OpenAI 节点。这里推荐选择 gpt-4o 或是 gpt-4o-mini。我们将 Temperature(温度)设置为 0.1。较低的温度能确保大模型只进行事实归纳,拒绝生成任何天马行空的编造。
我们的 Prompt 需明确要求模型只提取以下三类核心信息,并以强约束的 JSON 格式输出:
你是一个资深项目秘书。请阅读以下 Slack 对话历史,提取出今日的以下事实:
1. decisions:达成的核心决定或共识。
2. action_items:分配的待办任务,必须明确执行人和具体任务。
3. open_questions:仍然悬而未决、需要后续讨论的疑难问题。
你必须只输出符合以下格式的合法 JSON:
{
"decisions": ["决策一", "决策二"],
"action_items": ["任务一 (执行人: 小张)", "任务二 (执行人: 小李)"],
"open_questions": ["问题一"]
}
为了确保输出的格式百分之百不会因为模型的标点抽风而解析失败,建议开启 n8n OpenAI 节点的 JSON Schema 强约束选项,在底层直接限制模型的输出结构。
卡片组装与 Slack 自动推送
在获得结构化的 JSON 结果后,我们可以直接使用 n8n 的 Slack 节点,调用 Post Message 方法。为了让版面看起来高雅大方,我们应当配置 Slack 的 Block Kit(区块套件)进行卡片排版。
我们可以将 JSON 拼装为多段的 Layout Blocks,比如用不同的颜色条区分决策(绿色)、待办(橙色)和待讨论项(灰色),最终推送至团队公共的 每日早报 频道。这不仅实现了数据沉淀,更让团队成员每天下班前只需花费十几秒,就能迅速同步所有项目的实际进展。
常见坑与生产环境报错 (Error Logs)
1. 报错:接口限流
Error: Request failed with status code 429 (Too Many Requests)
原因:由于你的工作流瞬间拉取并处理了大量频道,超出了 Slack API 的高频调用额度限制。 解决方法:在获取频道历史消息的节点之间插入一个 Wait 节点(设置为等待 500 毫秒),对并发网络请求进行物理削峰,即可平稳度过限流阈值。
2. 报错:上下文超出最大长度限制
Error: context_length_exceeded
原因:当遇到某些研发频道在一天内产生了上万条刷屏讨论时,直接打包会把大模型的 Context 窗口直接撑满。 解决方法:首先在 Code 节点中配置最大字符限制(如只保留最新 5000 字符),或者采取「频道分块初筛」策略,先用小模型把各频道的无意义闲聊精简过滤后,再将精炼结果递交给主模型生成总摘要。
自建 n8n 方案 vs Slack 官方内置 AI 的对比 (Comparison)
在为团队搭建信息简报工具时,我们需要评估自建方案与同类内置工具在各个物理维度上的差异:
| 比较维度 | n8n + OpenAI 自建方案 | Slack 原生 AI 功能 | 手工轮值整理 |
|---|---|---|---|
| 数据隐私保护 | 极高,聊天内容在自托管 NAS/VPS 本地处理 | 一般,需要授权商业云服务进行语料处理 | 绝对安全 |
| 规则自定义程度 | 极高,支持编写任意 JS 清洗规则和 Prompt 框架 | 较低,仅能使用官方预设的摘要模板 | 极高 |
| 运行资源成本 | 极低,仅需支付大模型 API 消耗的少量 Token 费 | 高昂,必须升级至 Slack 昂贵的企业版订阅 | 极极高的时间成本 |
| 复杂场景适应 | 可跨多频道聚合,可关联 Notion 并导出为表格 | 仅支持单频道或单 Thread 的局部摘要 | 适应度高但低效 |
通过对比可以看出,使用自托管 n8n 的核心优势在于对数据的绝对控制权和极致的性价比。我们无需为团队每人支付高昂的企业版月租,就能享受到媲美专业助手的信息过滤服务。