Paul Jialiang Wu agentic-portfolio English Español 한국어 日本語✉️ 免费订阅列表
← 返回作品集

AI-Native 系列 · 智能体化工程

应用一直在说「完成了」。它在说谎。于是我们让它自己审计自己。

作者Paul Jialiang Wu · agentic-portfolio-lovat.vercel.app · 2026-08-01

一分钟速览——你能带走什么

我和一个 AI 协作开发的一款应用,曾告诉用户「登录链接已发送!」——可它背后根本没有邮件服务。我们没有一个个地去修漏洞,而是把产品做出的每一个承诺都写了下来(一共 80 条),并为其中 20 条配上了机器检查。这套诚实的记分板一天之内从 6 项绿灯变成了 15 项——审计系统还抓到了一个谁都能进的管理员后门。让这一切奏效的,只有一条规则:没有证据,就不算通过。

一个关于老年人传记应用、一句说谎的成功提示,以及那份终结了打地鼠式修漏洞的「claim」台账的公开开发实录。约 8 分钟阅读。

The app kept saying done — it was lying. A scoreboard going from 6 to 15 verified claims, with the lies it told on the left
诚实审计的一天:应用做出的承诺,与它真正能证明的东西。

那句说谎的提示

我正在开发新遗产传记(New Legacy Biography) ——一款让 AI 采访者陪伴老人、问出孙辈总是来不及问的问题,再把答案写成书里一章的应用。这种产品,出一个漏洞可不只是添麻烦。软件要是弄丢了你祖母讲的那条她从小长大的河边故事,丢掉的东西是没法重新下载回来的。

这个项目上,和我搭档开发的是一个 AI agent。它出活很快——单元测试全绿,135 个全过;TypeScript strict mode:干净;Lint:零错误。然后我扮成普通用户,试着用邮件链接登录。屏幕上写着:「登录链接已发送!」——your login link has been sent, check your inbox.

邮件从来没到过。它也不可能到——生产环境里根本没配置任何邮件服务。代码里有一段「开发环境兜底逻辑」,把邮件内容打印进一个没人会看的服务器日志,然后照样跟用户报告成功。我们信任的每一道关卡都是绿的,产品却在对唯一重要的那个人说谎。

更精彩的还在后面。「邀请家人」功能——这款产品的核心,亲属们靠它给生日纪念册贡献照片和语音——生成的邀请链接开头是http://localhost:3000。一个只存在于我桌面上那台电脑的链接。把它分享给外地的姑姑,一点用都没有。而注册页唯一的路径,走的正是那条同一个虚构邮箱——也就是说,有那么一段时间,地球上没有任何一个新用户能注册这款产品,而所有测试仍然全绿。

绿色的测试,为什么没能救我们

Edsger Dijkstra 在他 1972 年的图灵奖演讲里,说出了那句没人愿意大声说的实话:"program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence"(中译:程序测试可以非常有效地证明 bug 的存在,但要证明 bug 不存在,测试是完全无能为力的。) [1]。五十四年过去,AI 辅助开发不但没让这句警告过时,反而让它更加锋利——因为生成式工具太擅长写出看起来已经做完的代码。单元测试测的是函数,却从没人测过承诺.

Hamel Husain 做机器学习产品做了这么多年,用更当代的话说出了同一个诊断:"I've found that unsuccessful products almost always share a common root cause: a failure to create robust evaluation systems"(中译:我发现,失败的产品几乎都有同一个根本原因:没能建立起足够可靠的评估体系。) [2]。他这套推理里真正值得偷师的部分是:没有评估体系,修好一个失败只会暴露出另一个——他管这个现象叫「a game of whack-a-mole」(中译:一场打地鼠游戏)[2]。那一周我过的正是这种日子。修好邮件的谎言,发现了 localhost 链接;修好链接,又发现语音输入需要的模型文件根本没部署上去。每一只地鼠都是个意外,因为没人在记分。

心智模型:一份「承诺台账」

整个思路其实很简单,简单到明天你不看这篇文章也能照做一遍。你产品做出的每一个承诺——每一个按钮、每一项导航、每一行营销文案——都是一条claim(待验证的承诺)。没有机器检查的承诺,只是个传言。 所以:

  1. 把每一条承诺当作数据写下来。 不是记在脑子里,也不是写在文档里——而是写进代码能读取的文件。我们的文件里有这样的条目:「亲友无需注册可上传照片」「新用户可以完成注册」。
  2. 为每条承诺配一个像真实用户那样去验证它的检查。 用真实浏览器在生产环境上填表单;用一个不带 cookie 的请求,像你姑妈那样打开邀请链接。
  3. 诚实地打分,用三个等级,而不是两个: PASS(通过)、FAIL(失败),以及 NOT MEASURED(未测量)。第三个等级才是真正撑住整个系统的——一条你没法验证的承诺应当被 排除在外,绝不能悄悄算作绿灯。
  4. 拿它当闸门。 只要有一条被把关的承诺失败,整个运行就该愤怒地退出。一个诚实的 ❌ 胜过一个虚假的 ✅。
