跳到正文
InfoQ · 微信公众号·· 12 小时前精选AI 评分66

首席架构师 Carlos Kelkboom 分享 5 条 Agent 编程反常识原则

AI生成的代码看不懂就扔掉重来:一位首席架构师的 5 条 Agent 编程反常识原则

AI 导读

InfoQ 编译 Patrick Akil 主持的播客,首席架构师 Carlos Kelkboom 分享五条 Agent 编程原则:亲自搭建代码骨架、主 Agent 禁止直接修改代码、生成的代码看不懂就扔掉重来、尽量让 Agent 一次性完成较大任务、用三个 Agent 并行探索再由第四个 Agent 比较合并。

推荐理由

原文系统梳理了首席架构师 Carlos Kelkboom 的五条 Agent 编程原则及其争议,读者可以对照反思自己的 Agent 协作与代码审查流程。

正文

原创 林绮蓓、蔡芳芳 2026-10-18 10:15 河北

AI 编程最大的差距,可能不在于谁让 Agent 写得更快,而在于谁更清楚该让它做什么。

图片

图片

翻译|林绮蓓

编辑|蔡芳芳

“我已经很久没好好看过代码了。”在 AI 编程工具越来越强的今天,这句话开始成为一些开发者描述自己工作方式的方式。需求交给 Agent,代码由它生成,测试和审查还可以交给其他 Agent。软件似乎从来没有这么容易做出来过。

但另一种情况也越来越常见:项目启动得很快,做了几轮后却很难继续。Agent 悄悄换掉原有部署脚本,同一个功能在代码库里被实现了五遍;一旦需要大幅调整架构,它往往选择继续打补丁。开发者拥有了大量能运行的代码,却未必还看得清系统究竟是怎么搭起来的。

在首席架构师 Carlos Kelkboom 看来,问题已经延伸到人与人的协作。开发者遇到问题越来越习惯先问 Agent,PR 下的讨论逐渐减少,与用户沟通、理解产品需求、反复思考架构的过程也更容易被跳过。代码可以更快生成,但一个项目为什么做、为谁做、以后怎样演进,仍需要有人作出判断。

在 Patrick Akil 主持的这期播客中,Carlos 分享了五条颇为反常识的 Agent 编程原则:第一,亲自搭建代码骨架,提前确定目录、关键文件和函数签名;第二,禁止主 Agent 直接修改代码和文件,充分理解需求后才启动执行 Agent;第三,生成的代码看不懂就扔,执行结果隔离在 Git Worktree 中,一旦发现偏离预期结构,就直接舍弃重来;第四,尽可能让 Agent 一次性完成较大任务,避免反复修改导致代码不断打补丁;第五,让多个 Agent 并行探索不同方案,例如三个 Agent 分别开发,再由第四个 Agent 比较结果,只合并好的部分。

两人的分歧也贯穿了整场对话。Patrick 更看重工具能否尽快做出有用的东西,Carlos 则反复追问:开发者从中学到了什么?如果代码越来越便宜,工程判断、代码审查和初级工程师的培养该如何改变?讨论最终从编程实践延伸到未来编程语言、AI 泡沫,以及一个更根本的问题:当 Agent 能写越来越多的代码,人类工程师还应该把时间花在哪里?

太长不看版:

Patrick:软件工程这几年最值得警惕的变化是什么?

Carlos:开发者越来越习惯与 Agent 一起工作,却减少了与同事、用户的交流。PR 里的讨论变少了,产品意识也可能因此被削弱。能很快做出一个演示,和真正理解用户、把软件长期做好,是两回事。

Patrick:Agent 随时能回答问题,为什么还要花时间找人讨论?

Carlos:因为即时答案也会改变思考习惯。Agent 回答得快,还可能顺着你的预期说;人与人的讨论慢一些,却能带来不同经验、质疑和反馈。学习不只是得到答案,还要留出时间自己消化。

Patrick:为什么你坚持先搭代码骨架,再让 Agent 动手?

Carlos:Agent 擅长迅速找到一条实现路径,却未必顾得上新代码与整体架构的关系。我会先建目录、文件和关键接口,明确模块职责。否则,代码重复、“上帝对象”和莫名其妙的新脚本都可能出现。能不能把方向交代清楚,是我认为拉开 Agent 工程师效率差距的关键。

Patrick:不熟悉一门语言,也能先搭出合理的骨架吗?

Carlos:可以先研究成熟的开源项目,让 Agent 对比设计模式、解释取舍,再自己动手写些注释和初步结构,反复讨论。关键不是让它替你作出所有决定,而是借助它培养自己的判断力。

Patrick:为什么你的主 Agent 被禁止写代码、修改文件?

Carlos:我希望它先专心理解我在问什么,而不是听到问题就急着实现。我让主 Agent 负责对话、检索和确认意图,用多个模型辅助评分;只有当它对理解我的目标有超过 90% 的把握时,才向我提出启动执行 Agent 的建议。

Patrick:Agent 写完代码,你怎么审?发现不对又怎么办?

Carlos:先看是否符合我预先设定的结构。如果打开代码就认不出那些应该存在的东西,我宁可扔掉重做。我会在执行一两个小时后就暂停检查 Worktree;出了问题,就回到对话里查清是骨架、需求还是上下文信息相互冲突,再开新会话重试。

Patrick:为什么主张“代码便宜了,就应该经常推倒重来”?

Carlos:因为在我的经验里,Agent 对一次性完成较大任务比较擅长,对已有代码反复大改却不太擅长。既然生成代码的成本降低了,就可以并行探索不同方案,甚至让三个 Agent 分别开发、第四个 Agent 评估,不必为了保住已有代码而不断叠加补丁。

Patrick:如果人人都能靠 AI 写软件,还需要专业工程师吗?

Carlos:更需要工程判断。资深工程师要先厘清产品目标、架构、部署方式和安全边界,也要帮助新手学习这些取舍。我担心的一种情况是,我们培养了一代很会使用 Agent、却缺少独立开发能力的人。

Patrick:AI 生成的代码越来越多,代码审查应该看什么?

Carlos:除了最终 Diff,还应看前期需求和架构决策、每次提交如何推进方案,以及实际增加了哪些复杂性。可以借助静态分析、变异测试和新的可视化方式,但团队围绕 PR 的讨论不能因此消失。

Patrick:你怎么看 AI 的未来?这轮热潮会不会是泡沫?

Carlos:要分开看。AlphaFold、医学和材料科学等方向的突破让我觉得像魔法;LLM 在编程上的价值也很大,但巨额投入与产业承诺是否都能兑现,我有疑问。与此同时,权力向大型科技公司集中,以及 AI 是否真的缩小机会差距,也令我担忧。

1 开发者开始只和 AI 说话了

Patrick:今天的嘉宾是 Carlos Kelkboom,他是我认识的最出色的工程师之一。Carlos 你觉得跟几年前比,软件工程最大的变化是什么?

Carlos:首先,我观察到一个我不喜欢的现象:开发越来越像一个人的工作,同事之间的合作越来越少。过去大家重视拉取请求(PR,Pull Request),相互协作,也会在自己和同事的 PR 下交流意见;现在这样的交流越来越少,甚至有人说 PR 以后可能会消失。现在你经常和智能体一起工作,却不再和团队一起工作。这是我观察到的趋势,也是我认为很危险的一件事。

Patrick: 你觉得为什么会这样?我有个猜测,可能和我们在 Reddit、YouTube 上看到的情况有关。那里有很多独立开发者,往往是他们最先尝试新技术。当然,这也可能只是我的信息茧房,不知道这个观察是否准确。那么,在规模更大的企业里,开发团队依然有很多人,大家既要和 AI Agent 协作,也要和同事协作,实际情况又是怎样的?

