1. 为什么 Slack 里的 AI 助手总在“装死”
团队里用 Slack 的人越来越多,消息、告警、CI 通知全堆在频道里。你可能也想过:要是 AI 能直接住进 Slack,@ 一下就能查日志、跑脚本、定时汇总,那该多省事。但真动手时,问题一个接一个冒出来——Bot 收不到消息、回复格式乱码、Agent 跑一半卡死、定时任务不触发、重启后历史全丢。
这些坑我在搭 pi-mom 的时候基本踩了个遍。pi-mom 是 openclaw 底层 pi-mono 架构里负责“让 AI 住进 Slack”的那一层,它把 pi-ai(统一 LLM API)、pi-agent-core(智能体运行时)和 Slack 的 Socket Mode 缝在一起,做成一个能自我管理的 Slack Bot 智能体。所谓“自我管理”,指的是它不靠你手动重启来更新记忆或技能——Agent 自己写文件、自己定闹钟、自己造工具,下一条消息就能用上。
这篇是系列第一篇的第五部分,聚焦 pi-mom 的 Slack Bot 智能体接入与运行验证。我会给你一份可复制的config.toml骨架,把统一 Key/API 通道 TaoToken 的配置方式讲清楚,再带你走一遍启动验证动作。适合已经在用 Slack、想给团队加一个常驻 AI 助手的开发者,也适合正在研究 pi-mono 架构、想搞明白事件调度和沙箱执行怎么落地的人。读完你能在自有环境里复现整个接入流程,而不是只停留在“看懂了”。
2. TaoToken 前置:统一 Key/API 通道怎么接
pi-mom 本身不绑定某一家模型服务,它通过 pi-ai 这一层去调 LLM。pi-ai 的设计是“一套代码调多家模型”,所以你需要一个统一的 Key/API 通道来承接请求。TaoToken 在这里扮演的就是这个通道角色——你拿到一个 Key,配好 base URL,pi-ai 就能把请求发出去,不用在代码里到处写不同厂商的 endpoint。
先明确几个地址,后面配置会用到:
- 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
- API 基址:https://taotoken.net/api
- 模型对话页:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=models
- Coding Plan 页:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan
- 控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console
- API Keys 管理:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
- 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc
- ClaudeCodeAnthropic 接入:https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=claudecode-anthropic
拿到 Key 的流程不复杂:进控制台,在 API Keys 页面创建一个新 Key,复制出来。注意 Key 只在创建时完整显示一次,关掉页面就看不到了,所以先存到安全的地方。如果你还没决定用哪个模型,可以去模型对话页先试几下,确认响应速度和输出风格符合预期,再回到 Coding Plan 页看长期编码场景的额度方案。
注意:Key 不要写进会提交到 git 的文件里。pi-mom 的配置支持从环境变量读取,后面
config.toml里我会用占位符,实际运行时通过环境变量注入。
pi-ai 调用时的 base URL 填https://taotoken.net/api,模型名按文档里列出的写。这里有个容易搞混的点:base URL 后面不要自己加/v1之类的路径,pi-ai 内部会按厂商协议拼接。我一开始手动加了/v1,结果一直 404,排查了半天才发现是路径重复。
3. 可复制配置:config.toml 骨架与 Slack 参数
pi-mom 的配置分两块:一块是 pi-ai 的模型通道,一块是 Slack Bot 的接入参数。下面这份config.toml骨架可以直接复制,把占位符换成你自己的值。
# config.toml — pi-mom Slack Bot 智能体配置骨架 [ai] # 统一 Key/API 通道 provider = "taotoken" base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" # 从环境变量读取,不要硬编码 model = "claude-sonnet-4-20250514" # 按接入文档里的模型名填写 max_tokens = 8192 temperature = 0.3 [slack] # Socket Mode 接入,不需要公网回调地址 app_token = "${MOM_SLACK_APP_TOKEN}" # xapp- 开头 bot_token = "${MOM_SLACK_BOT_TOKEN}" # xoxb- 开头 # 允许 Bot 响应的频道,留空表示所有已加入频道 allowed_channels = ["general", "dev", "ops"] # 是否在线程里展示工具调用详情 show_tool_details = true [sandbox] # docker 模式隔离执行,host 模式仅本地开发用 mode = "docker" container_name = "mom-sandbox" workspace = "./data" [events] # 事件文件监听目录,相对 workspace watch_dir = "events" # 周期事件默认时区 timezone = "Asia/Shanghai" [memory] # 全局记忆文件名 global_file = "MEMORY.md" # 是否每次请求前重新从磁盘读取记忆 reload_each_request = true几个参数值得单独说。api_key用${TAOTOKEN_API_KEY}这种写法,pi-mom 启动时会从环境变量里取,这样配置文件可以安全地放进版本库。model字段要跟接入文档里列出的名称完全一致,大小写和日期后缀都不能错,否则会返回模型不存在的错误。
slack.app_token和slack.bot_token是两个不同的东西。app_token 用于 Socket Mode 建立长连接,bot_token 用于调用 Web API 发消息。两个都要在 Slack App 后台生成,权限范围至少需要chat:write、channels:history、app_mentions:read。Socket Mode 的好处是不需要暴露公网地址,本地开发也能跑。
sandbox.mode建议生产环境用docker。Docker 模式下 Agent 执行的命令都在容器里,即使它手滑跑了rm -rf /,影响的也只是容器,宿主机没事。host 模式方便调试,但风险高,别在正式环境用。
环境变量这样设置:
export TAOTOKEN_API_KEY="你的Key" export MOM_SLACK_APP_TOKEN="xapp-你的AppToken" export MOM_SLACK_BOT_TOKEN="xoxb-你的BotToken"4. 启动验证:从消息到回复的完整链路
配置写好后,先别急着连真实 Slack。pi-mom 的示例目录里有一套离线演示,可以在不配任何 Token 的情况下验证系统提示词构建、事件调度和记忆加载。这一步能帮你确认 pi-ai 通道是通的。
cd examples npm install npm run 06:prompt06:prompt会输出 Docker 模式下的完整系统提示词。你要重点看两处:一是## Environment段里有没有正确显示沙箱模式和工作目录;二是## Memory段里有没有加载出全局记忆和频道记忆。如果这两段是空的,说明reload_each_request没生效或者记忆文件路径不对。
接着验证事件系统:
npm run 06:events这个示例大约跑 14 秒,会依次演示 immediate、one-shot、periodic 三种事件的创建和触发。观察输出里事件文件被写入events/目录后,监听器是否立刻捕获;one-shot 事件到点后是否自动删除;periodic 事件是否按 cron 周期重复触发。如果 periodic 只触发一次就停了,检查schedule字段的 cron 表达式是不是写成了 5 段而不是 6 段。
离线验证通过后,接真实 Slack。启动命令:
./docker.sh create ./data ./docker.sh start mom --sandbox=docker:mom-sandbox ./data启动后看终端日志,正常会输出类似SlackBot connected via Socket Mode和EventsWatcher started on ./data/events两行。然后在 Slack 频道里 @ 一下你的 Bot,发一句“帮我看看当前工作目录下有什么文件”。预期结果是:主消息先显示“正在处理...”,然后 Agent 调用 bash 工具执行ls,线程里出现工具调用详情,最后主消息更新为文件列表。
验证成功的标志有三个:主消息有最终回复、线程里有工具调用记录、终端日志里能看到 token 用量。如果主消息一直停在“正在处理...”,多半是 pi-ai 通道没通,去终端看有没有 401 或 404 报错。
5. 本篇常见错排查
报错一:401 Unauthorized或invalid api key
先确认TAOTOKEN_API_KEY环境变量在当前 shell 里真的存在,用echo $TAOTOKEN_API_KEY看一眼。如果变量名拼错了,或者 Key 复制时带了空格,都会报这个。还有一种情况是 Key 被删了或者过期了,去 API Keys 页面重新生成一个。
报错二:model not found
config.toml里的model字段跟接入文档里的名称不一致。注意有些模型名带日期后缀,比如-20250514,少写一段就找不到。去模型对话页确认一下当前可用的模型名,直接复制过来。
报错三:Slack 里 @ 了 Bot 但没反应
先看终端日志有没有message received之类的记录。如果没有,说明 Socket Mode 没连上,检查app_token是不是xapp-开头、bot_token是不是xoxb-开头,两个别搞反。如果有message received但没有后续,检查allowed_channels里有没有包含当前频道名,频道名不要带#。
报错四:Docker 模式下命令执行失败
docker.sh create之后要确认容器真的起来了,用docker ps看mom-sandbox在不在运行列表里。如果容器没起来,Agent 执行 bash 时会报连接错误。另外 workspace 路径要写绝对路径或者相对于启动目录的正确路径,路径不对会导致挂载失败。
报错五:记忆更新后下一条消息没生效
检查reload_each_request是不是true。如果设成了false,pi-mom 会缓存系统提示词,记忆改了也不会重新读。另外确认 Agent 编辑的是MEMORY.md而不是别的文件,文件名大小写要一致。
报错六:periodic 事件重复触发但每次都发消息
这是[SILENT]机制没生效。周期事件触发后,如果 Agent 判断没有异常,应该回复[SILENT],SlackBot 检测到后删除状态消息、不发内容。如果每次都发“一切正常”,检查 Agent 的系统提示词里有没有包含[SILENT]的说明,或者模型是不是没按约定输出。
6. 下一步:把通道和验证动作固化下来
走到这里,你应该已经能在自己的环境里把 pi-mom 跑起来,看到 Slack 频道里 Bot 的回复和线程里的工具调用详情。整个链路里最关键的两个点,一个是 pi-ai 通过 TaoToken 统一通道调模型,另一个是启动后的验证动作——先离线跑06:prompt和06:events,再接真实 Slack。
如果你在排障阶段卡在接入或 Key 配置上,直接去 API Keys 页面重新生成一个 Key,对照接入文档检查 base URL 和模型名。如果你还没确定用哪个模型,先去模型对话页试几轮,确认输出风格符合团队需求。长期在 Slack 里跑编码类任务、需要 Agent 自己定闹钟和造工具的,可以看 Coding Plan 页的额度方案,把周期事件的频率和模型调用量对上。
我自己的习惯是,每次改完config.toml先跑一遍离线示例,确认系统提示词和事件监听都正常,再启动真实 Bot。这样能把配置错误和 Slack 接入错误分开排查,省掉不少来回试的时间。