跳到主要内容
Huan Du

huandu.me

15 分钟阅读

人需要和 AI 一起经历开发全过程才更可控

AI 可以承担大部分实现,但目标偏差往往要在开发过程中才看得见。人只有和 AI 一起经历全过程、及时判断方向并完成最终验收,结果才更可控。

  • #thoughts
  • #ai-agent
  • #engineering
  • #decision-making

几天前,我让 Agent 帮我迁移一套长期运行的线上服务。我先讲清楚哪些服务不能受影响、迁移按什么顺序推进、哪些操作必须先经我确认,以及怎样才算整个切换完成。Agent 盘点了现有服务、配置和入口,把工作拆成若干阶段,然后开始逐步验证。

第一版计划看起来很完整。进入环境之后,新的情况才不断出现。有些旧配置仍然在承接流量,有些依赖只有对照实际运行状态才能确认,某个方案在新环境里能不能成立,也要等部署和检查之后才知道。计划还得继续用,只是需要随着现场信息继续修改。

做完这件事,我更能感受到人和 Agent 之间的分工怎么拆才合理。查资料、使用工具、完成常规实现,Agent 通常比我更快,覆盖面也广。但这项活最后往哪儿走,还得我来判断。我要知道哪些风险不能碰,在新信息出现时判断原计划要不要改,最后还要按照真实场景完成准出测试,确认结果能不能交付。

有些事,得做起来才知道

前段时间,我还让 Agent 把一个面向用户的产品页面重新做了一遍。需求里有布局、跳转、媒体展示和几种不同的交互边界。我只描述了产品希望用户看到什么、哪些行为不能发生,并提供了设计材料和项目位置。组件怎么拆、数据怎样组织、代码放在哪里,我让它根据项目自己判断。

Agent 读了现有项目,找到可以复用的结构,写出了第一版。编译通过,自动测试也通过了,页面看起来离目标已经不远。真正打开页面走一遍,问题才开始变得具体。某个入口的位置不符合实际使用时的视觉重心,某项交互在边界情况下会让人误解,某一段内容在手机屏幕上显得拥挤。这些问题很难在开工前全部写成一份需求,只有看到能运行的页面,我才能判断哪里不对劲。

于是又改了几轮。我指出问题,Agent 提出修改办法,有时它会补充一个我之前没想到的实现方式,有时我会否掉一个看似合理、实际会改变产品意图的方案。来回几轮之后,页面才逐渐接近我心里的目标。

除了服务迁移和页面重构,我还经常让 Agent 参与线上故障排查。我会告诉它用户看到的现象、故障大概从什么时候开始、此前试过哪些方向,以及线上环境只能做哪些操作。它去查日志、运行状态、配置和代码,沿着证据寻找原因。这个过程里,它需要不断提出假设、验证假设,也需要把已经证实的事实和暂时无法证实的猜测分开。

我在旁边做的事看起来普通:确认一个现象是否真的与问题有关,要求它继续追到能解释完整故障的原因,判断某个结论是否足以支持修复,决定新增加的诊断手段能不能在开发环境里做。方向一偏,越往下查越浪费。方向找对了,Agent 的调查速度就会非常快。

这几件事放在一起,我对 Agent 能做什么、人该做什么,有了更具体的感受。开发过程中的上下文很少能一次性写完。人当然可以把已知的目标、约束和验收标准提前说清楚,也应该尽量说清楚。问题在于,还有一部分信息藏在代码里、运行结果里、用户操作里,甚至藏在自己看到产物之后才出现的反应里。它们要在工作推进过程中才会被看见。

Superpowers 习惯先把判断做完

Superpowers 我早就知道,最近为了把自己的工作方式和它逐项比较,又完整看了一遍它的开发流程。它是一套给 coding Agent 用的开发方法,包含一组 skill,目标是把开发过程做得更稳定、更可重复。

拿到一项任务后,它会先用 brainstorming 追问真实目的。人和 Agent 一起讨论方案,人选定方向并批准设计。接下来,Agent 把设计写成详细计划,里面包含要改哪些文件、接口是什么、测试怎么写、每一步用什么命令验证。计划得到确认之后,Agent 按任务连续执行,再配合测试驱动开发、逐任务审查和完成前验证。

这套办法解决了很多实际问题。目标写下来之后,新会话不用依赖之前的聊天记录。子 Agent 可以只看自己需要的任务说明。测试和审查也不完全依赖人的临场注意力。任务足够清楚,设计和计划足够准确时,Agent 可以在很长一段时间里连续工作,人不必一直守在旁边。