Carlos:我有个好处,就是完全不用社交媒体。我连 Reddit 账号都没有,LinkedIn 也只是拿来和你联系。我不太关注社交媒体上的讨论,但我读很多东西,包括文章和白皮书,也跟很多公司和员工交流,所以我的印象不完全来自网上的展示。

我认为快速做出个东西却不收尾,和认真做一款希望能长期使用的产品,完全是两回事,这就像是马拉松和短跑的区别。一个人独立做项目,往往差最后一口劲把它真正做完;把东西放到社交媒体或 YouTube 上展示,和真正完成产品,也是不一样的。

比如,现在网上经常有人展示自己如何快速“做出”一款游戏。我之所以给“做出”加引号,是因为游戏开发最大的难点其实在于倾听玩家的反馈,并把游戏设计做好。这些事情当然也可以借助 AI Agent 不断迭代,但开发者仍然需要与外界交流。

与人沟通本来就是最难的事情之一,而现在,开发者可以待在自己的小圈子里,不怎么与外界交流,就能独自做出很多看得见的成果。这反而进一步强化了这种倾向。但开发软件时,始终需要想清楚两个问题:为什么要做这个软件?它是为谁而做的? 所以我才说,产品意识正变得越来越重要,但它恰恰也是当下被削弱得最厉害的东西。

Patrick:你思考过怎么解决这个问题吗?以我自己的经历来说,以前我觉得开始最难;有人说自己启动了很多项目却没做完,我一直不理解,因为我总是在有把握能完成时才开始。而现在,开始一件事对我来说从未如此容易。

Carlos:是的。

Patrick: 我用的工具有额度限制,界面上还有一个进度条。每到周末或者月底,我就总想着尽量把额度用满。甚至临睡前还会琢磨:要不做个游戏?我确实做过一些游戏,后来甚至还搭了一套能自动生成游戏的 Harness,让其他人也能用它来制作游戏,相当于在游戏开发之上又加了一层工具。我会试着解决一些自己预想未来可能出现的问题,看看最终能做出什么。但往往做到这一步就停下了,没有再往前推进:既没有把项目打磨到足够稳定,也没有真正完成,更没有把它做成可以出售的产品。我启动过很多项目,但真正做完的没几个。

Carlos: 不过,这种情况以前就有。我自己就做过大概五个编译器,每个都动手写了,也都差不多快完成了,但真正称得上做完的只有一个。软件开发一直如此:有了一个有意思的想法,想顺便学点东西,于是开始动手,最后却不一定能做完。

现在的区别在于,你得先想清楚为什么要启动这个项目。是为了学习?为了试验 AI Agent?还是为了真正做出一款产品?我觉得,现在开发者需要对自己做一件事的目的有更明确的认识。一旦目标清晰了,你刚才说的那种困扰也就没那么严重了。

如果你只是想玩一玩、找点乐趣,那你其实已经达到目的了。但如果你是想以此创办一家公司,那就必须把东西真正做完。

Patrick:说到这种情况,我发现自己和 AI Agent 好像也困在了一个小圈子里。遇到问题时,我第一反应往往是去问 Agent,而不是找你这样的同事交流。至少在我身边,这种工作方式已经很常见了。你觉得,开发者该怎么跳出这个圈子,更多地与其他人交流、协作?

Carlos:这个问题我已经想了很久。我觉得我们一起工作的方式、做软件的方式,恐怕都要改变。开源已经发展了这么多年,我觉得现在还得多办聚会,多分享经验,围绕具体项目共同工作。最好能够组织小组,成员愿意互相看看彼此的产品、提提意见。大家得重新走到一起,我们需要真正聚在一起合作。虽然待在自己的圈子里更容易,也得想办法降低门槛,让你更容易找到对你的项目感兴趣的人。

这也意味着我们需要更开放一点,不要害怕把想法讲出来。人们常说点子不值钱;放到全世界来看,点子也许确实不稀缺;可对想到它的人来说,它很珍贵,也很私人。分享想法时,人们可能担心被别人抢先实现,也担心自己的想法不够成熟。要消除这种顾虑,就需要一个包容、愿意互相支持的社区。我想到一个例子:最近推出的《魔兽世界 Forever》,不知道你有没有听说过。人们在测试版里问一句“这个设置怎么关”这样很基础的问题,也会有四五个人来帮你。做软件的人需要这样的互助氛围。

Patrick:但我看到的趋势是大家都会选择去问自己的智能体,似乎没必要问人了。有些人本来就不愿意回答那些他们觉得太简单的问题。我甚至听过一句话:“先问你的智能体,再来问我。”这话有些好笑,却也让人感到不安。我感觉大家比过去更容易怀疑自己的能力,即使智能体可能把人带偏,或者让人看不到全局,大家也更倾向于依赖智能体指路;从学习的角度看,只和智能体交流,学到的东西可能不如和人讨论时多。

Carlos:是的,问人确实慢,因为你无法立刻得到答案。智能体则能立即回应,而且往往倾向于给出你希望听到的答案。你可以同时问几个模型,让它们互相质疑,或者设计一套对抗式的流程,多少能缓解这个问题。但这会带来一个更深的变化:你会越来越习惯只和这些立刻回答的机器交谈,不再留时间给自己安静地想。那些纷乱的念头,本来得在经过一段时间的沉淀,才能慢慢理清,从而让你生出新想法,或者让你发现原来还有另一条路可以尝试。

等会儿我们可以聊聊我具体怎么用智能体写软件,但创造力这件事值得我们先讨论。John Cleese 讲过创造力的开放模式和封闭模式:进入开放模式,首先得进入一种开放、平静的心理状态;什么都不做,让纷乱的想法逐渐沉淀,才有可能真正放开思路。可社交媒体、AI 和智能体却持续提供新的信息。我们几乎没有时间坐下来,闭上眼睛,整理自己的想法。

Patrick:这有什么坏处?我有问题只要向智能体提问,马上就能得到答案,紧接着处理下一个问题,一路往前赶。我一直觉得做软件就是要快。有了智能体,我们推进得更快;虽然也更容易出现故障,但修起来也快。速度在我看来还是很重要的。如果我不坐下来想清楚自己在做什么,那我会失去什么?

Carlos:我认为代价是学到的东西变少了。知识需要经过思考和消化,才能真正被掌握。让智能体直接生成代码,自己不一定学到了什么。以前认真学过、如今会用智能体的人,会比未掌握基础、仅依赖智能体的人更有优势。工程实践的乐趣,本来就在于不断学习:进入陌生领域,读一份新规范,学一门语言,试一个新框架。JavaScript 为什么会有那么多框架?也是因为做框架的人一路从别人那里学到了东西。而要真正做到这一点,必须给自己时间去消化。

Patrick:那我学习怎么操作智能体,学习相关领域知识、为智能体准备的各类配置和说明文件,以及不断出现的智能体工作框架的新功能,从长远看,这也算学习吗?

Carlos:当然算。

2 先搭骨架再让 AI 写代码,效率可能差 10 倍

Patrick:那你从智能体身上学到的最重要的一点是什么?具体工作时,你又是怎么把它用好的?

Carlos: 这其实是两个不同的问题。先说我是怎么与 Agent 协作的吧。现在,我会先亲自搭好代码骨架:建立目录结构和文件,在文件里写一些注释,有时还会提前写好类名、函数名或函数签名。这些内容不需要特别规范,写个大概就行。关键是通过这些准备工作,明确告诉 Agent 我想要怎样实现,让它按照我设定的方向去写代码。

