先说结论
这个飞书私聊助手已经实际使用了好几个月。它最初只是一个方便在手机上随手记录和提问的入口,真正让它值得单独写下来的,是长期使用过程中逐渐暴露出来的权限边界问题。
让模型「少做危险的事」做不到,锁死「它能碰到的范围」可以。
这个项目把 Pi Agent 接到飞书私聊,但真正花功夫的不是接入,而是边界:工作区固定、path 参数过检、bash 命令拦截三道防线,全部在工具层完成,不依赖模型的自觉。
它和常见的 Code Agent、Assistant 不在一个赛道:响应快,适合随手用,比如记点子。
目录
- 1. 它适合什么场景
- 2. 手机上的 Agent 入口
- 3. 第一道门:工作区固定
- 4. 第二道门:path 参数过检
- 5. bash:最难的一关
- 6. 会话与命令
- 7. mock:不连飞书也能验
- 8. 收个尾
1. 它适合什么场景
这个助手的定位不是「主力开发者」,而是「随手可用的帮手」。
和 Code Agent 那种一跑十几分钟、一个完整任务的调性不同,它坐在飞书私聊里,反应速度非常快,所以适合那些不值得开一个正式任务的小事:
- 某个时刻脑子里冒出一个点子,想快速记下来——发一句「记一下:XX」,它写进 NOTE。
- 一个简单问题、一段临时文本整理,随手问随手答。
- 不用切换终端、不用打开 IDE,手机上和办公聊天混在一起顺手完成。
场景越小、越临时,它越显得顺手。简单任务交给快助手,重磅活再开 Code Agent,这是这套组合的用法。
2. 手机上的 Agent 入口
个人 Agent 平时在终端里用,想随手用就缺一个手机入口。IM 私聊是最省事的选择:飞书私聊文本消息接入 Pi Agent,每个用户保留自己的 session,默认继续上一次对话。
但接入本身不值钱,值钱的是边界——不解决边界问题的接入,等于给模型开了一个远程终端。
3. 第一道门:工作区固定
Pi SDK 的工具支持创建时绑定目录:
1 | read / write / edit / grep / find / ls → 全部绑定 NOTE_DIR |
工具从出生起就只知道一个目录,模型无法通过参数把工作范围挪到外面。
提示词里写「请只改 NOTE」是软约束,模型不一定听;工具绑定才是硬约束。
4. 第二道门:path 参数过检
文件类工具大多有一个 path 参数。包一层守卫:执行前把 path 解析成绝对路径,仍在 NOTE_DIR 内才放行,越界直接抛错:
1 | guardPathTool(execute) → 先检查 path → 通过后才转调原始工具 |
关键细节是判断「在目录内」用 path.relative,而不是 startsWith。子串前缀不等于目录前缀——startsWith("/tmp/a") 会把 /tmp/abc 也当成 /tmp/a 的内部文件。
5. bash:最难的一关
bash 没有 path 参数,路径藏在命令文本里,静态审计做不到完备。这关只能做折中:
主防线是 cwd——bash 创建时就固定在 NOTE_DIR,模型 cd 不出去就动不了外面。
辅助防线是正则拦截明显越界:../ 父目录引用、cd / 绝对路径、cd ..、rm / mv / cp 指向外部路径、cat / sed / awk / head / tail 读外部路径。
明说清楚:这不是通用沙箱,能拦住明显风险;要更强隔离得上容器,第一版不追求。
6. 会话与命令
以飞书用户(open_id)为粒度维护会话:Pi 端保存完整 JSONL 对话,助手自己只存一份轻量索引(当前 session + 历史列表),两者职责分开。
索引损坏时直接抛错,而不是悄悄覆盖——丢失映射最多新建一个,静默弄丢映射才是坏情况。
slash 命令只做六个:/help /new /list /current /resume /stop,未知的 /xxx 不猜。/help 的输出刻意保持简短——手机屏幕上没人想看长文。
7. mock:不连飞书也能验
本地验证是另一个容易忽视的工程点:
1 | npm run mock:send -- "/help" |
mock 入口绕开真实飞书 SDK,但完整走 AssistantService、命令路由、session 管理和 Pi Runtime。测试同理,通过注入 fake runtime 不依赖真实模型和网络。
接入层和业务层分离之后,边界逻辑可以在没有 IM、没有模型的情况下全部验证。
8. 收个尾
| 层 | 手段 | 性质 |
|---|---|---|
| 提示词 | 「请只改 NOTE」 | 软约束,模型可能不听 |
| 工具绑定 | 创建时绑定 NOTE_DIR | 硬约束 |
| path 过检 | 执行前解析并校验 | 硬约束 |
| bash | cwd 固定 + 正则拦截 | 折中,拦明显风险 |
多数 Agent 框架内置了权限与工具隔离能力,但默认往往是全开。接入之前先问「它能碰什么」,比接入之后救火便宜得多。
