这是一份依据英文字幕整理的完整中文译稿,保留约一分钟一处的回看时间戳。口语重复和字幕断句经过整理,专有名词以原视频和英文字幕为准;正式引用前请回看原视频核对。
[00:00:00] 主持人:已经直播了。好,太好了,我想我们已经上线了。各位,等一下我会把这段在 YouTube 上稍微剪一下,补一个正式的开场,介绍你之类的。我先把你从主画面里隐藏,之后再请你回来,可以吗?Lauren:好啊。主持人:好。对了,你那个昵称怎么念?是 potato 吗?Lauren:没有,就是 potato。主持人:就是 potato?好。Lauren:对,本来想用日语式的拼法。我的 Twitter——现在是 X——用户名背后有个故事:那时候我玩电子游戏,想取个可爱的昵称。我特别喜欢吃,就想到了「potato」。但正确的拼法已经被占了,只好变通,最后用了现在这个写法。不过我平常还是念 potato。主持人:好,potato。我那位商业伙伴一直坚持说应该念成 potato——
[00:01:00] Lauren:就是 potato。主持人:对,Joel Hook。Lauren:如果你想那么念也行。主持人:对,更准确。好,那我正式介绍一下。大家好,今天又给大家请来了一位嘉宾。上次做这种有点像播客的节目时,我们请了 Uncle Bob,聊了软件质量、Agent 和许多有意思的东西。今天这位了不起的嘉宾,最近在 Twitter 上关于软件工厂、如何提高工作质量、加快交付速度,以及如何沿着与 Agent 的信任阶梯一步步往上走、从而交付越来越多成果的讨论,反响非常大。她就是 potato,欢迎你,非常感谢你来。Lauren:谢谢邀请,很高兴能来。我也是你的忠实粉丝。主持人:我也是你的忠实粉丝。有人说这是两个 skill 圈子的大脑相遇,简直是 skill 界的奥林匹斯山之类的,因为我们俩都有很受欢迎的 skill 库。
[00:02:00] 主持人:就像开播前说的,我其实还没怎么用过你的库,所以特别想把你脑子里的经验都挖出来,回去好好用,也用得更好。我想先从你最近的一场演讲谈起,大概十天前吧。你把那场《我上个月如何向生产环境交付 2,500 个 PR》的演讲发到 X 上,传播得特别广,好像有三百万次浏览。我看了,非常喜欢,也推荐给了别人。我想把这次聊天当作那场演讲的一场问答,因为我看完有太多问题,想深入聊聊。先说你提到的 Agent 信任阶梯:随着你越来越信任 Agent,就能让它们做越来越复杂的事,或者扩展到使用越来越多的 Agent。你自己是怎么一步步爬上这架信任阶梯的?
[00:03:03] 主持人:比如你到了 SpaceX 之后,又是怎么继续往上走的?Lauren:这段经历其实在我加入 Cursor——也就是现在的 SpaceX AI——之前就开始了。我以前在 Meta 的 React 团队工作。离开 Meta 后,我休息了一个月,因为有点倦怠。当然,人倦怠了会做什么呢?去开一个新的业余项目。于是我就开了一个项目,也用 AI 写代码。但我开始发现,自己花了好多个小时,只是在事无巨细地管理一个 Agent。那是二月,可能是二月初或者一月。大家当时特别迷恋「编排」这个概念;Cursor 的 agents 窗口之类的东西还没流行起来,很多人仍然待在终端里,讨论着「我做了一个自定义 orchestrator」。这一下也勾起了我的技术好奇心。
[00:04:04] Lauren:我一边做那个玩具项目,一边忍不住琢磨怎么让自己的 AI 编码配置更高效。旅程大概就从这里开始。我退后一步,意识到自己把大量时间花在微观管理单个 Agent 上;我也在做 skills,却发现很难衡量某个 skill 的输出、结果或实际影响,基本是在摸黑前进。不过迭代速度很快。那个项目后来在某种程度上成了 PAC 的基础,尽管当时我还不知道。我在构建最早一批 skills 的过程中学到的一些技巧,至今也还在。项目仍然开源,有兴趣可以去我的 GitHub 看,在 potato/noodle——口述时还拼了 n o dl e——下面。
[00:05:05] Lauren:里面有一些 skills 和一个 brain 目录。我那时很关心一个问题:怎样把我自己的能力提炼出来,交给 Agent?因为我意识到,我做的一切其实是在教 Agent 像我一样写代码、像我一样走工作流程,skills 就是一个切入点。后来我加入 Cursor,开始做 agents 窗口。它有不少性能问题,运行相当卡。我有 React 方面的经验,所以有人问我愿不愿意帮忙。刚进 Cursor 的时候,工作非常手动:我埋头看 flame graphs 和 heap snapshots,想弄明白应用到底为什么这么慢。
[00:06:06] Lauren:但我又回到了同一个认识:瓶颈是我自己。我什么都手动做,某种意义上就是一个「肉身代理」,夹在我的 Agent 和 Chrome DevTools 之间,这让我很烦。主持人:这是哪一年的哪个月份?我们把时间线理一下。Lauren:我三月加入 Cursor,这大概是四月初。刚加入时我没有任何 skills,因为我觉得个人做的那些可能不再适用了,就先搁置了。但在做 agents 窗口,以及现在做 grockbot 的过程中,我逐渐意识到,最初做 skills 时学到的很多东西依然很有用,尤其是验证、严谨地开展工作这些方面。
[00:07:07] Lauren:因为按我的经验,即使是最前沿的 Agent,也往往会走捷径,选择最省事的做法。所以我做的许多 skills 都围绕一个问题:怎样让最省事的做法恰好也是正确的做法,甚至是最好的做法?主持人:把自己的专业经验提炼出来,把每天做的事变成流程,这听起来太熟悉了。我做 skills 也是在做同一件事。不过很多人觉得,随着人们越来越依赖 AI,领域专业知识会越来越没用。在进一步聊之前,你直觉上怎么看?Lauren:我反而觉得,领域专业知识比以往任何时候都更重要。我好像也在 X 上写过这个观点。
[00:08:08] Lauren:有时我会这样看 AI:尤其是模型越来越聪明、能力越来越强,前沿模型已经好得惊人——顺便说一句,我很喜欢 Opus 5.5——当模型真的越来越强时,瓶颈就不再是 Agent,而变成你能不能把意图和目标清楚地表达出来,让 Agent 理解并真正执行。因此我认为,有深厚领域知识的人有巨大的优势,尤其是还对技术有一点好奇心的人。比如医生、律师,或者其他在非工程领域有深度专业知识的人,只要稍微懂一点技术,摸索出 Agent 的用法,就可以做出非常出色的产品。
[00:09:10] Lauren:前提是他们脑中有足够清晰的愿景,也能把它表达成 Agent 可以实现的东西。我觉得如今真正的瓶颈,就是怎样把你的意图和愿景传递给 Agent。主持人:是啊,自从 Agent 出现,我基本上就对语言着了迷。我一直在想词怎么组合、怎样表达得更精准、自己用的短语里还藏着什么。我特别喜欢的一种时刻是,找到一个词,Agent 抓住它,说「好,我要强化这个词,在自己的思考轨迹里反复用它」。TDD 就是我早期发现的一个例子。最近也有很多人在讨论「用 Agent 时要不要用 TDD?」我觉得这不是关键。关键是,你让 Agent 去思考 TDD、去写测试,重新调整它处理事情的优先顺序。这也是我觉得 grilling 有效的原因。Grilling 就是——
[00:10:10] Lauren:对,对。它会把那些词从你嘴里引出来,或者至少帮助 Agent 理解你的想法,让它把合适的词提给你,你就能说「没错,就是这个」。我也借鉴过你分享的一些技巧。最近几周你提到过一个我特别喜欢的:减少或消除 tautological tests,也就是同义反复式的测试。Agent 写的一堆没用的测试一直让我很受不了。「tautology」这个词,尤其对英语不是母语的人来说,未必人人都熟悉,但它包含了很多意思。词就像一种压缩:你把大量意图和意义压进一个词里。所以我完全同意你说语言的重要性。
[00:11:13] Lauren:其实我一直对语言感兴趣,包括编程语言、人的自然语言,以及它们是怎么形成的。现在有了 Agent,自然语言和编程语言仿佛汇合了;说到底,它们都是语言,都是沟通。主持人:完全同意。我读过戏剧学位,很早就在琢磨语言、莎士比亚之类的东西,所以这一切让我觉得很熟悉。好,在进入正题之前,我最想聊的是软件工厂。software factory 是个很热的词,我自己也在想这个方向,还在做一门相关的课程。它说的是把自己的能力扩展到交付数量高得近乎不真实的 PR;不了解这套方法的人听了会觉得离谱。我想从如今只同时使用一到五个 Agent 的人开始,聊到怎样让上百个 Agent 同时运行,以及这到底如何运作。
[00:12:15] 主持人:所以我很想听你说说,为什么用「Michelin Kitchen」而不是「software factory」作比喻。我觉得这能体现你怎么看这件事。Lauren:对。我一直不太喜欢「软件工厂」这个说法,不是因为它不准确,而是很多人想到工厂,并不会联想到质量或手艺。对我,以及很多做产品的技术人来说,这些都很重要;我们在乎用户体验,也在乎自己做出来的东西。所以「软件工厂」虽然贴切,有时也会让人产生一些负面联想。后来我选了「Michelin Kitchen」,我觉得它更让人向往。我也很喜欢这个比喻,毕竟我喜欢吃东西。
[00:13:16] Lauren:我叫 potato,也喜欢做饭,而且看到了很多相通之处。比如给自己做一顿饭,一方面是为了实用——填饱肚子、活下去;另一方面,它也可以变成艺术。米其林星级厨师,甚至任何一位厨师或做饭的人,都能把很普通的食材变成一顿美味的饭,让你想起童年之类的经历。这也有点像我说的信任阶梯。你可以把自己的旅程想象成家庭厨师的成长:一开始你一个人做所有事,切菜、备料、收拾,完全是一场独角戏。
[00:14:17] Lauren:可以做个思想实验:你本来一个人做饭,后来伴侣、兄弟姐妹也加入,突然全家人都挤进厨房。我想大多数人都会很紧张:「这么多人在我的厨房里乱转,连餐具在哪儿都不知道!」主持人:我的厨房最多只能容纳一个人。Lauren:没错。所以这个比喻很贴切,因为你要问自己:如何从一个人做饭,走到有一支队伍——甚至不用一支队伍,只要几个副厨——在厨房里帮忙?怎么合理地分工?不是为了分工而分工,而是让合作的效果真正大于各部分相加。这就是「Michelin Kitchen」对我很有用的地方:当你成为主厨,就不一定亲自烹制每道菜了;你更像厨房的 tech lead。
[00:15:18] Lauren:主厨不能只想着做菜,还得组织整个厨房,像厨房的 CEO 一样。什么时候订食材、怎么储存、怎么处理、什么时候得准备好,这是一整套工作,不只是烹饪。这与工程师如今写代码的方式很像:你不再亲自写每一行代码,而是有 Agent 来做,但作为人,你仍要为最终结果负责。你的名字依然和作品联系在一起,声誉也是。所以你怎样布置厨房、配置 skills、环境和 codebase,我认为这些最终都成了构建时的新食材……
[00:16:20] ……产品。Matt:我很喜欢你这种做法的一点,是你非常重视 Agent 所处的环境。很多人会想:Agent 已经很强了,我大概没办法让它变得更好;那些神奇的模型开发者已经把 harness 和模型搭配好了,我们信任它就行。我也没法去改 Claude Code 的内部机制,或者你正在用的其他工具。但你的方法让我特别认同,而且我自己也提倡这一点:你可以改变 Agent 工作的环境。你可以修改代码库,也可以给它工具,包括验证工具,让它自己检查工作成果。我看你那场演讲时,最喜欢的就是你对验证投入的关注;验证正是开始建立信任的杠杆。你能具体谈谈它是什么样的吗?我们不妨先说说大家有哪些实际办法,可以改进……
[00:17:20] Matt:……自己的流程、自己的“厨房”。Lauren:对。我其实说过很多次,即便你不使用 PAC,也不使用你自己的那些 skills,工具箱里最重要的一项 skill 仍然应该是验证。没有验证就不行。顺便向不熟悉这个概念的观众解释一下:你可以说是给 Agent 装上“手”和“眼睛”。这是我喜欢用的比喻。Agent 能运行代码,能像普通用户一样实际操作它,还能调试、采集 traces 和 snapshots。有意思的是,我加入 Cursor 之后做的第一个 skill,实际上就是这个。它才真正让我开始沿着“信任阶梯”往上走了一点;此前我看过或做过的一些其他 skills 都没能做到这一点。
[00:18:21] Lauren:因为不管其他 skills 有多好,比如 how skill、Y skill、unsop skill,我仍然得亲自充当 Agent 和运行结果之间的中介。如果 Agent 看不到自己的工作结果,它就不可能据此迭代。大家开始谈的“循环”就是这个意思。“循环”或者“Agent loop”听起来很抽象,别人会问它到底是什么;但对我来说,让循环真正成立的最关键部分就是验证,因为 Agent 能检查自己的工作。这就把人从中介的位置移开了。比如,我最早用验证解决的一个问题,是 Cursor 的 Agent 窗口的性能优化。当时我想做到一种叫 hill climbing 的事情。
[00:19:23] Lauren:我想这是各家实验室经常谈的概念:你有一套评分标准,或者某种判断、打分的方法;有了循环,就可以让 Agent 不断尝试改进。Andrej Karpathy 也曾发布一个叫 auto research 的项目,里面就有很多类似想法。总之,我认为验证可能是 PAC 里最重要的 skill,在很多其他工具集中也是如此,最值得优先投入。我自己花了很多时间调校 create verification skill。我们内部现在也有很多验证 skills:Cursor 或 spacexi 的每个应用都有一个,而且这些 skills 还会自动维护。
[00:20:25] Lauren:它已经成为团队的关键基础设施,因为人人都在用。Matt:你在这件事上做得很深入。我在演讲里看到你甚至为此做了一个自定义 CLI。它是做什么的、怎么执行任务?你为什么要做它?这也说明你在这个方向上推进得有多深。Lauren:对。我很早就学到了一点:大概在一月,或者去年年底,大家最担心的是 context window。那时最热门的问题就是如何管理 context window,因为当时的 compaction 和 summarization 还不够好。社区里甚至有个说法:Agent 只要总结或压缩过一次上下文,接下来整个 session 就会变“笨”。
[00:21:25] Lauren:所以大家都在想办法高效使用上下文,这也启发了验证 skills 里的部分 CLI 工作。现在上下文的重要性没那么突出了,因为 Agent 更强了,harness 的 summarization 也进步了。当然,我依然觉得保持 context window 干净有好处。CLI 对我而言,主要是把 skill 中确定性的部分写成脚本或 CLI,避免让 Agent 在不必要的地方做判断。我把 Agent 和 skills 的工作看作一条渐变的光谱:有些部分完全需要判断,需要思考、整合多个上下文信息;另一些部分则更加确定。
[00:22:28] Lauren:比如你要把代码从一种模式重构成另一种模式,那很机械,不需要 Agent 每次都重新思考,想出一套新做法。这就是做 CLI 的动机。你会发现我做的很多其他 skills 也是如此:我尽量把确定性的部分提取出来,变成代码,只把真正需要判断的部分留给 Agent。所以在某种意义上,我把 skill 看成一个包装层:里面有自定义工具,外面配一点如何使用它们的简短说明。不过这个 CLI 本身并没有什么特别新奇的,它不是一款有突破性的软件,只是和 Playwright、Chrome DevTools Protocol 交互,再调用一堆 API 的胶水代码。
[00:23:28] Matt:不,这很有意思,因为它相当于把信息藏在 skill 背后,对吧?我猜这样可以让 skill 保持精简,再把更复杂但确定性的事情交给 skill 里的脚本。你几乎是在压缩信息,同时让 Agent 更稳定地重复完成更多工作。Lauren:对。Matt:很有意思。Lauren:而且如果你在意 context window,这确实有帮助,因为 Agent 不必每次都重新发明轮子。早期我们没有 CLI 时,我注意到 Agent 虽然会尝试验证自己的工作,却每次都要从头搭一套东西,每个 Agent 的做法还不一样。这太低效了。浪费的不只是上下文,还有时间:Agent 得先去写脚本或 CLI,再测试;有时候它写的还不能用,而上一个 Agent 明明做过一个可用版本,却又把它丢掉了。
[00:24:29] Lauren:所以那时我就很清楚,应该把它做成 CLI,放进 skill,让以后每个使用它的 Agent 都能复用同一套东西。我也觉得大家值得想一想:你的 skills 和 rules 里究竟有多少内容可以变成确定性的?这是我常想的一项核心原则:怎样高效利用确定性与非确定性,让 Agent 在非确定性任务上发挥所长,因为那正是它们受训要做的事;至于更机械、更直接的部分,就交给完全确定性的程序。做迁移时也能看到这一点。
[00:25:30] Lauren:我也经常谈迁移:从一种技术迁移到另一种技术,尤其是迁移到更适合 Agent 的技术。迁移中相当大一部分可以交给脚本和 CLI 完成,例如确定性的 codemods,遍历 abstract syntax tree,再机械地转换代码。让脚本来做,而不是让 Agent 逐项处理。Matt:完全有道理。这背后还有一点:你把一部分事情从 Agent 身上拿走,放进环境里。假如你发现 Agent 总犯某个错,你就想让这个错在环境中根本不可能发生。这也关乎代码质量。我常谈什么是好的代码库;我喜欢的一个定义是:好的代码库,是容易修改的代码库。
[00:26:31] Matt:也就是修改起来方便,又不容易把其他东西弄坏。这意味着你有很多 guardrails,让 Agent 或人只能沿着非常有限的路径行动。你在演讲里也谈到了这一点,而且不只是自动检查那一面,比如 linting、type checking 等;还包括你如何设计抽象。我记得你们甚至为 Agent 的工作做了一个 framework。你显然非常重视这件事。跟开发功能、交付工作等其他事情相比,它到底有多重要?Lauren:我几乎觉得,工程师的新工作就是把时间花在环境上。我昨天差点为此发一条推文,不过最后没发。
[00:27:33] Lauren:如果你没有花时间建立对 Agent 的信任,也没有打造 skills 和工具,就可能一直卡在信任阶梯很低的位置,不太相信 Agent 做出的东西。在那种情况下,唯一的应对办法就是埋头盯着它们,事无巨细地管理;这很耗时。陷在这种模式里,你就没有余力去想更高层次的问题,比如怎样让自己更高效。打个比方:以前你亲自写代码时,如果从未花时间学习开发工具,没听说过 VS Code,也不知道 Vim,只会用 Notepad,甚至连 Git 都没听过,那就是类似的处境。
[00:28:33] Lauren:你没有花时间磨自己的刀。刀钝了,做什么都慢。尤其是交付期限逼近时,你更会陷入困境:手里没有快刀,也没有好工具,却承受着必须交付的压力,只能一直埋头赶工。但我确实认为,如果你能抽出时间琢磨自己的工作配置——还是回到做饭的比喻——比如切蒜特别慢,那就可以买个压蒜器,把蒜放进去一压,速度就快多了。机器和工具的发明是有原因的。如果你经营的是米其林餐厅的厨房,却不给厨师配工具,事情当然会非常低效,而且每个厨师都只能自己想办法。
[00:29:34] Lauren:所以在我看来,工具和确定性就是把那部分工作接过去。你刚才说的约束也是一样。说到约束,我想稍微岔开一下,谈谈 TypeScript。我们都有 TypeScript 背景:你在 TypeScript 和 Total TypeScript 上做了大量工作,是这个领域的领军人物;我也很早就采用 TypeScript,许多年前还在 TypeScript Conf 做过一两次演讲。其中有一次讲的是类型系统以及如何约束类型。我最喜欢 TypeScript 的一点就是 type narrowing:从一个范围很宽、似乎什么都可能是的类型出发……
[00:30:35] Lauren:……通过 type guards、type narrowing 和 runtime checks 一步步缩小范围,最后你能说:“哦,这不只是一个 string,而是一种非常特殊的 string,是个常量。”这是我通过类型系统确定的。我觉得它和代码库里的约束有很多相通之处:你在收窄可能性空间。甚至从 category theory 的角度看,也是在限制可能存在的类型数量,最后规定这里只有一种类型。至于我正在做的那个叫 Dune 的 framework,它不是开源项目。我通常说它有点像我们内部给 Electron 应用用的 Next.js,但它还附带很多非常严格的 lint rules。
[00:31:36] Lauren:这个代码库的设计让做一件事基本只有一种方式。我们大量使用约定式的模式:比如所有 feature 都有自己固定位置的目录。还有一个机制会通过 registry 和遍历代码库等方式发现 features。这些约定和 lint rules 共同创造了一种环境,让人很难写出糟糕的代码。这既减轻了你自己的认知负担,也让 Agent 不必再为这些事费神:要加一个新 feature,就放进新的 feature 目录,相关代码都放在那里,而不是继续往一个 god file 里堆。这其实就是我设立 feature 目录的初衷。
[00:32:36] Lauren:最早几个版本的 Grockbot 是由大约八个 god files 构成的,每个至少有一万行,甚至更多。所以我不得不把它们拆成较小的部分。这也是观察 Agent 如何出错带来的启发,而观察本身很重要:每次看到错误,或者发现有事情可以做得更好,就退一步想,怎样把它变成一条 lint rule?怎样让代码库使这种错误根本不可能发生?这也让我想起自己学习 TypeScript 和类型系统的经历:如何收窄可能性空间,让我确切知道自己面对的是什么。我觉得两者有很多相似之处。Matt:完全有道理。Denny,说来好笑,你把 TypeScript 和 god files 放在同一段话里;TypeScript 自己就有一个出了名的、长达两万五千行的类型 god file。
[00:33:39] Matt:不过我不知道他们后来有没有重写那部分;大概已经重写了。好,环境很重要。你得像鹰一样盯着你的 Agent,把它犯的每个错误都转化为环境里的东西。环境的好处是,你不用给 Agent 塞进过多规则,也不用让它记住那么多事。规则就在环境里,它工作时自然会碰到,恰好在需要的时候受到约束。好,我们还没谈那 2,500 个 PR。它们是怎么来的?你已经建立了信任阶梯,打磨了环境,也意识到自己想扩大规模。具体是怎么扩大的?你不会每个月亲自发起 2,500 个聊天吧?那不可能。所以你的 repo 里是否有自动触发机制?这个软件工厂究竟怎么自己启动工作?
[00:34:40] Lauren:没错。我首先要说,要达到这么高的 pull request 数量,前提一定是环境,也就是我们刚才谈的那些东西。如果我没花时间琢磨厨房、刀具,以及给 Agent 配备的工具,肯定做不到现在这样。某种意义上,我花时间建好了一间厨房、一家餐厅,现在即使我不在那里,它也能运转。还是餐厅这个比喻。Matt:对,完全是这样。你就像 Gordon Ramsay,把设计好菜单的诀窍都教给了行政总厨,厨房也布置得非常好,一切都准备妥当。
[00:35:40] Matt:现在你就能开第二家、第三家餐厅了。Lauren:我大概会把自己做的每个项目、每个大型聊天都看成一家餐厅。我同时经营着好几家,像坐直升机一样在它们之间来回巡视。视项目而定,有的需要我更多参与,有的则少一些。不过,这些项目确实需要一些它们自身没有的外部触发和上下文。很长一段时间里,我就是传递这些信息的人。举个最典型的例子:项目正在做某个功能,或者你在修 bug,不断收到 bug 报告,但报告进了 Slack、Linear 或 X。这些外部系统并没有连到你的内循环。所以我喜欢把它分成外循环和内循环来谈。
[00:36:41] Lauren:我不确定自己用的定义是否标准,但对我而言,内循环基本就是我的工程师——我的 Agent 工程师——围绕我的意图,或者说某一时刻对我意图的快照,在代码上工作。问题是,这个快照可能会过时:新信息出现后,我就得充当中间人,把那些上下文转交给 Agent。如果没有触发器把信息拉回内循环,你就必须亲自承担这个角色:到 Slack、X 或其他地方搜集上下文,了解 bug 报告、功能请求,或者别人提到的后端基础设施存在某种限制。所有这些信息,你都得亲手传给 Agent。所以我觉得 Grockbot 这样的工具很有用。
[00:37:41] Lauren:因为它们也能帮你把外循环自动化。一旦把这两个循环连起来,能力就很强了:Agent 突然可以自己获取上下文。举个简单例子,你可以接入 Slack MCP,或者在自己搭建的 harness 中订阅某个 Slack 频道。然后你就能告诉 Agent:订阅这个频道;每次有人报告某类 bug,就去做分诊,用我们此前花时间建立的验证技能复现问题。再加上我们配置好的其他技能,我对它们很有信心:它们确实能去理解 bug,确认问题在 main 分支上是否仍然存在,而不是由用户的设置或数据造成的,或者只是用户漏装了某个依赖之类的。
[00:38:45] Lauren:所以我觉得,建立这两个循环并把它们接起来,是如今工作中非常重要的一部分,尤其当你想扩大自己的能力时。这里的一条主线是不断问自己:我在流程中的哪一步成了瓶颈?为什么 Agent 需要我来回答这个问题?我总会这么想,然后思考怎样让 Agent 自己找到答案——不是靠幻觉或猜测,而是靠真实数据。很多人会谈“公司大脑”或者“上下文图谱”,我觉得这些说法不必要地复杂,甚至有些抽象。对我来说,问题只是:怎样把 Agent 所需、原本必须由我亲自传递的信息,变成它自己能够获取的信息?
[00:39:46] Lauren:教会它之后,我就能从这个环节抽身。这就是我做到两千多、或者不管具体多少个 PR 的原因:这些循环都已经建立起来了,我就能开连锁餐厅,真正让自己并行运转。所以我当然不是坐在那里亲手创建 2,500 个聊天。实际上,这些项目在运作。Cursor 最近推出了一个叫 Projects 的新功能,里面有协调 Agent。协调 Agent 很擅长分派任务,而不是自己动手做;它们管理、监督一份任务清单,再派生 sub-agent 去执行。我持续提供上下文,或者教 Agent 自己获取上下文,然后它们替我完成工作。还有最后一点,对我来说,真正让我能达到那么多 PR 的关键是倒过来想这个问题……
[00:40:47] Lauren:怎样才能让 Agent 自己合并自己写的代码?因为当我说“上个月我交付了 2,000 到 2,500 个 pull request”时,人们最自然的反应就是:“你怎么审的?这么多 PR,你的团队一定恨死你了。”Matt:我们等会儿再谈这个好吗?我有个相关的好问题。Lauren:好,没问题。Matt:我想把刚才那个很棒的比喻再展开一点。以前如果所有聊天都由你手动发起,就等于你亲自把订单一张张送到厨师手里;而如果有个 Agent 负责出餐调度,你就能让整套机制自己运转。那具体是什么样?你有这些订阅频道、拉取 Slack 消息的 Grockbot,听起来还配了几个协调 Agent,或者说幕僚长 Agent,来监控这些信息?
[00:41:49] Matt:你打开电脑管理这些 Agent 时,看到的到底是什么样子?Lauren:这个目前可能有点让人困惑,我们正在努力把它简化、统一。现在有 graphbot,当然你也可以用其他工具。我主要把这类工具看作外循环:像 graphbot 这样的工具带有连接器。很多人把它们叫作个人 Agent;它们能连接邮箱、日历、Slack、Plaid,以及各种服务,都是把上下文拉进工作流程的很好来源。就像人类团队一样:假如我是一个带工程师团队的经理,像我以前在 Netflix 工作时,经理们常谈的一个理念就是“提供上下文,而不是施加控制”(context not control)。
[00:42:49] Lauren:有意思的是,这个理念同样非常适用于 Agent。你当然可以通过控制、事无巨细地盯着来推动结果,但你真正想做的是提供上下文:教会 Agent,也教会工程师独立完成工作,这样就不需要微观管理了。我看到两者之间有很多相似之处。说回 graphbot,具体来说,我有一些 grabbot 会查看我的 Slack 频道、X、邮件或 Linear;它们有持续订阅的例程,所以一直在监控。我会告诉它们,例如:“留意 graphbot 桌面应用的 bug;一旦发现,就发给我的 Cursor Project。”这里有个很酷的地方:grabbot 可以连接 Cursor。
[00:43:51] Lauren:Cursor 有我刚才提到的 Projects 新功能。一个 Project 本质上配有一个运行在云端的协调 Agent,它有自己的电脑,主要职责就是管理其他 Agent。它就像你的行政总厨,或者幕僚长:自己不直接做事,而是把工作委派给下属的 sub-agent,编排和管理它们的工作,并负责推动进度、管理事务、传递上下文。Matt:如果突然涌入一大批问题,比如同一个 payload 里有 30 个,或者短时间内接连收到 30 个,协调 Agent 就能理清情况并分派任务?Lauren:对,正是这样。它会收到那大约 30 个 payload,然后派生 sub-agent;一个协调 Agent 其实能组织出好几种不同的 Agent 拓扑。
[00:44:52] Lauren:它会找出比较高效的方式,把任务分配给 Agent 团队。我经常用 Cursor Projects,也经常用 grabbot。Cursor Projects 是我的内循环,grabbot 是我的外循环。grabbot 收集所有外部上下文,再交给 Projects,因为它可以直接向这些 Project 发消息。你甚至不必打开 Cursor,只需告诉 grabbot:“为这一系列任务创建一个 Project。”这些任务彼此相关。比如突然收到大量性能问题报告,大家都说应用很慢;它们可能相互关联,甚至其中一些有相似的修复方法。你当然可以每个任务都派一个 Agent,但这样就失去了它们之间的联系。
[00:45:53] Lauren:结果可能会重复劳动,也可能没能思考更高层的问题。修 bug 时,多个略有不同的 bug 报告有时反而有帮助,因为它们能让你拉远视角:只看第一份报告时,我以为问题在这里;看了其他许多报告后,才发现根源其实在更上层。Matt:明白了。这就是为什么那个循环里会有这么多 Agent,对吧?不是每来一份 bug 报告就派一个 Agent 单独去看;如果好几份报告都指向同一个问题,那样不同 Agent 就会重复工作。Lauren:对。Matt:真有意思。这样一来,真实用户持续提交的报告就成为源源不断的触发器,推动工厂加速运转,相当于不断有新订单进来。除了 bug 报告,还有哪些来源会推动你产出这些 PR?
[00:46:54] Lauren:有趣的是,有一部分来自阅读代码本身。不过先澄清一下:那 2,500 个 PR 显然不是 2,500 个新功能。事实上,很多工作是“打理花园”,我很喜欢这个说法。如果你所在的团队有很多人类工程师,这件事尤其重要。这也呼应了我之前说的环境:好的环境不只帮助你和 Agent,还能帮助团队里的所有人。想想一个刚入职的同事,他还不了解团队的工程实践;如果环境建设得很好,他从第一天就能有效产出,不必先提交一大堆质量不高的 PR,就能直接写出很好的代码。嗯……我好像说着说着忘了原本要说什么。Matt:我有个追问:让 Agent 去看代码,具体是怎么触发的?什么时候触发?有人可能会说每小时跑一次,或者设置一个 cron job……
[00:47:56] Lauren:对,对。我也看了你最近的一些推文,关于设置例程的那些内容,写得很好。我也有类似的例程。举个简单例子,React 有很多容易踩的坑,你肯定也知道。所以我有一个 Agent 会持续查找不良模式。有意思的是,我并不让它一发现问题就立刻修,而是先把问题追加到一份文档里。
[00:48:58] Lauren:每隔几天我会去看一眼,发现这些其实全是同一类问题。这样就有了一个缓冲区、一条队列。有时这比为每个问题马上派出一大批 sub-agent 去修更有效,因为如果你只处在纯执行模式,一心想着尽快处理不断涌入的订单,就可能看不到全局。有了缓冲,你不得不退一步思考整体:这些记录下来的材料摆在眼前,你可以作为人来判断;当然,也可以让 Agent 判断。关键是让你和 Agent 都有机会识别模式,否则如果你只是一味地……
[00:49:59] ……一次解决一个 bug。这其实也是有一个“幕僚长”Agent 的好处:它不仅能执行任务,还能看到全局。Matt:太有意思了。你说的这种软件工厂里的幕僚长,让我脑子里一下冒出很多想法。我下周要录的课程恐怕得改一改了。好,我们来谈谈审查吧。别人会问:那 2500 道菜从你面前端过去时,你每一道都尝了吗?我猜答案大体是没有。Lauren:对。我觉得你也不想进入一种以后再也不尝菜的状态;但要扩大规模,尤其你有好几家餐厅时,也不可能每道出厨房的菜都亲自尝。所以重点就变成抽样,以及……
[00:51:00] ……审视流程。这里工厂的类比或许更贴切:作为工厂的质量主管,你没法检查每一件产品,只能抽样。你每天去看 pull request 的质量,检查 Agent 写的代码,非常严格地审视它们,找出 Agent 的低效做法和不好的模式,然后思考如何修正整个环境,而不是只纠正那一个 Agent。如果只是一次偶发事件,可能没什么需要修的。但如果你发现多个 Agent 都遇到同一个问题、走同一种捷径,或者到处复制同一个变通办法,那就说明你该想想……
[00:52:00] ……怎么改造你的厨房或工厂了:检查你的 skills、约束、lint 规则、类型系统,调整它们,让同样的问题不再发生。这样做得足够多,代码库和整个环境就会受到充分约束,也能很好地引导 Agent,你便可以放手了。这是理想状态。不过我必须说,达到这一步很难。我不想把它说成用了 PAC 就能轻松做到的事。你得花很多时间和精力,认真思考自己的代码、Agent 在哪里出错,再有意识地设置护栏和约束,让它们默认就能做对。Matt:不过,回到软件工厂的比喻,这还不是一座“黑灯工厂”吧?
[00:53:02] Lauren:某种程度上其实是。Matt:是吗?Lauren:对。如果 Agent 可以自行合并 pull request,那我睡觉的时候,它就已经有点像黑灯工厂了。我的 Agent 现在全天候工作。我相当于有十多个幕僚长,每个负责不同领域。例如,一个负责 Grockbot 桌面应用的性能,一个负责修复用户报告的 bug,还有一个只是出于好玩,探索用另一种语言重写它:假如重新构想成原生应用,会是什么样?那只是个小实验。关键是,花时间把环境搭好之后,我现在可以等 pull request 合并后再审查。在 PAC 里,你可以告诉 Agent 开启 full autopilot,它会……
[00:54:04] ……启动一套强度很高、很严格的验证循环:为每个 pull request 派出多个 verifier Agent,还会做 fuzzing,也就是实际运行应用,到处点击,像真人一样使用它,寻找回归问题和实现中的 bug。发现问题后,它会自己修复,再重新验证,直到 PR 达到可以合并的状态。这确实很耗 token,当然你可以调整强度:比如不用十个 verifier Agent,只用一个,或者只让 Agent 自己验证一下——不过那样效果不好。真正给我信心的是验证,再加上环境本身。这两者结合,我才能放心地说:“Agent,你们自己去合并吧,明早我会……
[00:55:06] ……看 commit 历史来审查。”Matt:发现问题就再修正方向。Lauren:对。我会 revert 或修改代码,增加新的 lint 规则等等。走到这一步确实需要时间,但一旦做到了,感觉非常神奇。我常跟人说,我现在睡得好多了。第一次开启这种“黑灯工厂”时其实很吓人,我心想:“万一我弄出 SE 呢?万一一夜之间把东西搞坏了呢?”这需要很大的勇气,但我还是做了。现在我睡觉时,Agent 也在自行合并代码。所以从这个意义上说,它确实是黑灯工厂。Matt:听起来……对,有时候灯是关着的。Lauren:确实。Matt:因为我理解的黑灯工厂,更接近 Karpathy 最初对 vibe coding 的定义:代码几乎……
[00:56:07] Matt:……不存在了,你甚至忘记还有代码这回事。但你的方法完全不同:代码和环境至关重要;如果代码和环境很糟,产出也会很糟。垃圾进,垃圾出。所以我觉得这不是同一回事,也许有个调光开关吧,有些地方是暗的,有些地方是亮的。Lauren:所以厨房的类比可能更好。Matt:对,餐厅。就算你经营餐厅,也会时不时去看看、尝尝菜。Lauren:对。Matt:我觉得这里“抽样,而不是把每件事都卡在人工审查上”非常重要。Lauren:对。Matt:对于那些处在高度重视安全的环境里工作的人,你会怎么说?你工作的环境显然很重视安全。Lauren:嗯。Matt:还有一些人在做医疗、法律或……
[00:57:10] Matt:……金融领域的应用。我会把某些 PR 看成“双向门”:合并后还能 revert,退回去的成本很低;但另一些 PR 是“单向门”,可能导致数据丢失,或者造成很难撤销的后果。如果你的大多数 PR 都是单向门,你会怎么处理?你会不建议用这种方式吗?Lauren:这是个很好的问题。我觉得归根结底还是看 Agent 的验证质量能达到什么程度。如果一个领域的工作可以验证,那就容易一些;从某种意义上说,单向门也就变成了双向门。但如果你做的东西极难通过程序验证,那么要达到我们刚才说的状态,确实很难。
[00:58:11] 所以,领域本身的可验证性是能否这样做的重要条件。软件工程在很多情况下比较容易验证,虽然也不是完全如此。数学的某些方面也是例子——当然不是全部,但如果你写出一个证明,有些部分就能验证。这个问题很好,我其实也没有完整答案。我认为整个行业和我们这些工程师都得继续摸索。我对未来的希望和预测是,会出现越来越多有意思的、面向 Agent 的新编程语言。我见过的其中一个很有意思,叫 Bend——Bend,B-E-N-D。这门语言……
[00:59:14] ……在某种程度上把编程和证明结合了起来。以前你必须用另一门语言来写证明。给不熟悉的人解释一下:这里的“证明”指的是用数学方法形式化验证一段代码是否正确,尤其当你的代码是以非常函数式的方式编写时。但很长一段时间里,你得在 Lean、TLA+ 之类的另一门语言中构造数学证明,然后用求解器检查你是否覆盖了所有情况,是否存在 race condition 等问题;其他例子我一时想不起来了。所以,回到你的问题,我觉得如果你能够……
[01:00:14] ……找到让 Agent 真正验证工作成果的方法,而且验证结果能让你有信心,那你就可以让 PR 自动合并。如果代码能编译、证明也表明它是正确的,那为什么不合并呢?当然,并不是所有领域都能验证,这确实是个难题。Matt:好,我们得考虑收尾了,快到一个小时了。你后面还有安排吗?我得在给儿子做晚饭前处理点事。Lauren:我可以再聊一会儿,按你的时间来。Matt:那我们再聊五分钟。我还想问最后一个问题:你怎么看 Pstack,以及怎么看 skills?我们开播前聊过,有人会把它们看作“我的 skills”和“你的 skills”。这些框架要怎么结合?各自该取用什么?
[01:01:18] Matt:比如,怎么把 Pstack 和我的东西一起用?我觉得 skills 基本上就是从流程中提炼出来的:把流程写成文字。我很想知道,你建议大家怎么吸收 Pstack 和我的东西,再转化成自己的流程。你今天分享了一个很相关的方法:回头看自己以前的对话记录,从中挖掘信息。看看你给 Agent 写过的 prompt,哪里纠正过它们,哪里反复需要介入,然后把更高层的经验变成可复用的 skill,让 Agent 不再犯同样的错。Lauren:我觉得 PAC 和你的 skills 非常互补。我完全同意……
[01:02:19] Lauren:……skill 其实就是流程。说到底,它不过是英文或其他语言写成的文字,是 Markdown。你完全可以按适合自己的方式把它们交织、组合起来。但我确实觉得,每个人都该有自己的一套刀具。我又回到做饭的比喻了,但这个比喻很贴切:厨师换一份工作、去另一家餐厅时,会带上自己的刀。工具是跟着人走的。对我来说,关键是信任自己的工具。花时间把它们磨锋利,真正弄懂它们,你就能做出很了不起的事。每个人的 skills 和工具组合都不一样。有人可能把你的 grill me 和 dogs 结合起来效果很好,也有人可能把 wayfinder skill 和 Pstack 里的一些执行类 skills 结合起来。也有人可能……
[01:03:20] Lauren:有人更多使用你的 skills,有人更多使用我的。归根结底,还是看你有多信任我和 Matt。如果两个都信任,当然可以用我们的 skills;但我也鼓励你去看自己的对话记录,让 Agent 检查你反复使用的模式、不得不介入的时刻,建议把它们转成 lint 规则或新的 skills。过去的对话简直是一个装满上下文的宝库:流程在其中成了具体的东西,不再只是脑中的抽象想法。你能看到它实际如何发生,从中提取大量信息。我甚至在 PAC 里做了一个叫 recall 的 skill,专门处理这件事。它来自我反复遇到的一种情况……
[01:04:20] Lauren:当时我在做 Cursor 应用的 virtualization,遇到了很多 bug。每次开一个新对话,我都会想:“上一段对话里有那么多有用的上下文,我想把它带到新对话里,怎么办?”于是我开始回看过去的对话记录,后来用 recall 把这套操作压缩成一个 skill。这样我每次就不用再写一大篇话,让 Agent 去读这些对话等等。我越来越觉得,尤其随着 Agent 能力增强,skill 主要是在编码工作流程。去年的 skills 更像是在写实现细节,比如明确告诉 Agent 要用哪些脚本命令。现在用最新的模型,这些部分其实可以删掉,专注于流程本身。skill 更像是一连串步骤……
[01:05:22] Lauren:……一套真实的操作流程。我觉得未来 skills 会越来越短、越来越精炼。而且它们完全可以兼容。你也可以直接读我们的 skills,把它们组合成自己的东西:比如把 Wayfinder 和 potato mode 结合,做一个自己的定制模式。skills 最吸引我的地方就是它们非常可塑;你想怎么改都行,因为它只是语言。Matt:完全同意。里面没有什么魔法,只是文字。Lauren:正是。Matt:如果说真有什么魔法,那也是选了哪些词、用了哪些表达,以及把抽象流程转化成语言时投入的思考。一旦这一步做完,成果就摆在那里,谁都能拿来用。Lauren,非常感谢,这次聊得太棒了。Lauren:我也聊得非常开心,真的……
[01:06:24] Lauren:……很享受和你聊天。希望以后还能再聊。Matt:我很愿意再来一次。Lauren:我也很愿意。Matt:当然。我们到时候再联系……Lauren:对,周一。就这么定。Matt:就这么定,第二期。非常感谢大家。我这就结束直播。Lauren 和我还会留在这里再聊一会儿。也非常感谢大家观看,太棒了。
英文原始字幕 JSON:raw_subtitles/MN9dGgmLyso-en-opencli-raw.json,由 OpenCLI 获取,共 1738 条。本文按 66 个段落保留完整时间线;各段中文是口语转写的译文,而非逐条字幕的机械对照。