因为我发现,Agent 很擅长沿着一条路径快速解决问题,甚至可以说是暴力求解,但它经常忽略这些代码该如何融入应用的其他部分。结果就是代码重复、模块内聚性差,甚至出现“上帝对象”(God Object)等问题。这些都是我们不希望看到的,因为它们会让代码越来越缺乏灵活性。

所以,我现在都会亲自搭建这套骨架。这个过程可能花 20 分钟、半小时,有时甚至要一个小时。比如开发编译器时,我会先规划目录结构,写一个词法分析器(Lexer),再写一点语言规范。我还会提前设计好抽象语法树(AST)如何转换为中间表示(IR),并通过目录和文件结构体现这些设计,再用我想实现的语言写出大量示例。有了这些准备,Agent 就能非常出色地生成符合我要求的编译器。

Patrick: 因为你提前搭好了代码骨架?

Carlos: 对,没错。我也试过完全不做这些准备,直接让 Agent 从头到尾自己写。结果做上一两个月,就会明显感觉越来越难推进:Agent 的速度变慢了,生成的东西也越来越不符合预期,有些功能开始出问题。打开代码文件时,你甚至已经认不出自己的应用了,完全不知道中间发生了什么。

这种情况我遇到过很多次。比如,项目原本有一个部署脚本,但不知道为什么,Agent 突然决定不再使用它,反而另外创建了好几个脚本,最后谁也不知道这些脚本到底是干什么的。

所以,不要跳过前期的结构设计,而且必须非常明确地告诉 Agent 你希望它做什么。我认为,这种能力可能就是区分 10 倍效率和 100 倍效率的 Agent 工程师的关键。

Patrick: 但要做到这种有意识的设计,我得依靠过去积累的经验。我对项目结构确实有自己的判断,不过主要限于那些我熟悉、亲手实践过的编程语言。如果现在让我做一件完全没做过的事,比如开发编译器,我该怎样培养这种能力和品味,才能判断什么样的代码骨架才是好的?

Carlos:好问题。在智能体出现之前,你会怎么做?

Patrick:我会向有经验的人请教。我过去不喜欢从零启动项目,工作里接触的大多是已经启动的项目。有了现成约定,我通常能高效开展工作;可让自己从头建立项目约定,我没怎么尝试过。我会找那些擅长做这件事的人,一起做,问他们哪些决定最重要。因为没有亲手反复做过,这些经验也没有真正的内化。但是现在再遇到这种事,我大概会先问智能体。如果还是卡住了,也依然会找人帮忙。

Carlos:如果是现在,我会这样做:面对一门完全陌生的语言或一个新领域,我先去找做得不错的开源项目,下载后研究。如果你更愿意待在“智能体的小圈子”里,也可以让它对照几个项目,找出值得学的做法。用 Claude 之类的工具,还可以准备一些“追问我”“教教我”这样的技能:让它讲清这些项目的基础,哪里做得好、为什么好,哪里有问题。花上一两天,你对好的、坏的做法多少会有感觉。然后我通常会出去拿杯咖啡,坐下来独立思考,整理刚学到的内容。遇到不明白的地方,再回去提问,之后继续思考。

只有当我对想做的事有了比较清楚的感觉,才会从很小的概念验证开始,搭一个骨架,请智能体评估:这样搭可行吗?能同时解决刚才提到的两个问题吗?就这样来回琢磨,直到心里感觉对方有了底,才让它动手实现。这些年我学到的一点,就是不要贪图马上看到成果的那一下快感。

Patrick:照我的理解,如果我没有先搭建骨架,智能体就会自行决定代码结构。它能积极完成眼前的任务,却未必能充分考虑结构是否合理。

Carlos:没错,而且它也不管你将来想要什么,只顾着把你眼下提出的要求硬做出来。

Patrick:可软件以后总是会变的。你是这个意思吗?

Carlos:做软件,唯一不变的就是变化。就拿编译器来说,没人会写完一个编译器就觉得大功告成了,它总会不断演进。可能需要增加新的语言特性,也可能要调整优化方式。

举个我自己的例子。我曾经开发过一个编译器,最初只实现了一套很简单的列表机制,后来想进一步扩展它。当时我已经和 Agent 一起开发了大约一个月,而且用的是一门我不太熟悉的编程语言。最后,我让 Agent 回过头来检查列表功能,结果它告诉我:同一个列表功能竟然被重复实现了五次。

如果只是让 Agent 一路埋头写代码,就很容易出现这种情况。后面当然可以通过不断迭代来清理和重构代码,但前提是,你得先能识别出问题在哪里。

Patrick:对,这恰恰是我觉得最难的地方。我很喜欢你刚才提到的方法:先看看开源社区里有哪些现成的实现,了解好的设计模式,再让 Agent 帮你解释这些东西,让自己真正理解其中的原理。

你可以不断向 Agent 追问,直到把自己好奇的问题彻底弄明白,再消化吸收这些知识,然后才开始动手。我觉得自己平时还没有充分利用这种方式,但以后如果要用一门不熟悉的语言开发项目,我想试着这样来设计代码骨架。

毕竟我掌握的编程语言没你多。如果我不熟悉一门语言,能不能先通过和 Agent 讨论来完成这些准备?这样开始是否可行?你会有什么建议?

Carlos:当然可以。你可以先问它:“这门语言最重要的理念是什么?能不能拿我熟悉的语言来类比讲讲?”比如你会 C#,想学 Go,就问:“我会 C#。要写出符合 Go 语言惯例的代码,我需要改掉哪些习惯?两门语言差在哪儿?我现在的写法哪里不对?”然后自己先写点东西,哪怕只是几段注释和一个很粗的结构,写错也没关系。智能体可以帮你改。先请它看看你搭的架子,它通常会直接指出这里不对、那里不对,然后你再提出质疑,和它继续讨论。

Patrick: 你觉得现在还有必要学习编程语言吗?

Carlos: 我觉得,我们可能很快就需要一门全新的编程语言了。我知道很多人都这么说,但我确实认为,编程本身有几个根本性的东西需要改变。

首先,我认为应该彻底抛弃堆内存(Heap)。我们不再需要指针、动态内存分配,以及围绕它们建立的那一整套机制。我希望未来的编程语言具有很强的确定性,而且可以分为三个层次。

• 第一层是人类编写的代码,可以把自然语言和某种结构化语言结合起来。甚至不需要太复杂的语法,也许只要有一个 component 关键字,再加上组件名称就够了。然后在组件内部,通过缩进和类似 Markdown 的写法,描述这个组件应该完成什么任务。

• 第二层是某种中间表示,可以是图表、视频,也可以是其他直观的视觉或音频形式。Agent 会通过这些形式,向你解释它理解的目标是什么。开发者则可以通过语音或其他方式提出质疑、进一步明确要求,再把这些反馈转化回第一层的描述。

• 最后一层才是真正运行在机器上的程序表示。我认为,这一层应该抛开传统编程中许多沿用至今的假设。

具体来说,while 语句和其他循环都应该有明确的执行边界,还可以采用 Actor 模型。我们应该真正摆脱堆内存,重新采用基于记录(Record)的数据结构,或者过去被称为 Plex 的那种结构。

最终,我们需要重新获得一种能力:能够清楚地推理自己的机器上究竟在运行什么,而不是像现在这样,面对大量难以预测的程序行为。

Patrick: 你之所以强调确定性,主要是因为现在的程序存在太多不可预测的行为吗?

