【译】当 Agent 承担工作时,如何保持批判性思维

原文:Addy Osmani,Critical thinking when agents do the work(X 长文)。本文为中文译文,保留关键专有名词与术语。

过去,我们被教导,批判性思维(critical thinking)意味着以谦逊的好奇心和适度的怀疑态度面对新信息——接触不同观点,形成自己的判断。这一点依然成立。但如今,我的大量工作都通过 Agent 完成,日常工作中已经没有什么会迫使我进行批判性思考。对于那些已经全面拥抱 Agent 工作流(agentic workflows)的工程师和产品人——同时运行多个会话,并期待模型继续进步的人——我想先说明:我非常喜欢这些工具。我写这篇文章,并不是为了倡导少用 Agent 工作流。

我的目标是帮助你在一个可以轻易把任何事情交给 Agent 的世界里,依然保持批判性思维。

过去,我们的大部分认知加工和审美判断,都发生在提出问题与得到答案之间。现在,这段间隔已经缩短到以秒计。你越多地使用 Agent 工作流,保持批判性思维就越困难,不过原因可能与人们原先预想的不同:随着模型进步,明显错误的比例越来越低。许多——甚至大多数?——输出都文笔流畅、基本正确,让你觉得没有必要再看一遍。

即使你同时运行许多个 Agent,查看这些输出的,也仍然只有你这一双眼睛。

你必须主动把批判性思维安排进日常工作,因为在默认情况下,没有什么会替你做到这一点。

我们之所以很难自行纠偏,部分原因在于,Agent 工作流用起来很舒服。在忙碌的一天里,迅速得到令人满意、而且往往正确的答案,确实让人轻松。但也正因如此,我们很容易放松警惕。

卸载、让渡与投降

和别人讨论这个问题时,我会把它描述成一条光谱:

光谱的顶端是认知卸载(cognitive offloading):把任务委托给 AI,同时仍然对结果负责。我整天都在这样做,你也应该这样做。中间是判断让渡(deferral):工具的输出成了你的新输入,那个结果不再被当作一个有待验证的假设。底端则是认知投降(cognitive surrender):AI 的输出悄然成了你自己的判断,而你觉得没有必要检查它。

“认知投降”这个术语由 Wharton 的 Steven Shaw 和 Gideon Nave 提出。它非常贴切地描述了我观察到的现象:随着信任——或者惰性——增加,人们会沿着这条光谱逐渐下滑。这个转变很少被察觉,因为每一步都很小,而且看起来都合情合理。上一个答案你认真读过,于是下一个就略读一下。再下一个,你只扫一眼框架。直到有人问起其中某一行,你却解释不出来,甚至连借助 Agent 都解释不清。

这就是认知投降,也是认知债务(cognitive debt)积累的方式。通常,直到你试图调用自己对系统的心智模型(mental model),才会发现它根本不存在。Margaret-Anne Storey 写过,这种现象在团队中表现为:大家对系统所共有的理论性理解逐渐被侵蚀。我也写过它在代码领域的对应概念——理解债务(comprehension debt,这个术语由 Jeremy Twei 提出)。在当下,它完全不可见。代码库看起来整洁漂亮,测试也全部通过。直到你必须修改系统,却发现已经没人理解它了,问题才会显现。同样的情况也会发生在你只看了战略文档或规格说明的目录,就签字批准的时候。

说清楚一点,我并不是在提倡不可能做到的事。要在脑中维持一个庞大现代代码库的完整心智模型,本来就不现实。Claude Code 团队曾公开表示,他们会按需重建理解:需要理解某个部分时,就让 Claude 解释那一块,而不是把整个系统模型一直装在脑子里。正如我之前写过的,这类债务比大多数工程师想象的更容易补回来。只要能在需要时重建对局部的理解,就不必一直维持完整模型。你只需要知道,自己缺少哪些理解。

对于风险较低的事情,你完全可以放心地全部委托出去。但如果一个问题的答案,你连借助 Agent 都无法解释,那就意味着你已经放弃了对它的主导权。

这也不一定总是问题。就在最近,我录制一门课程,需要从三家评分相近的酒店中选一家作为录制地点。我没时间逐条查看所有评价,于是把这个决定交给了 AI。结果不错,下次我还会这样做。但在决定如何投资我们的钱、如何给孩子提供职业建议时,我不会这样做;在工作中决定应该做什么产品、哪些变更会影响哪些用户、是否可以安全发布时,我也不会。犯错代价低的事情,可以交出去;后果需要别人承担的事情,要把推理和判断留在自己手里。