它最厉害的地方,是把很多判断提前做完。人先把目的、方案、边界和验收标准想清楚,再把这些内容整理成设计、计划和测试。详细计划会逼着人把很多没想清楚的问题提前说开,这很有价值。进入执行以后,Agent 主要按计划推进,遇到计划没有写到的细节,它自行决定并记录下来。

这种做法很适合边界比较稳定的活。需求清楚,模块之间关系明确,验收可以写成自动测试,出了问题也容易回滚,前置设计和详细计划可以把后面的执行变得很顺。大规模、可拆分的工程任务尤其容易从中受益。

我的顾虑也来自同一个地方。前置设计做得越细,人越容易把它当成目标已经完全想清楚的证明。计划记录的是当时的理解,它不会自动知道后来看见了什么。现实推翻计划里的某个假设以后,前面已经投入的时间、代码和讨论仍然摆在那里。人会舍不得推翻,Agent 也会沿着已有计划继续补,最后形成很多次小修小补,真正错误的方向反而混在这些工作量里面。

这时候,单靠 Agent 自己发现方向不对并不够。它可以发现代码里的矛盾,也可以质疑某一步是否还能执行,却不知道一件新出现的事情是否改变了产品目标,或者是否值得让整个计划停下来重做。这些判断需要人的经验和责任,也需要人及时看见中间结果。

Superpowers 同样重视人的参与。它把人的参与放到了设计和计划阶段,希望用一份充分讨论过的前置说明,换取执行阶段的自主。我的工作方式把人的参与一直留在开发过程中间,用更频繁的交流换取更早的方向修正。

前置契约与持续校正两种协作节奏:前者由人先确定设计和计划,Agent 连续执行后由人看结果;后者由人提出目标与边界,Agent 提方案并执行,人在中间纠偏,最后完成验收

上图是我对两种协作节奏的理解。上半部分里,人的判断主要落在设计和计划;下半部分里,人的判断跟着 Agent 的工作一起往前走。差别就在这里,人的判断什么时候进入执行过程。

Superpowers 的过程控制其实很完整。它对测试、审查和完成条件规定得很细,执行过程也有自己的检查。两种做法的区别在于,人的判断落在流程里的哪个位置:Superpowers 把它放在前面,后面 Agent 主要按计划往前走。人再次看到完整结果时,已经很难判断哪一步其实很早就偏了。

和 Agent 边做边把思路理顺

我现在更习惯先把目的、预期结果和自己的想法讲清楚,再让 Agent 去读项目、分析上下文、自己决定实现方式。只有非常确定的小改动,我才会指定具体函数或具体写法。

原因很简单。Agent 能快速读取大量代码、文档和工具结果,也更容易从现有项目的习惯里找到合适的做法。我把实现细节规定得太死,反而可能把它限制在我不完整的理解里。它自己沿着项目上下文找出来的方案,经常比我仓促写下的指令更完整。

动手之前,我会让它先说准备怎么做,也会要求它把不确定的地方列出来。计划保持到我能看懂的程度:准备改动哪些部分、关键假设是什么、风险在哪里、完成后准备怎样验证。看到这些内容,我才能判断它是不是理解了目标。

有些问题在计划阶段就能发现,有些要等代码写出来才明显。Agent 先跑出一个能用的版本,我打开页面、执行关键操作、检查真实结果,再把自己的判断告诉它。它解释为什么这样实现,我补充它不知道的产品背景或业务约束。它提出更合适的做法,我决定哪些可以接受,哪些必须重做。

这样的配合既保留 Agent 的主要执行权,也保留人的关键判断权。Agent 承担主要实现工作,阅读代码、尝试方案、运行测试、处理错误,它完成大部分具体工作。人做的是另一类工作:理解它的思路,提出有建设性的意见,在关键处拍板,在它偏离目标时把它拉回来。

这样一来,对人的要求确实更高。我要跟得上 Agent 的思路,知道它为什么要这样改,能看出某个方案在产品层面是否成立。看不懂它的实现时,我不能假装已经理解,也不能因为自动测试通过就直接放行。整个过程里最稀缺的,就是人的判断力。