Carlos: 对,但还有一个原因:如果采用这样的运行时,性能也会非常高。

另外,现在的计算系统其实有些割裂。比如,为 GPU 编写程序和为 CPU 编写程序,往往需要采用完全不同的方式。CPU 针对分支预测、数据预取等做了大量复杂优化,而 GPU 的计算模型相对直接,也更具有确定性。你分配一块内存,填入数据,再在上面执行一些计算,整个过程就完成了。按照这种模型,不需要那些围绕堆内存和动态分配建立起来的复杂机制。

要让 GPU 适应 CPU 的那套编程方式很难,我也不认为这是正确的方向。我觉得我们应该反过来,让 CPU 向 GPU 那种更具确定性的计算方式靠拢,同时保留 CPU 所需的不同计算能力。 这样,我们就能更充分地利用 SIMD(单指令多数据)等能力,也能支持不同的数据结构。比如需要处理图结构时,就可以把它映射到合适的表示形式上。

这就是我认为未来编程语言需要具备的核心特征:高度确定性。

我刚才可能还没解释清楚,为什么确定性这么重要。想象一下,你把一颗卫星送上太空,它的内存容量是有限的。如果程序运行时还在不断进行堆内存分配,就可能出现内存不足异常,或者空指针异常。你肯定不希望卫星在太空中遇到这些问题。

而现在,软件正在越来越多地应用于机器人、卫星、机器学习等领域,我们需要尽可能确保程序的运行行为是可预测的。如果一台设备只有 2GB 内存,你就应该能够明确知道,这个应用在任何情况下都不会超出这个限制。所以我才认为,我们不能再继续依赖动态内存分配了。

Patrick:我觉得这可能也是为什么,至少在卫星这类场景里,很多人会选择 Rust。因为我理解,Rust 能让开发者尽可能在早期发现这类问题。

Carlos:Rust 还有一套规范,通过限制可使用的语言特性,让程序行为更具确定性。不过,真要靠人手写,确实挺费劲,至少我自己的体验是这样。

Patrick:那你试过让 Agent 写 Rust 吗?

Carlos:试过。写起来比很多其他语言慢一些,但也挺有意思。Agent 其实很擅长写 Rust,只是它们拆分代码的方式往往不符合我的预期。而且,我一直觉得 Rust 代码后期很难修改。一段 Rust 代码只要能正常运行,我就不太想再碰它了,觉得这样就算完成了。相比之下,其他语言重构起来要容易得多。

当然,这只是我个人使用 Rust 的感受。我并不想劝大家放弃这门语言。Rust 是一门设计得很出色的语言,拥有很多现代编程语言应该具备的特性,比如可辨识联合类型(Discriminated Unions)等。但在我看来,借用检查器(Borrow Checker)本质上是为了管理堆内存中的数据。如果我们彻底取消堆内存,也就不再需要借用检查器了。

想象一下,如果有一条记录(Record),它在内存中的位置是固定的,而且从程序启动开始,所有数据就已经安排好了。这样,你只需要知道记录的起始位置,再通过偏移量定位各个字段,就能非常快速地访问数据。

Patrick: 有意思。那你设想的这种新语言,最终会是一门统一的语言吗?大家会逐渐收敛到同一种语言上吗?

Carlos:这正是我提出三层结构的原因。我认为最终生成的代码,以及底层运行时,可以是统一的,但中间各层基本上都可以像插件一样自由替换。甚至可能发展到这样一种程度:每个人只需要和自己的 Agent 对话,就能定义出一门属于自己的编程语言。

Patrick:不过,这又让我想到一个问题。我在想办法提高 Agent 的工作效率时,经常遇到一个难题,其实人与人之间、不同团队之间,甚至组织的不同层级之间也一样:大家如何使用同一套语言交流?比如我说“组件”,在 Agent 的语境里究竟是什么意思?是自定义 Agent、本地 Agent,还是主 Agent 下面的子 Agent?不同的人可能有完全不同的理解。如何建立共同语言,一直是个难题。而按照你设想的未来,每个人都可能有自己的编程语言和交互方式。那大家又该如何建立一套彼此都能理解的共同语言?

Carlos:这可是个价值百万美元的问题。说说我自己的看法吧。回到二十年前,如果我要开发一套 CRM 系统,大家其实不会一直争论“客户”到底是什么,因为数据模式(Schema)已经明确规定了“客户”的定义。真正困难的是,怎样形成这套 Schema,以及之后如何让它不断演进。但在某个阶段,这套 Schema 就是大家对“客户”的共同定义。所以,最难的是先达成一个初步共识,再在此基础上不断迭代。

如果我没理解错你的问题,我觉得我们应该从比现在简单得多的东西开始。比如,哪怕一开始只规定“客户有一个 ID”,大家也能立即达成共识:没错,客户当然需要一个 ID。然后我们就可以在此基础上逐步完善。数据建模已经为我们提供了很多现成的方法。比如星型模型,或者分别从销售和营销的角度建立客户模型。我们可以有不同类型的模型,满足不同的需求。

但关键在于,共识不应该只是某个时间点上确定下来的东西,我们还需要就它未来如何演进达成共识。

过去软件开发的速度比较慢,人们更关注眼前要做什么,而不是系统今后如何演进。这也是为什么我觉得,今天的敏捷开发已经不像它原本应该有的那样敏捷了。这个问题我们之前讨论过很多次,我觉得敏捷开发在某种程度上已经偏离了初衷。而现在有了 Agent,我们或许可以重新回到敏捷开发最初的理念:先从一个简单的起点出发,然后快速迭代、不断演进。

Patrick:这个观点很有意思。

3 AI 让代码不值钱了,但工程经验越来越重要

Patrick: 我们聊了这么久 Agent 辅助编程,我还真没想到,提前搭建代码骨架竟然是这么关键的一步。因为至少在我身边,有些人的工作方式完全不同。他们会说:“我已经很久没看过代码了。”他们觉得最高效的做法,就是让 Agent 包办所有事情,自己根本不用看代码。最后要么请其他人审查 Agent 生成的代码,要么让多个 Agent 进行对抗式审查或盲审。这些人一直在摸索、调整自己的工作方式,希望即使不亲自阅读代码,也能保持很高的效率。但显然,你不是这么做的。

Carlos:确实不是。而且说实话,我甚至不太理解这么做有什么乐趣。当然,如果你是在开发一款准备拿去卖的产品,想靠它赚钱,需要尽快推向市场,那我能理解。可如果只是为了自己做点东西,我就不明白了。你让 Agent 去干活,自己出门逛个街、看场电影,回来看到 Agent 交付的成果,就觉得很满足?我实在体会不到这有什么乐趣。

Patrick: 拿我自己来说吧,有时候我想要的就是最终结果。我未必在乎这个结果是怎么实现的,代码写成什么样,或者将来好不好维护。我只是想得到那个东西。

Carlos:可你刚才不是还说,自己启动了很多项目,却没几个真正做完的吗?那这两件事怎么解释?

Patrick:因为有时候,我确实没能得到最初想要的结果。我可能突然想到一个问题,琢磨该怎么解决,然后就让 Agent 花一整晚去研究。我觉得这种习惯也和工具的使用额度有关。我每周都有一定的额度,如果没用完,就总觉得浪费了自己花钱买来的东西,有种错过了什么的感觉。所以我总想着尽量把额度用足,尤其现在,我觉得以后可能还会更贵。