我会问自己的问题

当我不清楚自己究竟怎么想时,通常会回到一些基本问题:我怎么知道自己在解决正确的问题?我怎么知道自己采用了正确的解决方式?有什么证据支持我的结论?我怎么知道工作已经完成?大多数时候,这些无非就是谁、什么、哪里、为什么、何时,以及如何。写出来显得幼稚得可笑,但它们会迫使你从一些原本可能忽略的维度思考。如今,我们太容易跳过这一切,直接问 Agent:它觉得我们应该怎么做。下面这些,就是我现在会问自己的新版问题。

提问之前,我是否先提出了一个假设?在让 Agent 处理任何不那么简单的任务之前,我都会先写下——哪怕只是在脑子里想一下——自己认为答案可能是什么。猜得不好也没关系。有了新信息,你随时可以改变想法。但一旦读过一个表达完善的回答,就很难再想象其他可能性。如果你完全没有方向,可以让模型做一次 Thariq Shihipar 所说的“盲点扫描”(blind spot pass):把你已经知道的内容交给模型,让它找出你的“未知的未知”(unknown unknowns)。

我是在请它帮助我思考,还是在把思考交给它?两者都可以,前提是你清楚自己正在做哪一种。

什么情况一旦属实,就意味着这个结论是错的?然后去查明。模型对自身置信度的评估,远不如一个你能实际执行的测试有价值,所以,给它一个这样的测试。

我是否听过从不同角度提出的反对意见?当我对某个没有唯一答案的问题采取了鲜明立场时,我会请不止一个模型为相反立场辩护,然后审阅输出,形成自己的看法。这会花更长时间,但最终我会对这个主题了解得更多。

当着未来负责维护它的人的面,我敢押注这个结果是对的吗?这适用于代码,也适用于你交付的任何其他东西。我认为,这就是能否为自己的交付作出交代的标准。

我已经不再练习哪些技能了?也许是某些日常调试工作。我可以接受放下其中一部分,但我希望这是有意识的选择。

把验证变成习惯

最近,我写了很多关于验证(verification)的文章,因为我认为,瓶颈已经从编写代码,转移到了确认自己做得对。当你给 Agent 提供验证自身工作的手段,无论是端到端测试(end-to-end tests)、属性测试(property tests),还是实际操作应用,它都可以在你还没查看任何东西之前,完成修改、运行验证测试、读取输出,再尝试一次。这就是 Boris Cherny 所说的“给 Claude 一种验证自身工作的方法”,我认为,这是取得出色成果最关键的组成部分之一。你会把精力放在构建这些反馈循环、审查证据上,而不必逐行阅读所有代码。

但你也可能把验证本身交出去。“有什么证据支持我的结论?”变成了“检查变绿了吗?”Agent 让创建测试变得如此便宜,你会看到大量绿色通过标记,但一个通过的测试,完全可能发现不了已经损坏的功能。如果测试和功能实现犯了同样的错误,测试就会通过。而且,一个绿色标记只说明某一项性质得到了验证,我们却很容易以为它涵盖了一切。

检查变绿时,问问它证明了什么。再问问,它没有证明什么。

事先定义清楚什么叫“已验证”,因为事后你会为任何结果找出合理化解释。

Agent 工作的终点应该是某种具体、可观察的东西:一个通过的测试、一张截图、一条日志,或一段调用链路(trace)。这样,完成标准就建立在事实上,而不会因为“看起来做完了”之类的感觉,变成可以随意解释、甚至放弃判断的东西。收到 Agent 的完成通知后,先别看总结,先查看它实际执行的命令片段及其输出。

Claude Code 也可以通过一个使用全新上下文的子 Agent,对自己的工作进行自我审查,作为合理性检查(sanity check)。值得把这一步固化到反馈循环里,让它每次都执行,而不是只有你记得时才做。我最后仍然会问一句:“我有没有漏掉什么?”这听起来很傻,但经常发生这样的情况:我使用前沿模型(frontier model)完成一个复杂功能,查看了结果,也审查过了,再问一句“我有没有漏掉什么?”,它就会补充两三件事。这就是为什么我总会问。

