做 AI 智能体的人,几乎都在同一个地方栽过跟头:会话一长,模型就开始忘事。为了让它记住,大家的第一反应是加一个向量库。这个方案听起来天经地义,直到有人在真实数据上把它跑了一遍。
字节跳动的 DeerFlow 就是这么干的,而且它做了一件开源项目很少做的事——把一次花钱跑出来的负结论原样放进了仓库。在那份实验里,最朴素的摘要方案答对 22.5%,换成关键词回查能答对 90%,而再叠一层向量检索反而掉到 85%。
先说它到底是什么
一句话:DeerFlow 是一个跑在 LangGraph 之上的超级智能体外壳(harness,也就是把大模型、工具、记忆和沙箱串起来干活的那一层)。
真正干活的不是它自己,是一个主智能体——它负责把任务拆开,分给子智能体;需要记忆就去查记忆,需要跑代码就开沙箱(一个关起来跑、碰不到宿主环境的独立进程),需要特定能力就加载一个「技能」。
它的体量是这样的:
| 部分 | 装什么 | 实测规模 |
|---|---|---|
| 后端主体 | 网关、接口、运行时 | 5.2 万行 Python |
| 智能体外壳 | 技能、子智能体、沙箱、记忆 | 16.3 万行 Python |
| 后端测试 | 离线跑的单测 | 43.7 万行,974 个测试文件 |
| 前端 | 网页界面 | 9.3 万行 TypeScript |
| Python 合计 | 含以上各项 | 66.5 万行 |
而这些数字都不是我想写它的理由。它最特别的地方是:它不靠模型来管技能质量。
它给技能设了一道机器闸门——一个纯粹按规则跑的审查器,把技能包当成不可信的数据读一遍,逐条出告警,全程不调用任何模型。这件事在同类项目里很少见:绝大多数「技能」仓库的质量靠作者自觉,或者靠一次人肉 review。
我把这道闸门跑了一遍
先交代环境。一切都跑在评测沙箱里,被测对象落在沙箱工作目录,宿主目录被临时文件系统盖住,全程没碰生产机上的凭证。闸门的入口是一条命令行,按技能目录读,输出机器可读的检查结果。
第一遍:23 个官方技能全量扫描。
| 严重度 | 条数 |
|---|---|
| 阻断项(blocker) | 0 |
| 错误(error) | 6 |
| 告警(warning) | 229 |
| 提示(info) | 3 |
229 条告警压得很不均匀:体量最大的「技能创建器」一个技能占了 59 条,图表可视化 28 条,PPT 生成 18 条。23 个技能里,只有 3 个一条告警都没有,其中一个就是审查器自己。
按规则名拆开看,整轮扫描出的 238 条结论其实只出自 7 类规则:
| 规则 | 条数 | 严重度 | 在说什么 |
|---|---|---|---|
resource.missing |
155 | 告警 | 正文引用的文件在包里不存在 |
resource.unreferenced |
46 | 告警 | 包里有文件,但没被任何地方引用 |
resource.escaping-link |
24 | 告警 | 链接写法会跳出包的范围 |
network-cleartext-http |
4 | 告警 | 内容里出现非本机的明文 HTTP 地址 |
network-local-http |
3 | 提示 | 引用了本机地址 |
python-subprocess |
4 | 错误 | 技能里的脚本调用了外部命令 |
secret-env-assignment |
2 | 错误 | 类密钥的赋值里填的是真值 |
前三类加起来 225 条,占了 229 条告警的 98%,全是同一件事:技能正文或正文引用的文件里,指向了一个不存在或没被用上的资源。这不算大事,但它是「文档没跟上功能改动」的典型形态。真正值得看的是那 6 条错误。
第二遍:按它自己 CI 的判定规则重新跑一次。
它的持续集成里有一条专门的技能审查流水线。规则写在脚本里:命中阻断项或错误项就算失败,除非该条目在豁免清单里。豁免清单是一份带到期日的文件,每条都要写明文件指纹和豁免理由——我数了一下,整份清单里只有 2 条,都属于同一个技能,到期日都是 2027 年 2 月 28 日。
| 技能 | 错误 | 其中已豁免 | 判定 |
|---|---|---|---|
| 技能创建器 | 4 条 | 2 条(豁免到 2027-02-28) | 失败 |
| 数据分析 | 2 条 | 0 条 | 失败 |
| 审查器自己 | 0 条 | —— | 通过 |
两份没被豁免的错误,原因一样:技能里的脚本调用了外部命令。中间那两条豁免也是同一个原因,作者在豁免理由里写清了「命令是固定的、参数是列表形式、不走 shell」。技能创建器另外两条错误则是密钥格式的赋值写进了正文和参考文件。
也就是说,按它自己写下的规则,这 23 个技能里有 2 个过不了自己的闸门。而它们恰好是「造技能」和「分析数据」——最容易被用户直接点开的那两个。
第三遍:这道闸门到底抓得住什么。
评价一个审查器,不能只看它漏什么,也要看它抓什么。我照它的规则造了 5 个技能包,每个只埋一个典型风险,看它报不报:
| 我埋进去的东西 | 它的反应 |
|---|---|
| 安装脚本里用管道把远程脚本喂给 shell | 报了,错误项 shell-curl-pipe-shell |
| 同上,但中间插了提权命令和参数绕一下 | 也报了,规则没被绕过去 |
配置文件里写死一个 sk-live- 开头的密钥 |
报了,错误项 secret-env-assignment |
环境变量文件里写 REVIEWER_SECRET= 加真值 |
报了,同一条规则 |
脚本里读 /etc/passwd |
报了两条:敏感路径 + 调用外部命令 |
5 个中了 5 个,包括加了提权命令的那种明显绕法。这道闸门比我预期的靠谱——它的规则是逐条照着真实绕过手法配了测试的,比如管道后面接 sudo 再跟参数再跟 shell 这种写法,专门有一组用例盯着。
一个我自己撞出来的问题。
闸门有个读取限额(默认是 4096 个文件、单文件 64 MB、总量 512 MB),超了就只读一部分。我把总量限额压到 10 字节再跑,出现两件连锁的事:
| 状态 | 包指纹 |
|---|---|
| A 包完整读取 | sha256:50cc6e88… |
| B 包完整读取 | sha256:abd89407… |
| A 包被截断 | sha256:e3b0c442… |
| B 包被截断 | sha256:e3b0c442… |
两个内容完全不同的技能包,在截断之后拿到了同一个指纹。而这个 e3b0c442… 恰好就是「空内容」的哈希值。同时它还会报一条「包根目录没有 SKILL.md」的阻断项——文件其实好好躺在那里,只是没被读到。
这个设计本身能理解:没读到就没法算。但指纹在报告里的作用是标识「我审的是哪一个包」,它还被写进审查结论里当锚点。截断状态下这层含义就没了,而两台机器上读到不同内容却拿到同一个指纹,也不是不可能。
最有价值的证据,是它自己那份失败报告
仓库里有一份任务接续实验的完整报告,结论是负的。
背景是这样的:智能体干长任务时,对话历史会被反复压缩,压完就丢细节。这份实验拿公开的记忆问答数据集取 42 道题,比较四种方案在「压完还能不能答对」上的差别:
| 方案 | 答对 | 正确率 |
|---|---|---|
| 只有滚动摘要 + 近期消息 | 9 / 40 | 22.5% |
| 摘要再加一份工作笔记 | 11 / 40 | 27.5% |
| 摘要再加关键词回查 | 36 / 40 | 90.0% |
| 再加一层向量混合回查 | 34 / 40 | 85.0% |
从摘要换到关键词回查,正确率涨了 67.5 个百分点;在这之上再叠一层向量检索,反而掉了 5 个百分点。那 42 道题里有 2 道因为接口断连没跑完,所以分母是 40。
它自己在报告里把话说得很克制:这 5 个百分点是「1 例新增正确、3 例新增错误」,配对检验的 95% 置信区间横跨零点,不能据此断言向量总体是负收益——但同样拿不出正收益的证据。所以结论是「不支持默认引入向量检索」,回查能力应该做成可插拔的可选件。
报告里还有一句很老实的话:这轮是「强制多次压缩」的压力设置,不能把摘要那 22.5% 当成生产环境的默认水平。
谁该用它,谁不该
放到选型地图上看,它的位置很清楚。
如果你只是想让聊天机器人记住几句话,它太重了——要跑四个服务加一个数据库,浏览器得开在 2026 端口,还建议配一个反向代理。这一点上站内之前评过的轻量方案更合适,比如那份零依赖的记忆系统。
如果你在做的是多步骤、要跑代码、要跨会话接续的智能体,它的分层是少见的完整:23 个自带技能覆盖研究、数据分析、文档、幻灯片、图像与音视频;每个技能都要过前面那道闸门;主编排(也就是决定先派谁干、后派谁干的那一层)和子智能体、沙箱、记忆是分开的模块,不是一坨提示词。
它也不是没有钝的地方。技能包被截断读取时那个指纹问题,说明这道闸门自己的边界还没收紧;而 229 条告警里 155 条都是「引用了不存在的文件」,是文档在功能改动后没跟上——对一个技能库来说,这类失修比代码 bug 更常见,也更容易被忽略。
适合:手里已经有模型额度、要一套能自己长技能的智能体基座、并且真会去改它代码的团队。不适合:想开箱即用、不打算读源码的个人用户——66.5 万行 Python 不是一下午能读完的东西,光它的变更日志就有 9100 行,而正式版本标签只打了 3 个。
我的判断
值得放进观察清单。它最值得学的不是功能清单,是两件事。
第一件,把技能质量交给确定性规则,而不是交给模型的心情。这道闸门不看模型打分,只按固定规则出结论,命中就算失败——代价是它也会把自己人拦下来,这就是那 2 个技能判失败的原因。第二件,把一次花钱跑出来的失败结论原样发出来。前者在开源圈里算少见,后者要罕见得多。
至于向量检索,我的建议是别急着加。先按它那份报告的顺序试:先把原始记录留住、把关键词回查做起来,等有自家数据证明它稳定带来净收益,再考虑要不要叠一层。
关注 AI商业快讯,每天一篇 AI 热点深度解读。
相关阅读:Hindsight 深度评测:4.6 万 Star 的 Agent 记忆系统,2538 条行为快照我重跑零处不一致,5 条日期误判却被冻在测试里 · Paperclip 深度评测:9.7 万 Star 的 AI 员工管理系统,4775 个提交里 2127 个署名 AI 员工