于是,一遇到什么问题,我就想:不如先扔给 Agent 试试,看看它能做出什么。然后我再去探索、研究它生成的东西。有时候虽然没达到最初预想的目标,但我至少学到了一些东西,或者摸索出一些组织任务、使用 Agent 的新方法,也算有所收获。这就是我现在的工作方式。

举个例子。有一次,公司给了我们一天的创新探索时间,可以自由做任何想做的项目,我就利用那一天搭了一套能够生成游戏的 Harness。我之前在一场会议上看到 Google 展示过类似的东西,当时还问他们:“你们打算开源吗?我很想让身边的人也试试。”

因为我有个比我小 16 岁的弟弟,他不懂编程,但我觉得他一定会喜欢自己做游戏。如果能给他这样一套工具,让他通过语音输入描述自己的想法,就能生成游戏,那一定很有意思。可 Google 后来并没有开源,所以我就想,那干脆自己做一个吧。于是我真的动手做了。对我来说,最终想要的就是这样一套工具,至于底层代码具体怎么实现,我其实没那么在意。

当然,我也会深入考虑一些细节,比如生成的游戏应该是什么效果、什么风格,要不要使用模板引擎,以及如何保证结果的确定性。这些才是我真正投入时间和精力的地方。比如,用户提出一些具体的游戏功能需求,我就希望通过这套 Harness 生成的游戏,能够尽可能符合他的预期。

后来,我弟弟真的用它做出了一个游戏。我又针对那个游戏做了不少深入的调整和完善,之后他又做出了更多游戏。我还把工具交给了我的伴侣,以及其他不懂编程的人,他们也都能用它来制作游戏。而在整个过程中,我其实并没有怎么查看代码。但我已经得到了自己想要的结果。

Carlos:但这完全没问题啊!因为你的目标本来就不是学习怎么开发游戏,也不是学习怎么写游戏引擎。你只是想让身边的人开心,看到自己在乎的人露出笑容。这是件很美好的事。如果一款百分之百靠 Vibe Coding 做出来的应用能实现这个目标,那就尽管这么做,完全没问题。

不过,你做出来的东西,和一支专业团队精心打造的游戏,肯定还是有区别的。当然,就算是专家团队花费大量心血制作的游戏,也未必能让玩家满意。玩家可能花了 50 欧元买游戏,玩完却觉得:“我花了 50 欧元,就买了这么个东西?”

我想换个角度问你:如果当时和你一起开发这套 Harness 的,是一位拥有 25 年经验的游戏设计师或游戏工程师,结果会有什么不同?

Patrick:有意思。如果当时能和这样一位经验丰富的人合作,我想我会更深入地研究一些技术和设计上的问题,因为我觉得自己能从中学到很多东西。比如,我和 Agent 为了尽快得到结果而做出的那些选择,到底是不是明智的?

假设我已经做好了这套 Harness,现在想把游戏画面彻底升级一遍。有些生成的游戏虽然采用了复古风格,但画面看起来还是比较粗糙,像素感很重。我也见过那些 3A 大作,知道高质量的画面能给玩家带来怎样的体验,所以会想在这方面再深入一步。但我不确定,光靠自己和 Agent 能不能做到。如果有一位经验丰富的合作者,也许我应该在项目早期就把这些问题提出来,和他一起讨论,把相关的设计考虑提前纳入决策。

不过,现在这么说出来,我又有点犹豫:这样会不会反而过度设计了? 毕竟,我很喜欢自己当时能够快速做出成果,而且确实把东西交付给了用户。后来我也更新过模板和图形部分,中途还卡住了,不得不把之前做的东西全部推翻重来,第二次才成功。所以,也许有些问题确实应该更早考虑。

Carlos:你刚才描述的,其实就是在搭建代码骨架。你先确定哪些部分最重要,把它们的结构设计好,再通过这套骨架告诉 Agent 应该优先考虑什么。软件开发一直是这样。过去开发一套 CRM 系统,第一版可能先从界面入手,后来发现数据库也很重要,于是第二版就会更关注数据库设计。接着又发现,数据库虽然设计好了,但用起来很复杂,于是下一版开始更多地调整应用层。我一直说,一个应用往往要做上三四遍,就是这个意思。每次重新来过,都会让它变得更好。

Agent 编程也是一样,但前提是你愿意停下来,回头看看自己做了什么,想清楚哪些地方需要改变、哪些方面值得投入更多精力,这样下一次迭代才可能做得更好。不过,我发现 Agent 编程发展到一定阶段就会遇到瓶颈,因为 Agent 还不擅长彻底推翻一个旧的设计,再重新实现。它往往只会在原来的基础上不断打补丁,甚至在同一个代码库里把同一套东西重复实现两三遍。Agent 擅长写代码,但还不擅长从工程层面构建一个完整的应用。

所以,你不妨拿之前那套游戏生成工具再做一次实验。这次先搭好代码骨架,建立几个目录,在里面放上 Markdown 文件,说明每个目录负责什么、模块之间的依赖关系应该是怎样的。我不太了解游戏引擎的具体设计,但比如你可以指定用 raylib 开发一款 2D 平台游戏,把素材放在哪里、各部分应该如何组织,都提前写清楚。然后再让 Agent 从头试一次。我觉得这样不仅能做出同样好的结果,速度可能还会更快。

Patrick:听你这么说,我就在想,这中间的界限到底在哪里?什么时候应该花时间提前搭建代码骨架,什么时候可以直接奔着结果去?也许取决于我打算把项目做多远。如果准备长期投入、深入开发,那就值得先打好基础;但如果只是想快速验证一个想法,那不看代码、不搭骨架也没什么问题。比如最初做游戏生成工具时,我完全可以把第一版当成概念验证,先看看能不能做出来,再把它扔掉,从头做一遍,看看后面能不能不断迭代、走得更远。我挺喜欢这种思路。我们平时似乎很少主动丢弃已经写好的代码,我做过的东西几乎都还留在 GitHub 或电脑里,只有尝试失败了,才会把它们扔掉。

Carlos:没错,这也是 Agent 现在带给我们的改变。代码越来越便宜了,所以可以快速迭代,经常推倒重来。 我还发现一个挺有意思的做法:创建三个 Git 分支,让三个 Agent 分别在各自的分支里开发,也可以使用 Git Worktree,让它们并行尝试不同方案。然后再找第四个 Agent,对比前三个 Agent 的成果,只把好的部分合并进来。

Patrick:相当于先同时探索几条路径,还能从不同方案里学到东西。你前面说,提前搭建代码骨架是提高效率的关键。那骨架搭好之后,Agent 就能一路顺利完成开发吗?你的工程工作流里还有哪些重要环节?

Carlos:代码骨架真的非常管用。不过我得承认,我自己通常会搭得比建议别人搭的更深入、更细致。

比如开发 Rust 应用时,我会先创建好各个 Crate;开发 C# 应用时,我会先建立项目、给项目命名,再放一些 Markdown 文件,说明每个项目的职责边界。我还会快速画一张架构图,标明这里需要实现什么功能、那里负责什么,同时提前建好目录结构和一些核心文件。

就像之前说的,开发编译器时,我会先创建词法分析器(Lexer)的文件,甚至提前写好函数签名。这意味着,我已经认真想过 Token 应该采用什么样的数据结构。

如果不提前定义,Agent 可能就会自行生成一个枚举,列出所有 Token 类型,再附带一些简单的源码位置信息。但我希望 Token 的定义更具体,比如它来自哪个源文件,从文件的哪一行、哪个位置开始,到哪一行、哪个位置结束。把这些要求提前体现在代码骨架里,Agent 最终生成的代码就会更符合我的预期,我以后也更容易理解和分析这些代码。而且,Agent 很乐意沿着我提前设定的结构继续实现。

