
1. 为什么“会主动干活的 AI”和普通 Slack 机器人是两回事Slack 里塞个机器人这件事本身早就不新鲜了。Webhook 一挂关键词一匹配定时任务一跑一个“机器人”就诞生了。但 company-brain 这个项目在 GitHub 上被推荐恰恰是因为它踩中了一个很多人没想明白的分界线被动响应和主动干活是两种完全不同的系统设计。普通的 Slack 机器人本质是一个“问答机”。你 它它回你你发指令它执行。它的行为边界完全由人的输入决定没有人触发它就安静地躺在频道里。而 company-brain 想做的事情是让 AI 自己去“看”团队在 Slack 里产生的信息流自己去判断哪些事情需要跟进然后主动把活干了——比如整理讨论结论、追踪待办事项、在合适的时间提醒相关的人。这个差别听起来只是“主动”两个字但落到工程实现上是架构级别的差异。被动机器人只需要一个事件监听器加一个回复函数主动系统需要持续的状态感知、任务队列、去重机制、权限边界以及最关键的——它得知道“什么时候不该动”。一个乱说话的主动 AI 比一个不干活的被动机器人危险得多。我之所以对这个项目感兴趣是因为它把“主动”这件事拆得比较克制。从项目描述和关键词来看它没有走“全自动接管一切”的激进路线而是聚焦在团队协作场景里那些高频、低风险、但确实消耗人精力的环节。这个定位很聪明因为团队协作里真正让人烦的往往不是需要决策的大事而是“谁说了什么、下一步谁做什么、什么时候该跟进”这类琐碎但必须有人记住的信息。适合读这篇内容的人大概分三类一是正在给团队搭内部工具、想看看别人怎么设计主动式 AI 的工程师二是对 MCP 协议和 Cloudflare Workers 这套组合感兴趣、想找个真实项目参考的开发者三是单纯好奇“AI Agent 到底怎么落地到日常协作里”的产品或技术负责人。不管你是哪一类下面我会把这类系统的核心逻辑、技术选型理由、以及实操中真正会踩的坑一层层拆开讲。2. company-brain 的核心机制它到底“主动”在哪里2.1 从“消息流”到“任务流”的转换逻辑要理解 company-brain 的主动能力得先理解它处理的信息形态。Slack 里的消息是线性的、碎片化的、充满噪音的。一个人在频道里说“这个方案我觉得可以但需要确认一下预算”这句话对人来说信息量很清楚但对机器来说它既不是明确的指令也不是结构化的数据。company-brain 的核心动作是把这种非结构化的消息流转换成结构化的任务流。这个过程大致分三步感知、判断、行动。感知层负责持续监听指定频道或线程的消息判断层用 AI 模型去识别消息里是否包含“待办、决策、承诺、问题”这四类信号行动层则根据判断结果决定是记录、提醒、还是生成一条新的跟进消息。这里有个关键设计点值得注意它没有试图理解所有消息而是只抓那四类信号。这个取舍非常重要。我见过不少团队做类似工具时一上来就想让 AI “理解整个对话”结果要么误报率高得离谱要么模型成本压不住。company-brain 的做法更像是给 AI 划了一个明确的狩猎范围——只盯那几种它擅长识别的模式其余的一律放过。2.2 主动行为的触发条件与抑制机制“主动”最怕的是变成“骚扰”。一个 AI 如果每隔十分钟就在频道里冒出来提醒你“你还有个任务没做”团队很快就会把它静音。所以主动式系统的真正难点不在于“能不能触发”而在于“什么时候抑制触发”。从项目的设计思路来看它至少考虑了几层抑制机制。第一层是去重同一条消息不会被反复处理同一个任务不会被反复提醒。第二层是时效窗口不是所有待办都需要立刻跟进有些可以等到当天结束前汇总。第三层是上下文判断如果一条消息后面紧跟着有人回复“已经处理了”那这个任务就不应该再被激活。这三层机制背后其实是一个朴素的工程原则主动系统的默认状态应该是“不动”只有在置信度足够高的时候才动。这和被动系统正好相反被动系统的默认状态是“待命”有人来才动。这个思维转换是很多人在做 AI Agent 时容易忽略的。2.3 为什么用 Cloudflare Workers 而不是传统服务器关键词里出现了 Cloudflare Workers这不是随便选的。Slack 的事件订阅机制要求你的服务端能快速响应 HTTP 请求而 Cloudflare Workers 的边缘计算特性天然适合这种场景冷启动几乎为零全球分布按请求计费。更重要的是Workers 的无状态特性逼着开发者把状态管理外置。company-brain 需要记住“哪些消息处理过了”“哪些任务还开着”这些状态不能放在 Worker 的内存里必须落到 KV、D1 或者外部数据库。这个约束看起来是麻烦实际上是好事——它让系统天然具备水平扩展能力也不会因为某个实例重启就丢失状态。我自己的经验是用 Workers 做这类事件驱动型 Agent最大的坑不在计算逻辑而在超时和重试。Slack 要求你的 endpoint 在 3 秒内返回 200否则会重试。如果你的 AI 判断逻辑是同步调用的很容易超时。所以正确的做法是Worker 收到事件后立刻返回 200把实际处理逻辑丢到队列或者异步任务里。这个模式在项目里应该是标准操作但新手很容易在这里翻车。3. MCP 协议在其中的角色不是噱头是解耦手段3.1 MCP 到底解决了什么问题MCP 这个词最近热度很高但很多人对它的理解停留在“又一个协议”的层面。放到 company-brain 这个场景里MCP 的价值其实很具体它让 AI 的能力扩展和主业务逻辑解耦。假设 company-brain 需要访问团队的 Notion 文档、查询 Jira 任务状态、或者读取 Google Calendar 的日程。传统做法是在代码里硬编码这些集成每加一个数据源就要改一次核心逻辑测试和部署成本都很高。MCP 的思路是把这些外部能力封装成标准的“工具”AI 通过统一的协议去调用主逻辑不需要知道背后是 Notion 还是 Jira。这个解耦带来的直接好处是可替换性。今天用 Notion明天换 Confluence只要 MCP Server 的实现换掉就行company-brain 的核心判断逻辑一行不用改。对于团队内部工具来说这种灵活性比性能优化更重要因为内部工具的需求变化往往比外部产品更快。3.2 MCP Server 的接入方式与常见误区从热搜词里能看到不少人在问“codex 接入 figma mcp 怎么授权”“codex 无法找到 mcp”这类问题说明 MCP 的实际接入还是有门槛的。在 company-brain 的语境下接入一个 MCP Server 大致需要确认三件事传输方式、认证方式、工具描述。传输方式上MCP 支持 stdio 和 HTTP 两种。Cloudflare Workers 环境里显然只能用 HTTP 方式因为 Worker 里没有本地进程可以 spawn。认证方式则取决于目标服务有的是 API Key有的是 OAuth。工具描述是最容易被忽略的——MCP Server 暴露的每个工具都需要有清晰的名称和参数说明否则 AI 在决定调用哪个工具时会犯迷糊。我踩过的一个坑是工具描述写得太模糊比如一个工具叫“get_data”参数叫“query”AI 根本不知道这个工具是查什么的结果要么不调用要么乱调用。后来改成“search_project_tasks”加明确的参数说明命中率立刻上来了。这个细节在官方文档里往往一笔带过但实际影响很大。3.3 多 AI 协作场景下的 MCP 编排热搜词里还有“多 AI 协作”和“mcp 协议”这两个放在一起其实指向一个进阶场景当 company-brain 需要同时调用多个 AI 能力时MCP 能不能作为编排层。我的判断是MCP 本身不是编排协议它更像是“能力接口标准”。真正的编排逻辑还是得在 company-brain 自己的代码里做。比如一个任务需要先让模型 A 做摘要再让模型 B 做分类最后调用 MCP 工具写入数据库这个流程的控制权在主程序手里MCP 只负责最后那一步的工具调用。不过 MCP 的标准化确实让编排变得简单了因为每个工具的调用方式一致主程序可以用统一的循环去处理“调用工具、拿结果、决定下一步”这个模式。如果没有 MCP每接一个外部服务都要写一套适配代码编排逻辑会被各种异构接口搞得非常臃肿。4. 从零复现一个最小可用版本的关键步骤4.1 环境准备与 Slack App 配置如果你想自己跑一个类似 company-brain 的东西第一步不是写代码而是把 Slack App 配好。这个过程有几个容易卡住的点。首先是在 Slack API 后台创建 App然后开启Event Subscriptions。你需要提供一个 Request URL这个 URL 就是你的 Cloudflare Worker 地址。Slack 会先发一个 challenge 请求来验证 URL 的有效性你的 Worker 必须正确响应这个 challenge否则保存不了。其次是权限范围Scopes。company-brain 这类应用至少需要channels:history读频道消息、chat:write发消息、users:read识别用户这几个。如果你要读私有频道还得加groups:history。权限给少了功能跑不起来给多了审核麻烦建议按最小必要原则来。最后是安装 App 到工作区拿到 Bot Token。这个 Token 要存到 Cloudflare 的环境变量里不要硬编码在代码中。Workers 的环境变量通过wrangler secret put命令设置这样不会出现在代码仓库里。4.2 Worker 里的事件处理骨架Worker 的入口逻辑其实不复杂核心就是“验证请求来源、快速返回、异步处理”。下面是一个简化的骨架用 JavaScript 写export default { async fetch(request, env, ctx) { const body await request.text(); // 验证 Slack 签名防止伪造请求 const isValid await verifySlackSignature(request, body, env.SLACK_SIGNING_SECRET); if (!isValid) { return new Response(Unauthorized, { status: 401 }); } const payload JSON.parse(body); // 处理 URL 验证 challenge if (payload.type url_verification) { return new Response(payload.challenge, { status: 200 }); } // 异步处理事件立刻返回 200 ctx.waitUntil(handleEvent(payload, env)); return new Response(, { status: 200 }); } };这里ctx.waitUntil是关键。它让 Worker 在返回响应之后还能继续执行异步任务避免了 Slack 的超时重试。如果你把handleEvent直接 await 在返回之前一旦 AI 调用耗时超过 3 秒Slack 就会认为失败并重发事件导致重复处理。4.3 AI 判断层的提示词设计要点判断一条消息是否包含待办或决策信号靠的是提示词。这里的设计直接决定误报率。我的经验是提示词里一定要给正例和反例而不是只描述规则。比如不要只写“判断消息是否包含待办事项”而是写成“以下情况算待办明确指派给某人的任务、带有时间节点的承诺、需要后续跟进的问题。以下情况不算闲聊、已经完成的陈述、纯信息分享。”然后给两三个具体例子。这样模型输出的稳定性会高很多。另外输出格式要强制结构化。让模型返回 JSON包含is_task、confidence、assignee、deadline这几个字段。confidence 低于某个阈值比如 0.7的直接丢弃不要犹豫。宁可漏掉一些也不要让低置信度的判断触发主动行为。4.4 状态存储与去重实现去重是主动系统的生命线。最简单的做法是用 Cloudflare KV 存一个已处理消息的 ID 集合处理前先查一下。但 KV 是最终一致的高并发下可能有窗口期。更稳妥的是用 D1Cloudflare 的 SQLite建一张表用消息 ID 做唯一索引插入冲突就说明处理过了。任务状态的管理也类似。每个被识别出的任务应该有一个状态字段open、reminded、done、ignored。主动提醒只针对open状态且超过一定时间的任务。当检测到相关消息里有人回复“搞定”“已完成”时把状态改成done。这个状态机不需要复杂但必须有否则系统会失去对“什么该提醒、什么不该提醒”的控制。5. 实操中最容易翻车的几个地方5.1 误报比漏报更致命这是我在做类似系统时最深的体会。漏报一个任务顶多是团队少了一个提醒人自己还能记住。但误报一个任务AI 在频道里 了不该 的人或者把一个玩笑话当成正式承诺那尴尬是公开的团队对系统的信任会迅速下降。所以调优的方向应该是先把置信度阈值调高确保几乎不误报再慢慢往下调。而不是一上来就追求高召回率。company-brain 这类工具的价值在于“可靠地处理一部分”而不是“试图处理全部”。一个只处理 30% 但从不犯错的系统比一个处理 80% 但经常添乱的系统有用得多。5.2 Slack 的消息格式和线程逻辑比想象中复杂Slack 的消息不是纯文本。它有 blocks、attachments、threads、edited messages、bot messages 等各种形态。你在处理事件时如果不区分消息类型很容易把机器人自己发的消息也当成用户输入来处理形成死循环。线程逻辑也要注意。一条消息如果是在 thread 里回复的它的上下文和主频道消息完全不同。company-brain 需要判断这个回复是对某个任务的确认还是一条新的独立信息这个判断如果做不好要么漏掉确认信号要么把无关回复当成新任务。5.3 成本控制别让 AI 调用失控每次消息事件都调用一次大模型成本会随着团队活跃度线性增长。一个几十人的团队一天几千条消息如果每条都过一遍模型费用不容忽视。实际做法应该是分层过滤。先用轻量规则关键词、消息长度、是否 了人做初筛只有通过初筛的消息才送进模型。这样能砍掉大部分噪音模型调用量可能降到原来的十分之一。另外对于同一线程里的连续消息可以合并成一次调用而不是逐条处理。5.4 权限边界AI 能看什么、能做什么这是团队协作场景里最敏感的问题。company-brain 需要读频道消息但应该只读它被明确邀请进入的频道而不是全工作区。它需要发消息但应该只在特定频道或者通过 DM 发而不是到处 人。从工程角度这些边界要在 Slack App 的权限配置和代码逻辑两层都做限制。权限配置是硬边界代码逻辑是软边界。不要只依赖代码里的 if 判断因为一旦有 bug硬边界还能兜底。6. 这类主动式 AI 工具的扩展方向6.1 从“提醒”到“预填”主动生成草稿company-brain 目前的能力偏向“识别和提醒”但同样的架构可以往前再走一步不只是提醒你有个任务而是直接生成一个草稿。比如识别到“需要确认预算”这个待办后AI 可以自动起草一条给财务的消息你只需要审核和发送。这个扩展的技术难点不在生成而在上下文收集。要生成有用的草稿AI 需要知道这个任务的来龙去脉、相关的人是谁、之前的讨论结论是什么。这要求系统不只是处理单条消息还要能回溯线程历史和相关频道。MCP 在这里又能派上用场——通过 MCP 工具去拉取相关的文档和记录。6.2 跨频道的信息聚合团队大了之后同一个项目的信息会散落在多个频道里。company-brain 可以做一个“项目视图”把分散在不同频道的相关消息聚合起来定期生成一份摘要。这个功能对管理者特别有用因为他们往往没时间翻遍所有频道。实现上这需要给消息打上项目标签。标签可以来自频道名称、消息里的关键词、或者 AI 的分类判断。聚合逻辑则是按标签查询、按时间排序、生成摘要。这个功能的挑战在于标签的准确性如果标签打错了聚合出来的摘要就是误导。6.3 与外部工具的深度集成通过 MCPcompany-brain 可以接入任务管理工具、文档工具、日历工具。比如识别到一个带 deadline 的任务后自动在任务管理工具里创建一条记录或者识别到会议决策后自动更新项目文档。这里要注意的是双向同步的问题。如果 company-brain 在 Slack 里创建了任务用户在任务管理工具里把它标记为完成Slack 这边应该同步更新状态。否则两边状态不一致用户会困惑。MCP 工具需要支持读和写两个方向而且要有冲突解决策略。7. 我实际搭这类系统时的一些体会搭过几个类似的内部工具之后我最大的感受是主动式 AI 的价值不在于它多聪明而在于它多可靠。一个能稳定处理 20% 明确任务的系统比一个号称能理解一切但经常出错的系统在团队里的存活率高得多。另一个体会是关于“克制”。做这类工具的时候很容易被“AI 能做什么”带着跑恨不得把所有能力都塞进去。但真正上线后你会发现用户最需要的往往就是那么一两个场景的自动化。company-brain 聚焦在 Slack 内的任务识别和跟进这个范围选得好因为 Slack 本身就是团队信息流转的核心节点在这里做文章投入产出比最高。技术选型上Cloudflare Workers 加 MCP 这套组合对于中小团队来说是很务实的。Workers 的成本低、部署简单MCP 让集成变得标准化。如果你正在考虑给团队做一个类似的工具我的建议是先从最小闭环开始只处理一个频道、只识别一种信号、只做一种动作。跑通了再逐步扩展比一上来就设计一个大而全的系统要靠谱得多。最后分享一个细节在提示词里加上“如果不确定返回 false”这句话能显著降低误报率。模型天生倾向于“找到点什么”你需要明确告诉它“找不到也是可以接受的”。这个小小的调整在实际使用中带来的稳定性提升比换一个更强的模型还明显。