LangChain 融了 1.6 亿美元。三年开发。十亿美元估值。他们的测试平台 LangSmith 确实做得不错:轨迹评估、数据集流水线、LLM-as-judge、回归测试、工具单元测试框架。该给的都给了。
但组件不等于实践。
LangChain 给你的是测试工具。它从来不告诉你测什么、按什么顺序测、以及什么时候算测完了。没有一个固执己见的工作流会这样说:
- 这个 failure 发生了
- 现在写一个 Skill
- 现在写确定性代码
- 现在写单元测试
- 现在写 LLM 评估
- 现在加一个 Resolver 触发器
- 现在评估这个 Resolver
- 现在检查重复
- 现在做冒烟测试
- 现在归档
这个循环不存在。你得自己从零散的原始工具里发明它。大多数 AI Agent 用户根本不做任何测试——因为他们选的框架给了他们健身房的会员资格,却没给训练计划。
大多数 AI Agent 的"可靠性"是基于感觉的。调 Prompt。更大的 System Message。"请不要产生幻觉"的咒语。这些东西在对话变得复杂的那一刻就开始失效。那些融了几百万美元来解决这个问题的框架,给你的是监控仪表盘和单元测试助手,然后说"祝你好运"。
两次失败,同一个形状
失败一:Agent 找十年前的出差记录。
我向 OpenClaw 问一个十年前的商务旅行,埋在日历历史里。简单问题,应该一秒找到。
Agent 的实际行为:
- 调用实时日历 API → 被阻止(太久远)
- 试邮件搜索 → 噪音大,没有结论
- 用不同参数再试日历 API → 仍然被阻止
- 五分钟后,搜本地知识库 → 立刻找到
答案一直在我的自有数据里。3146 个日历文件,跨度 2013 到 2026,已经索引,已经本地化,一个 grep 就能找到。Agent 只是没有先看那里。
失败二:Agent 说"你的下一个会议在 28 分钟后"。
现实:88 分钟。Agent 在脑子里做了 UTC→PT 时区转换,差了正好一小时。
这两个问题的共同形状:确定性工作(deterministic work)在 latent space 里做了。 日历 grep 是确定性的——同样的输入,同样的输出,每次都一样,不需要模型。但 Agent 在 latent space 里做这件事,启动推理、调用 API、解释结果,而一个三行脚本本可以瞬间返回答案。
这就是 bug。不是答错了,是做事的"场地"选错了。
Thin Harness / Fat Skills
在 thin harness / fat skills 架构里,Skill 是一份 Markdown 程序,它教模型如何处理任务——不是告诉它做什么(用户给 what),而是提供过程(how)。
想象一个方法调用:同样的过程,传入不同的内容,输出截然不同。
从失败一中产生的 Skill:
name: calendar-recall
description: "Brain-first historical calendar lookup. ALWAYS use this before any live API for any event not in the future or the last 48 hours."
# 硬规则:
# Live calendar APIs are ONLY for events in the FUTURE or the LAST 48 HOURS.
# Everything historical goes through the local knowledge base first.
然后 Agent 自己在 latent space 里阅读 Skill、理解到日历搜索是确定性工作,生成了确定性脚本:
$ node scripts/calendar-recall.mjs search "Singapore"
Found 2 matching day(s):
── 2016-05-07 ──
Flight to Singapore, Mandarin Oriental check-in
── 2016-05-08 ──
Lunch with investors at Fullerton Hotel
100 毫秒内执行完(大部分是 Bun 启动时间;实际 grep 在亚毫秒级)。零 LLM 调用。零网络。只有本地文件。
这就是让整个架构运转的循环:latent space 构建确定性工具,然后确定性工具约束 latent space。 Agent 用判断力(latent)写了 calendar-recall.mjs,现在 Skill 强制 Agent 运行那个脚本而不是推理日历数据。模型的智能创造了防止模型变蠢的约束。
旧失败路径在架构上变得不可达。Skill 说"先搜本地",脚本执行搜索,Agent 再没有机会自作聪明或再次犯错。
Skillify 的 10 步检查清单
一个 failure 被提升为 skill 时的完整清单:
- □ 1. SKILL.md — 契约(名称、触发器、规则)
- □ 2. 确定性代码 —
scripts/*.mjs(代码能做的就不需要 LLM) - □ 3. 单元测试 — vitest
- □ 4. 集成测试 — 实时端点
- □ 5. LLM 评估 — 质量 + 正确性
- □ 6. Resolver 触发器 — AGENTS.md 条目
- □ 7. Resolver 评估 — 验证触发器确实路由到正确的 Skill
- □ 8. 可解析性 + DRY 审计
- □ 9. 端到端冒烟测试
- □ 10. 脑内归档规则
一个没有通过全部 10 步的特性不是 Skill。它只是今天恰好能工作的代码。
为什么这整个循环重要
Skillify 的核心不是"测试",是把判断交给代码、把执行路径锁死。
一个没有测试的 Skill 系统会积累这样的失败模式:
- Agent 周一创建了
deploy-k8s。周四从另一个对话里又创建了kubernetes-deploy。两个都存在,都对类似短语触发。模糊路由,没人注意到,直到错误的那个在错误的时机运行。 - Skill 在刚写的时候工作完美。六周后上游 API 形状变了,Skill 悄悄返回垃圾数据,直到有人手动发现。
- 自主创建的 Skill 有个弱的触发器,从来匹配不上。它变成了孤儿,消耗索引 token,从不运行,慢慢腐坏。
这就是"没有测试,任何代码库都会腐烂"的问题——软件工程在 2005 年解决了它。Agent Skills 没有什么不同。
健康的软件工程团队里,每个 bug 都有一个测试。这个测试永远存在。这个 bug 在架构上变得不可能重复。AI Agent 应该以同样的方式工作。
最重要的 Eval 启发式
最有诚实的 Eval 启发式:搜你的对话历史,找到你什么时候说了"卧槽"或"什么鬼"。这些就是你缺失的测试用例。
Garry Tan 的结论:
一年后和我一起工作的 Agent,将由它在之前一年里犯的每一个错误塑造。这不是一个" nice to have"。这是整个论文的核心。
把大海煮沸。让你的 Agent 做点什么,然后 Skillify it。每天都这样做,你就拥有了一个他妈真正聪明的 OpenClaw,做所有你想让它做的事。