Patrick:你有没有什么开源项目,可以放在节目备注里,让大家看看你具体是怎么搭建代码骨架的?

Carlos:有,不过我暂时还不太想公开。我们刚才讨论的那门新编程语言,就是我现在正在开发的项目,而且完全是用 Agent 来做的。我很愿意让大家看看,但它还处在非常早期的实验阶段。人们对一件事物的第一印象往往很难改变,所以我有点犹豫:如果现在就让大家看到这个项目,却不了解我背后的想法,也不知道它未来会如何演进,可能会产生误解。也许我应该在 README 里放上这期播客的链接,让大家先了解这些背景。

Patrick:这其实又回到了我们刚才讨论的“共同语言”问题。你说要搭建代码骨架,我原本觉得自己理解这个概念,但后来听你讲到具体会搭到什么程度、会提前确定哪些东西,才发现你的做法比我想象中深入得多。所以我才想看看真实的项目是什么样的。对了,我之前还和另一个人聊过,他也在思考未来人们会如何开发软件。我可以介绍你们认识,感觉你们应该会聊得很投机。

Carlos:那挺好的。我还觉得,现在整个软件行业可能到了一个需要重新行动起来的时候。我不太想用“革命”这个词,但如果软件开发真正变得更加普及,让更多人都有能力开发软件,那我们也应该利用这种能力去帮助更多的人。

我很想发起一个组织或者社区,把有实际软件需求的人和愿意动手开发的人连接起来。比如某个群体遇到了困难,需要软件帮助解决,而另一些人手头正好有一些富余的 Agent 使用额度,就可以利用这些资源为他们开发真正需要的工具。举个例子,我知道有些人很难获得轮椅,或者需要等待很长时间,也许就有人能通过开发软件帮忙缓解这个问题。但前提是,我们得先把这些实际需求收集起来,清楚地整理在一个地方,让开发者能够挑选自己有能力解决的问题。

现在软件开发的门槛降低了,几乎人人都可以开始尝试。但我们还需要有经验的工程师参与,帮助这些新开发者理解一些基本的工程要求,比如安全措施。如果你没有明确要求 AI 检查代码安全性,或者进行渗透测试,它通常不会主动完成这些工作。所以,我们需要让专业工程师与那些希望通过软件帮助社区的人建立联系。我觉得整个行业都应该把更多精力放在这件事上。过去那种“我们是专家,只有我们才能开发软件”的观念,现在已经行不通了。

Patrick:确实,现在开发软件的门槛一下子降低了很多。人们可以很快上手,把各种想法变成实际成果。但我觉得,在这个行业里工作过一段时间的人,多少已经知道哪些做法是好的、哪些可能有问题,而新一代开发者还没有形成这样的判断力和直觉。

Carlos:是的。而且,如果再看看学校里工程专业、软件工程专业的人数下降的情况,就更让人担心未来会变成什么样。我们现在已经不怎么培养初级工程师了,只是直接让他们使用 Agent。甚至连完整的 PR(Pull Request)评审流程都不再走了。以前大家会在代码审查中留下评论,认真讨论软件质量,互相交流为什么某种实现更好。现在这些事情越来越多地交给 AI 完成。

我最担心的是,我们正在培养一代只会使用工具、却没有真正学会如何开发软件的人。如果有一天,Agent 的使用额度变得非常昂贵,贵到大家用不起,或者 AI 因为某种原因突然无法使用,那会怎么样?我们依赖的整个体系可能都会崩塌。这个想法真的很可怕。

Patrick:你觉得真的会这样吗?AI 会不会只是一场泡沫,等泡沫破了,就什么都不剩了?

Carlos:说实话,我觉得这里面有三个不同的层面。首先,AI 确实带来了革命性的突破。比如 AlphaFold、Google 正在做的细胞相关研究,还有医学、材料科学领域的进展,都让我感到非常震撼。机器人、自动驾驶也是如此。在我看来,这些才是真正展现 AI 能力的地方。我还跟孩子们聊过这件事:我已经在没有这些技术的世界里生活了 47 年,现在突然进入了这样一个时代,该怎么形容这种感受?我能想到的词只有一个——魔法。

然后是大语言模型。LLM 当然也非常了不起,但它们的资源消耗很大,能源利用效率也不高。各家公司投入了巨额资金,行业也作出了很多承诺,可这些承诺究竟能兑现多少,我并不确定。所以,尽管 LLM 在编程方面带来的帮助确实非常大,我仍然觉得围绕它们的热潮带着炒作和泡沫的成分。

第三个层面是权力格局的变化。看看如今最有钱、规模最大的公司,几乎都是科技公司。尤其从隐私和安全的角度来看,这让我感到不安。

Patrick:具体让你不安的是什么?

Carlos:AI 一直被宣传成一种能够缩小差距、让机会更加平等的技术。但到目前为止,我并没有看到它真正缩小了这些差距,也不确定将来能不能做到。

Patrick:也就是说,未来可能是富人越来越富,而人与人之间的差距并没有缩小?

Carlos:对。我真的不知道这一切最后会走向哪里。

Patrick:说实话,我现在有一种挺奇怪的感觉,因为我以前从没亲身经历过这样一场技术变革。互联网刚兴起的时候,也许有人体验过类似的变化,但我没有。所以我不知道,现在这种感受和当年是不是一样。如今行业变化实在太快了,哪怕出去休假两周,回来都可能发现自己错过了某个新东西,而它已经彻底改变了人们开发软件的方式。

无论以后我的工作怎么变,哪怕越来越偏向管理、不再经常亲自写代码,我依然很认同自己软件工程师的身份。有时我甚至会想,自己还配不配得上这个称呼,但从自我认同上说,我始终觉得自己是一名软件工程师。

更奇怪的是,身处同一个行业,大家对变化的感受却很不一样。有些人通过社交媒体等渠道追踪每一项新进展,几乎什么都不想错过;另一些人还是照常做每天的工作,觉得这些技术暂时还用不到自己身上,也许只是泡沫,生活并没有太大改变。现在行业里存在着很大的这种差异。

Carlos:是的。不过对我来说,这最终还是要回到学习上。早期几代 ChatGPT 刚出现时——我记不清具体是哪一代了——我买了一本机器学习的书,自己动手搭建神经网络。很快我就发现,我做的网络远远比不上那些大模型,也因此认识到规模确实很重要。但整个学习过程让我收获特别大。

我并不是说,学完这些就能自己造出一个大语言模型。如今构建大模型早已不只是神经网络本身的问题,还涉及围绕它的一整套技术体系。不过,学习基础知识,弄明白这些技术大致是怎么运作的,会给你一个非常扎实的根基。有了这样的基础,你就不会因为休假两周而觉得自己错过了什么。我甚至觉得,如果假期过得不错,你回来时的收获可能比出发前还多。

Patrick:对,我还是会照常休假的。说回来,我们最开始聊的是软件工程的工作流程,我还想把这个话题再深入讨论一下。

4 主 Agent 不准碰代码,生成的代码看不懂就舍弃

Patrick:你之前说,提前搭建代码骨架能显著提高效率。我最近还听到一个叫“循环工程”(Loop Engineering)的概念,我的理解是,整个循环既需要推动任务向前的力量,也需要在方向偏离时把它拉回来的约束。搭骨架就像是在正式开始前先确定方向。那么,后面的约束是怎么实现的?你会不会设置一些明确的执行路径或工具,让 Agent 始终待在你划定的边界内?还是说,只要骨架搭好了,它自然就会照着做?