当然,不必每次都做到这种程度;知道什么时候需要深入,本身就是一种技能。在我们介绍 Claude Code 团队如何做代码审查的文章里,我最喜欢的一条经验法则是:“如果你说不清这些检查会漏掉什么,就要求一次真正的审查,而不只是快速批准。”

这也适用于代码之外的工作。如果 Agent 替你汇总了五十次客户访谈,或者完成了一份竞品分析,就抽查几份原始材料,确认总结准确。找一个支撑你建议的关键数字,核实它的计算是否正确。

Agent 已经让搭建验证机制变得很便宜。对你而言,难的是知道什么才算好的验证。

真正关注生成的内容

假设 Agent 给你提交了一个 600 行的 PR(Pull Request)。你大致看了看结构,没有逐行阅读。变量名看起来合理,测试也通过了,于是你批准了。但在中间某个地方,事务边界处的执行顺序发生了一次细微变化,或者一个你从未考虑过的边界情况,其默认设置被反转了。我想,你确实算是审查过了,只不过,你只检查了那些自己原本就知道要找的东西。

编写代码和审查代码是两种不同的技能,而审查到某个程度,就可能变成机械盖章。所以,阅读 diff(代码差异)时,要像它不是 AI 写的一样认真,然后再越过 diff,看看 Agent 作出了哪些决策。在一个漫长的会话里,它会替你作出许多小决定:默认值是什么、哪些内容不在范围内、当两条需求冲突时,它重新解释了哪一条。

你不会在一份“一切顺利”的总结里看到这些,所以,要让它列出自己作出的决策和假设。然后考考自己。随机挑几行,问问:这一行是怎么回事?那一行呢?如果是一份文档,就把它关掉,试着凭记忆写出主要论点。有些人有个我很喜欢的长会话习惯:让 Claude 为这次变更写一份报告,并在末尾出一套测验,规则是:“只有测验全部答对,我才合并。”

充分理解你要交付的东西,理解到足以为它作出解释和辩护。因为总有一天,可能会有人问起。

Agent 也可以帮助你守住注意力。例如,我有一个开源项目,经常收到大量 PR。我会让 Agent 帮忙判断提交进来的是什么、哪些内容违背了我们的准则,以及哪些地方可能需要我关注。我很少让 Agent 自行决定这些事情,但它们可以缩小我需要关注的范围,让我真正去思考:这些变更是否在用正确的方式解决正确的问题。

接下来是数量问题,对此你必须诚实面对自己。我把它称为“编排税”(orchestration tax):Agent 生成的东西,与那些你愿意署上自己名字、为之负责的东西之间,存在一道差距。如果已完成的工作堆积得比你审阅得还快,那么在解决这个问题之前,再开一个会话也无济于事。你需要收紧检查,让更少的工作需要你亲自介入,或者放慢速度。

当产出量超过了你能为之负责的限度,你就已经不再是在审查。你只是在寄希望于它没有问题。

高质量输入,高质量输出

人的心智模型仍然参与其中,只是它的位置从中间转移到了两端。你的精力投入到了前端的任务描述和上下文,以及后端的输出审查。这就是为什么好的输入对输出质量如此重要,也是为什么我把写好 Prompt(提示词)视为一种批判性思维技能。

过去,如果你提出一个含糊的请求,别人会追问,你可能因此意识到:“等等,我其实还没想清楚。”Agent 往往不会在这里拦住你。它会补齐你遗漏的内容,交回一个看起来已经完成的结果,尽管背后的想法仍然模糊不清。我曾把这称为意图债务(intent debt):那些你没有亲手写下的产物中,可能隐含着未明说的目标、约束和理由。与其他债务不同,这一种没人能替你解决。意图必须来自你自己。

你的 Prompt 反映了你对问题的理解。如果你无法清楚地表达它,也许它在你自己脑子里就还不清楚。

寻求帮助之前,先用自己的话写一份需求简述。说明受众、范围之外的事项,以及完成标准(definition of done)。如果第二轮纠正后仍然没达到目标,就停止微调,重新写 Prompt。

这件事也可以让 Agent 帮忙。我很喜欢 Andy Clark 对“委托 AI 系统”和“与 AI 系统协作”所作的区分。在后者中,你会进入一个相互增强的良性循环:你的 Prompt 让输出更精准,输出又让下一轮 Prompt 更精准,并让你对问题的心智模型更加清晰。如果还有不明确的地方,就让 Agent 围绕它不理解的内容来访谈你。如果结束会话时,你对问题的心智模型也得到了完善,那就是成功的信号。