The claim ledger loop: promise becomes claim, claim gets a machine check against production, scored PASS / FAIL / NOT MEASURED, failures get fixed, the loop reruns
一图看懂承诺台账。第三个等级——NOT MEASURED——才是让另外两个等级保持诚实的关键。

诚实一天,能挖出什么

第一次针对生产环境的完整测试跑出的成绩是:6 通过、11 失败、3 未测量,覆盖 20 条机器可验证的承诺。这并不是因为这款应用大部分是垃圾——而是因为几个月来从没人要求它证明过什么。到当天结束时:15 项通过,剩下的每一个 FAIL 也都有了明确、限定范围的解决方案,而不再只是一种模糊的不安感。

三个发现,都不虚此行:

留下的模式,扔掉的反模式

值得留下的模式:

我们付出代价才学到的反模式:

这套机制,说穿了就是:生成式工具的优化目标是看起来合理的完成度——写出的代码,看起来就该是“完成”本该有的样子。这个优化目标里,从来没有要求邮件服务真实存在。所以,走向“假完工”的压力是结构性的,不是道德问题,对策也必须是结构性的。

第一原则,一句话说完:没有证据,就不算通过。

周一就能抄的作业

限定时间、目标明确——一个工作时段就能做完:

  1. (30 分钟) 打开你产品的落地页和导航栏,把它做出的 20 个承诺原封不动地写进一个 JSON 文件。
  2. (2—3 小时) 针对每一条承诺,写一个最笨、最直接的检查,像用户那样去操作它——用无头浏览器或 curl,对准生产环境,而不是预发布环境。给每条主张标记gate: true/false.
  3. (10 分钟) 运行它。把这份表格诚实地发布到团队都能看到的地方——PASS、FAIL、NOT MEASURED。
  4. 用一个数字衡量成功: 被闸门拦截的 FAIL 数归零,并且把这次运行接入 CI,让它永远不会悄悄腐烂。等它第一次拦下一个你原本很有把握的发布时,你就知道它起作用了。

我们的版本在仓库里,命名为 eval/claims.json + eval/run.mjs——20 条待验证的承诺,一条命令,诚实的输出。这套模式是我一直坚持的 OEC 循环(Observe → Evaluate → Control,观察→评估→控制)的一次具体应用:可观测性先于评估,而没有控制钩子的评估,不过是一块记分牌。

这件事,不只关乎软件

这件事所发生的那款应用已经上线:一个会说会听普通话的 AI 采访者,能顺着一段记忆一路跟进厨房——在上周的一次测试采访里,那段记忆闻起来是红枣和桂圆干的味道——然后把它写成一个章节;还有一个伴生 agent,能根据真实数据回答“我的书写到哪儿了?”这样的问题。这一周,它获得了一样比任何功能都更稀罕的东西:一个诚实面对自己的习惯。如果你也有一位父母,他们的故事你总说着要记录下来却一直没动手,它就在这里——而它现在能做到什么、还做不到什么,这份记分牌是公开的,这也正是我希望被推销任何东西时该有的方式。


参考文献

  1. Dijkstra, E. W.(1972)。The Humble Programmer(ACM 图灵奖演讲),EWD340:“program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence.”(中译:程序测试可以非常有效地证明 bug 的存在,但要证明它们不存在,则永远力不从心。)cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html
  2. Husain, H.(2024)。Your AI Product Needs Evals.“I've found that unsuccessful products almost always share a common root cause: a failure to create robust evaluation systems”(中译:我发现,失败的产品几乎总是有一个共同的根源:没能建立起稳健的评估体系);谈到症状时:“Addressing one failure mode led to the emergence of others, resembling a game of whack-a-mole.”(中译:解决一种失败模式,只会让其他失败模式冒出来,就像打地鼠游戏一样。)hamel.dev/blog/posts/evals

AI-Native 系列更多文章

本文属于 AI-Native 系列。文中所有内容都可以从公开的评测账本中复现——包括那些失败的部分。没有证据,就不算通过。发布按钮,握在你自己手里。