Carlos:当然会,我也做了不少这样的工具。不过麻烦在于,每次有新模型出来,我几乎都要重新设计一遍。我总是尽量从第一性原理出发:如果要让 Agent 作出判断、与你交流,它首先需要知道什么?由于上下文会不断重置,你得持续为它补充信息;但上下文又不能无限膨胀,否则 Agent 的表现会变差,成本也会越来越高。

所以,我借鉴了社交网络的思路来设计自己的 Harness。先找到与当前任务有关的信息连接和重要节点,再给每个节点附上一点元数据,比如一句话摘要、一个 Git 提交哈希,或者能找到更多资料的目录路径。随后按照这些信息与当前任务的相关程度重新排序。必要时还可以让人参与确认:“你要找的是这个吗?”确认之后,Agent 才沿着线索继续深入,最终找到相关的提交历史和代码,弄清楚发生了什么。

我还有一个习惯:总是先让 Agent 查看某次提交的差异(Diff),再去读完整的代码文件。我发现,先看改动能很好地帮助它建立上下文,就像是在真正阅读代码之前先热身。

Patrick:有意思。我知道“渐进式披露”(Progressive Disclosure)这个概念:先给 AI 留下一些线索,让它顺着线索逐步展开,找到需要的信息。但你的做法似乎又深入了一层:面对大量分散的信息,你会先做相关性重排,甚至在读完整文件之前先查看提交记录。这些都已经设计进你的 Harness 里了吗?

Carlos:对。

Patrick:也就是说,先看提交记录,再通过渐进式披露和相关性重排,一步步找到正确的信息。

Carlos:对,而且这些信息是分布式存放的。比如,我把负责检索资料的 Agent 叫作“研究 Agent”,虽然它做的事情还算不上真正的研究。它会查找本地文件、网站等不同来源。就像刚才说的,每条信息先提供一句简短说明,再附上目录结构、路径、哈希值或者 URL,需要时就可以沿着这些线索继续深入。说到底,这就是一张信息关系图,很适合逐层检索。

Patrick:但你并没有把它们放进图数据库,而是让这些关联在使用过程中自然建立起来?

Carlos:没错。我不用图数据库,就是为了让信息保持分布式。目前,我用 Markdown 文件表示节点,再结合索引检索以及 Markdown 文件头部元数据(Front Matter)中的关键词搜索,来查找节点之间的关联。我还在摸索怎样把这些机制和路径结合起来,管理所有信息。不过目前这套方法运行得不错,也确实很有价值,因为我还按照同样的思路组织了 Agent 的分工。

我最先对话的主 Agent 始终处于一种“开放模式”(Open Mode):它不会直接修改代码,也不会对本地开发环境做任何改动,只负责和我交流。我可以教它一些东西,也可以让它教我。对话中形成的信息会重新写回那张信息关系图,方便下次会话检索。等到充分理解任务之后,它才会启动子 Agent 去执行具体工作。我希望它在真正动手之前尽可能多地向我提问,再把它对任务的理解复述给我,供我确认。

Patrick:那这是不是意味着,你不会同时运行多个主 Agent 的工作循环?还是说你也会并行运行?

Carlos:会,我也会同时运行多个主 Agent。

Patrick:也就是说,你平时对话的主 Agent 不会修改代码,也不会改动文件系统。需要实际执行任务时,它才会启动其他 Agent。但与此同时,你也会并行运行另一个遵循同样规则的主 Agent 会话?

Carlos:对。

Patrick:有意思。那你为什么要默认禁止主 Agent 修改文件?它们明明有这种能力,而且非常积极,总想主动做点什么。但你却有意限制了它。为什么?

Carlos:因为我希望它专心回答我提出的问题。我之前做过一个游戏引擎。有一次,我在那个项目里问 Agent:“你怎么看 John Cleese 关于创造力的开放模式与封闭模式的演讲?”结果它反过来问我:“要不要我把这个实现到你的项目里?”

那一刻我突然意识到,它满脑子想的只有一件事:能不能帮我写代码?如果它只想着替我写代码,又怎么可能认真回答我的问题? 所以后来我干脆给它设了硬性限制:先好好跟我对话,不要急着动手。

我还设计了一套评分机制,会让几个模型参与评估,其中包括一个在本地后台运行、负责评分的 Gemma 模型。只有当主 Agent 对自己已经理解我的意图有超过 90% 的把握时,才可以向我提议启动子 Agent。

等子 Agent 真正开始执行后,它们可以一直做下去,运行 12 个小时也无所谓,同时启动多个也没关系。但在主 Agent 非常确信自己理解了我的要求之前,绝对不能开工。

Patrick:有意思。你现在会不会把更多工作放到 Agent 开始执行之前?比如一个想法可以只涉及某项功能的一部分,也可以是需要深入设计的一个界面,或者一整套功能。你通常会把任务拆得很小,还是尽量一次做大?

Carlos:我会尽量做大。因为我发现,Agent 不太擅长修改已有代码,却很擅长一次性完成任务。感觉它们接受的训练更偏向一次把事情做完,而不是在同一个代码库里持续迭代开发。至少我从一些基准测试中看到的是这样。

Patrick:真的?那我得把之前采访 Dex Horthy 的那期节目发给你。他提出了“上下文工程”(Context Engineering)这个说法,还向我介绍过一个叫 Slop Code Bench 的基准测试。它测的正是这种连续的软件开发:先做一次修改,再增加一项功能,过一段时间又要修改之前写好的功能,必要时还得重构。它让模型在一段时间里不断面对新的变更要求。我记得当时某个 6.0、也可能是 5.6 版本的模型,得分大约只有 15%。

模型做到一定阶段就卡住了,只会不断往已有代码上打补丁,后来甚至开始编造内容,或者无法管理好上下文。也就是说,连续开发过程中容易不断出错,而一次性完成任务的表现却好得多。这和你的观察很一致。不过,你的做法正好和我原先想的相反。我本来以为,改动越小,我越容易理解、查看和审查代码,判断它是否符合预期。你却倾向于在动手前把整套功能的要求都谈清楚,甚至用 Gemma 这样的本地模型评估 Agent 对任务的理解程度,再让它去执行。

Carlos:对,但这正是我提前搭建代码骨架的原因。大部分结构在执行前就已经确定了。

Patrick:那你会查看最终产出、审查代码吗?

Carlos:当然会。如果我不喜欢,或者看不懂,我就直接扔掉。

Patrick:那反馈是怎么进入下一轮的?毕竟你在前期花了不少时间,把一整套功能想清楚,Agent 又可能连续跑上几个小时。等你看完结果,发现不符合预期,接下来怎么处理?

Carlos:我始终让 Agent 在独立的 Git Worktree 里工作。如果我看不懂它写的东西,就直接丢弃。我不会急着花很多时间深挖,因为这通常说明它没有沿着我给出的代码骨架实现。如果把这样的代码直接合并进主项目,后面很可能会出问题。

我说的“看不懂”,并不是说我完全没有能力理解。我当然可以花很多时间逐行研究。但如果我打开代码,没办法立刻找到自己原本预期会出现的结构和内容,那就说明方向不对。我宁愿把这一版扔掉,重新做。

Patrick:所以这还不是传统意义上的代码审查,而是先快速扫一眼:我认不认得出这套代码?它是不是按照我预期的结构组织的?

Carlos:对,这是第一步,而且我会在 Agent 完成长时间任务之前就做这一步。通常运行一两个小时,我就会让它先暂停,打开 Worktree 检查当前的结果。如果一看就觉得照这个方向做下去肯定不对,我会直接回滚,关闭这个 Agent,开启一个全新的会话。