关键节点上,我还会让它把当前判断讲清楚。比如为什么选择这个方法,哪些已有代码影响了决定,哪些地方只能靠猜测。如果它能用项目里的事实支撑自己的方案,我会让它继续;如果关键结论只有语言上的自信,我会要求它回去补证据。

AI 写得比人读得还快,这件事我之前在《AI 越快,越不该替你做决定》里写过。那篇讲的是人为什么不能撒手。真到每天干活,还得回答另一个问题:人应该怎样参与开发,才能及时发现方向错误,同时又不把所有实现细节都揽回自己手里。

我现在比较稳定的习惯,是先讲清目标和边界,再让 Agent 去理解项目。中间要求它把重要假设和疑问说出来,遇到分歧就逐项讨论。任务较大时先做一轮规划,确认彼此理解一致再往下做。任务很小、结果也很确定时,可以直接执行,不必为了流程完整而增加一轮形式上的确认。

这些做法有一个共同目的,让我在还能容易改变方向的时候看见问题。开发早期推翻一个错误方案,往往只需要重新讨论一次;等到代码、测试、文档和部署都围绕错误目标铺开,修正就会变成一场漫长的清理。

这样配合当然费时间。Agent 跑得很快,我在旁边读方案、看结果、想取舍,也不会轻松。省下来的是方向错误之后的返工,换回来的是更早发现问题。

验收是责任的最后一步

最后验收时,我会自己按照真实使用方式走一遍。页面要打开,交互要操作,迁移后的服务要检查实际状态,故障修复要对照原先的现象确认问题真的消失。自动测试可以告诉我已有行为有没有被破坏,人的验收回答的是另一个问题:这件事有没有解决原本的问题,结果是不是我愿意交付的东西。

前面提到的那篇文章讲的是人为什么要做最终判断。放到具体开发里,人还要在过程中和 Agent 一起干活,最后再亲手验收。过程里一直在场,结果上亲自确认,靠的是同一份责任。

大方向错了,人应当承担主要责任。Agent 可以提出方案,也可以质疑需求,但它不知道这项工作的长期意义,不知道某个取舍会影响哪些现实关系,更不能替组织承担后果。人让 Agent 进入项目,给它目标、资源和权限,也要对最后交付的结果负责。

责任要算数,Agent 就得把重要假设、冲突和未验证的内容交出来。它静默补上一个看起来合理的默认值,或者只说一句“已经完成”却不给验证证据,人就没有机会做判断。这样的责任只是事后追责,没法在过程中发挥作用。

所以我把验证分成两层。Agent 负责自动测试、代码审查和完成前检查,证明改动没有明显破坏已有行为。人负责准出测试,确认真实结果符合目标,代价也可以接受。两层都完成以后,我才会说这项工作可以交付。

什么样的活适合这样做

这样配合当然也有代价。人要持续阅读 Agent 的思路和结果,要能理解方案,要在关键问题上做判断。人的注意力和专业能力会限制任务规模,也很难靠不断增加 Agent 来提高并行度。

目标稳定、验收能自动判断、错误容易回滚的任务,更适合 Superpowers 这种前置设计和详细计划的模式。人把目标说清楚,设计好验证方法,然后让 Agent 连续执行,效率会高很多。为了保持参与感而不断打断 Agent,反而浪费双方的时间。

目标还在变化,真实约束要看到产物才出现,方向错误会造成大范围返工,或者最终体验和业务取舍无法完全写成测试时,人就需要留在开发过程中间。此时人的主要工作是把新的理解及时带回来,判断原计划是否仍然成立,决定要不要停下来重做。

更常见的做法是把两套方式放在一起。用前置设计暴露明显分歧,用测试、审查和自动验证保证工程质量,用过程中的交流处理目标变化和关键取舍,最后由人完成验收。这样既能利用 Agent 的执行能力,也把目标判断和交付责任留在人手里。

和 AI 一起经历开发过程,表面上比写完需求就等结果慢一些。多出来的这些交流,让我能在方向还容易改的时候发现问题,也让 Agent 的产出始终对得上真正要做的事。人最后亲手验收,是把这份判断落实到交付上,也是明确告诉自己和团队,这项结果经过了人的确认。

Agent 可以帮我把事情做完。做什么、为什么做、什么时候算做完,这些还得由我来判断。人愿意陪 Agent 走过整个过程,最后再亲手验收,事情才会真的可控。

评论

  1. 正在加载评论…

发表评论

只支持纯文本:内容会原样显示,不会解析 HTML、Markdown 或链接。