同时,也要留意输入。每个 Agent 都很容易直接把上一个 Agent 的总结放进自己的上下文,没过多久,第三个 Agent 就已经没有读过原始文档了。

你还需要有自己的输出标准。我尝试过用 AI 进行很多不同媒介的创作,其中大部分从未展示出来,因为它们达不到我的标准。如今,所有东西都排版漂亮、语气自信,因此,表面的精致已经不再是一个有用的质量信号。

AI 也许让产出变快了,但如果我不愿意把某个结果归于自己名下,我就不会把它交出去。

当某个结果不符合你的标准时,把原因记录到共享配置、Hook 或测试中,避免同样的问题再次发生。品味就是这样产生复利的;而记录某个结果为什么没有过关,本身也是很好的练习。

“但模型会比我更擅长这些”

如果你像我身边许多人一样看好这个领域的未来,那么在前面几个章节里,你大概已经想过:再过一两年,模型就能发现那些我能发现的问题了,那为什么还要费心维持这项技能?

对于其中很多问题的发现,你也许是对的。我自己也一直主张,把越来越多的问题检测工作交给 Agent。但我认为,这件事依然重要,原因在于:归根结底,必须有人对交付结果负责。不管 AI 提供了多少帮助,都需要一个人承担责任。

对于某项具体任务,应该在多大程度上信任 Agent,本身就是一个需要判断的问题。审查工作成果,是让自己的判断保持准确的一部分,因为模型会犯什么错,一直在变化。Anthropic 对其工程师和研究人员开展的研究,把这个陷阱称为监督悖论(paradox of supervision):“监督 Claude 所需要的,恰恰就是那些可能因过度使用 AI 而退化的编程技能。”

有些问题对我来说最重要,而更强的模型也无法替我解决:你在构建什么?它为什么值得做?它会影响谁?你愿意为此牺牲什么?这些问题都需要你来回答。Agent 可以帮助你想清楚,我也希望它能帮忙,但最终,这些问题仍然属于你。

你可以把工作以及很大一部分审查交出去,但不能把最终责任也交出去。

日常实践

你不必一丝不苟地执行所有这些做法。把适合自己工作流的部分融入进去就好。

每周,不借助 Agent 写一点代码,或者亲手做一件实事——如果以后忘了怎么做,你会觉得很糟糕的那种。(我曾把这称为校准练习,calibration exercise,但它并没有道德评判的意味。)每月,写下自己已经不再做哪些事情,再决定其中哪些是你可以接受不再做的。我以前一篇博客里的一个问题,今天依然有效:如果 AI 不存在,你会有多无所适从?

如果某件事超出了你的理解范围,就去学会它。写作时,如果遇到一个从未见过的表达,我可以用 Google 搜一个只有一句话的解释,然后把它写进去。但我更愿意做一点研究,真正理解它,这样才能知道它应该放在什么位置。

认真检查机器的工作,本身就是实实在在的工作。假装它不算工作,团队最后就会干脆不做。它不是没有成本的,所以,把它作为一个独立事项列入计划、安排时间,你才会真正去完成它。

停止练习的技能终究会消失,而且速度可能比你以为的更快。那些你不愿失去的技能,就要继续亲手运用。

请带走这些要点

  • 有意识地使用工具。Agent 可以考你、访谈你、向你展示证据,但前提是你安排它这样做。所以,去安排。

  • 诚实面对自己在光谱上的位置。如果连借助 Agent 都解释不清答案,你就已经放弃了自己的判断。

  • 先有一个假设。提问之前先形成假设,哪怕猜得不好。

  • 一个绿色通过标记只说明一件事。它检查了什么?又没有检查什么?

  • 寻找证据。读总结之前,先看它运行了什么,以及返回了什么。

  • 通过阅读弄清楚它作出了哪些决策。它替你决定了什么?

  • 打磨你的 Prompt。你如何表达请求,体现了你对问题理解得有多深。

  • 设定标准,并坚持它。如果你不愿为它署名,就别把它交出去。

亲手运用那些重要的技能,让自己始终参与其中。你可以做这样一件事:提问之前,写下自己认为会发生什么;Agent 完成之后,写下它没有检查的一件事。告诉我,这是否改变了你阅读输出的方式。独立思考。提出更好的问题。为结果承担责任。