然后我会告诉新的 Agent,上一次哪里出了问题,问它怎样才能避免重蹈覆辙。于是我们重新讨论,查清究竟是我搭的代码骨架有问题,还是前面的沟通不够明确,或者多层信息图里的某些想法互相冲突。大多数时候,问题就在于一些设计想法彼此矛盾。我会先把矛盾解决,再让 Agent 重试。通常第二次就能做好,极少需要第三次。

Patrick:也就是说,问题主要还是通过重新沟通来解决?还是说,你也会把这些经验固化成明确的规则,让下一次执行更可预测?

Carlos:两者都会做。我一直在努力把不确定的东西变得更确定。大语言模型本身具有不确定性,同一个问题可能每次给出不同的答案,但我希望尽可能把它推向确定性的输出,让相同要求得到稳定的结果。为此,有时需要写一个严格执行指定操作的脚本,有时需要把代码骨架设计得更具体、约束得更严。我会尽可能用这些办法减少模型行为的不确定性。

5 别只审查 AI 写了什么,还要看它为什么这么写

Patrick:最后还有一件事我一直在想,就是我们以后该怎么看代码、审查 PR。我见过有人根据代码变更制作不同的可视化。假设你和主 Agent 已经把一整套功能讨论清楚,对需求也很满意,然后几个 Agent 连续工作了 12 个小时,最终交出大量代码。这个时候,评审者该怎么审查?有人把代码库可视化成一座城市,用建筑的分布和高度展示哪里增加了代码、复杂度集中在哪里;也有人用其他界面来呈现代码结构和复杂度。你已经通过确定性的脚本约束架构和编码规范,但既然代码生成越来越便宜,我们是不是也该重新设计查看和审查代码的方式?你想过这个问题吗?

Carlos:想过很多。这正是现在面临的一个问题。我发现,越来越多的 PR 下面连一条评论都没有。我不喜欢这样。我甚至希望大家能为了某一行末尾为什么没加分号,争得差点把椅子扔出去。团队需要通过这样的讨论找到彼此的边界,学会怎样合作。我们在节目一开始就问过:为什么开发者越来越不和彼此说话了?现在写代码的方式、管理 Agent 的方式都在变,但人与人协作的部分却正在慢慢消失。

大家常拿代码量太大当理由。可如果代码太多,为什么不让 Agent 少写一些?把每项功能控制得小一点,增加审查环节,像以前人与人协作时那样正常迭代,审查就容易多了。要是任由 Agent 一次提交一大堆改动,最后连验证都做不到,那就很可怕,因为你也失去了从开发过程中学习的机会。

Patrick:我见过一些完全不同于 Git 的可视化界面。我在想,如果你的 Harness 保存了你和主 Agent 之间的完整交流,那么这些对话是不是也能出现在 PR 里,让评审者看到你是怎样思考和作决定的?我很喜欢这个方向。你的工作方式是前期花大量精力想清楚问题,再利用 Agent 放大执行能力。既然代码生成已经很便宜,作为评审者,我反而更想看你前面做了哪些思考和取舍,而不只是盯着最后生成的代码。如果这些前期要求能可靠地落实到代码中,也许我就不必逐行看代码,而可以换一种方式审查,比如关注复杂度增加在什么地方。

Carlos:对,我也希望有一天能有足够的信心,不必再逐行看代码。我认为这是有可能的。这还涉及测试。单元测试当然有用,但只看测试通过,很容易产生过度的安全感。单元测试之外,还有变异测试(Mutation Testing):故意对代码进行修改,看看测试能不能发现问题。不过它对计算资源的消耗很大,我自己跑过,CPU 的负担非常重。所以我们对测试的思考还得再深入一些。

比如,可以从最初的代码骨架出发,利用静态代码分析,检查其中有多大比例的结构仍然保留;还应该逐个分析提交记录,看看每一次变更是怎样推动方案前进的。这些过程也许都可以可视化。重要的不只是代码最初是什么样、最后变成什么样,还包括它究竟是怎么一步步走到这里的。

我遇到过不少情况:Agent 明明在之前的迭代中犯了错,过了几轮却反过来说:“我之前就是这么做的,不知道你现在在问什么。”这些问题必须从流程中消除。在我看来,和 Agent 一起开发,有点像带一支全部由初级工程师组成的团队。你要是只跟他们说“去做吧”,最后可能会收到代码,有时甚至是很漂亮的代码,但不一定能得到一个完整的应用。

资深工程师应该先和产品负责人(PO)沟通,把产品需求和方向弄清楚。我与 Agent 的对话,以及那张信息关系图,本质上就是在梳理产品和产品愿景。然后我会搭建代码骨架、决定架构,这些也是资深工程师或架构师该做的事。我还会提前考虑应用怎么部署:放在 AWS 上,还是运行在用户本地?如果用 AWS,数据要不要放在 S3?数据库选 PostgreSQL 还是 SQLite?如果用 SQLite,数据库文件应该存放在哪里?应用最终怎样运行、用户怎样与它交互?这些决定不应该全交给 Agent 自己做。事先认真想清楚这些边界和取舍,就是搭建骨架的第一步。

Patrick:听你说完,我越发觉得还有很多东西要学,既兴奋又有些压力。你提到的这些前期决定,我过去参与的项目里,有些早就被别人定好了,还有些我根本没认真想过。我当然有自己的看法,但现在也很想去尝试不同的方法。比起以前,如今能试验的东西多了太多。我想多做一些实验,看看什么适合自己的工作方式,并从中学到东西。

Carlos:那就一起试试吧。我们可以办一场社区活动,找个场地,让大家带着笔记本电脑聚在一起。有人先搭代码骨架,有人不搭,分别试一试,看看结果有什么不同。大家既能探索怎样更有效地使用 Agent,也能借这个机会面对面交流。我觉得这才是第一步。现在我们越来越容易困在各自的小圈子里,要改变这种状态,就得重新聚到一起,动手尝试,一起犯错、一起笑,也一起学习。

Patrick:完全赞同。Carlos,非常感谢你来节目分享。下次我们别再隔三年了,也许一年左右就再聊一次。

Carlos:谢谢你再次邀请我。这次聊得很开心。

播客视频链接:

https://www.youtube.com/watch?v=mkN4uRZYPfs

声明:本文为 InfoQ 编译,不代表平台观点,也不构成投资建议,未经许可禁止转载。

今日好文推荐

干掉 Bun 和 Tauri,旧插件全部报废!OpenCode 2.0 正式发布:一次“重大改造”

Meta 发布 Muse Spark Open,号称全美最强开源模型,但编程基测输给智谱、Kimi

同年生的AI明星公司:一个要造出 4257 个百万富翁,一个有了2亿用户也没活下来

Meta 新模型杀回AI第一梯队,Alexandr Wang 亲述 Muse 7个月翻身内幕

图片会议推荐

QCon 全球软件开发大会·2026(上海站)将于 10 月 22 日—24 日举办。本届大会聚焦 Harness AI 时代的工程实践,从「构建 AI」到「驾驭 AI」,围绕 AI Native 架构、Agent Runtime、AI Infra、Agent 安全与可观测、Loop Engineering、具身智能与世界模型 等热门技术方向,邀请全球技术社区与产业一线实践者,共同分享 AI Native 时代最具价值的工程经验。查看更多详情可扫码或联系票务经理 18514549229 进行咨询。

图片

跳转微信打开

来源:InfoQ · 微信公众号 · mp.weixin.qq.com