大家好,今天又给大家带来了好东西。上次在这个姑且算是播客的节目里,我们请到了 Uncle Bob,聊了软件质量,聊了 Agent,还聊了很多有意思的东西。这次我们请到了一位很棒的嘉宾,我很高兴能请到他。最近他在推特上聊软件工厂如何提高工作质量、提高开发速度,以及如何一步步提升对 agent 的信任,好让你能交付更多、更多、更多,反响特别大。
他就是 Potato,欢迎,非常感谢你来参加。谢谢你邀请我,很兴奋能来这里。我是你的忠实粉丝,我也是你的忠实粉丝。我觉得大家都在说,这就像是 skill 领域的高手会面,像是 skill 领域的奥林匹斯山之类的。因为我们俩都有很受欢迎的 skill 库,就像开始前我说的,你的 skill 我用的还不算多,我想把你脑子里的经验都挖出来,这样我就能好好用,用的更好。
我想先从这个聊起。你最近做了一场演讲,大概是十天前,然后发到了X上,反响非常火爆。主题是我上个月如何把两千五百个PR上线到了生产环境,在X上大概有三百万次浏览吧。我看了很喜欢,也推荐给了别人。我想把这次访谈基本上做成那场演讲的问答,来问问你,因为我对那场演讲有一大堆问题,想深入聊聊。我想先聊的是,你提到和
agent 之间有个信任阶梯,你越信任 agent 就越能让他们做得更好,或者扩大规模,用上越来越多的 agent。
你是怎么一步步爬上这个信任阶梯的?到了 SpaceX 之后,你又是怎么越爬越高的?我觉得这段经历其实在我加入 Cursor 之前就开始了。Cursor 现在是 SpaceX AI。事情是这样的,在离开 Meta 之后,我之前在 Meta 的 React 团队工作,我休息了一个月,因为当时觉得有点倦怠。
那当然了,觉得倦怠的时候,你会做什么呢?去开一个新的业余项目,所以我就开了一个业余项目。当然,我用AI来写代码,但后来我开始意识到,我花那么多时间只是在事无巨细地盯着一个agent,对吧?当时是二月,可能是二月二月初或者一月。大家当时都很热衷于编排这个想法,那会儿像 Cursor 的 Agent
的窗口这类东西还没流行起来,所以大家还在终端里用着终端界面,都在说,来,我做了一个自己的编排工具,对吧?
所以我当然也被这个技术问题勾住了。我本来在做自己的小项目,结果被另一个技术问题勾住了。哦,怎么让我的 AI 编程环境更高效呢?所以这段经历算是从那里开始的。我停下来想了想,意识到自己花了这么多时间,事无巨细地盯着一个 agent。我也在做 skill,但发现很难衡量产出,结果也很难衡量 skill 带来的影响。
所以,我有点像是在摸黑前进,但迭代的很快。那个项目后来就成了 PS Stack 的基础,虽然当时我还不知道。还有一些我学到的技巧,比如做出最初的那套 skill,其实它现在还是开源的。大家想看的话可以去看看,就在我的 GitHub 上 potato 斜杠 noodle,拼作 N O O D L E,里面有一些 skill,还有一个 brain 目录。
我当时特别感兴趣的是,怎么把我自己的能力提炼出来,再交给 agent。不知道这样说能不能理解,对吧?因为我意识到,我想做的其实就是教 agent 更像我一样写代码,更像我一样按工作流程做事,所以 skill 就是做这件事的一个切入点。后来加入 Cursor 之后,我开始做 Agent 窗口,它当时有很多性能问题,挺卡的。
因为我有做 React 的经验,就有人问我,嘿,你要不要来帮忙做 Agent 窗口?所以刚开始在 Cursor 工作的时候,很多事情都靠手做。我埋头看火焰图,堆快照,想弄清楚这个应用到底为什么这么慢。但后来又有了同样的发现,我自己成了瓶颈。什么事情都是我手动做的,某种意义上我就是个人肉代理,或者说是我的 agent 和 Chrome 开发者工具之间的人肉代理,这样我很烦。
那大概是一年里的几月呢?时间线走到哪儿了?我是三月加入 Cursor 的,所以这大概是四月初,很早的时候吧。我是四月初加入的,当时我还没有任何 skill,对吧?我把自己那些个人用的 skill 放下了,因为我觉得他们应该用不上了。到后来做 agent 窗口,现在又做 Grokbot,我慢慢意识到,最初做那套 skill 时学到的很多东西都很有用,尤其是验证、严谨做事这些。
因为根据我的经验,我觉得 agent 就连最先进的那些也往往会往往会走捷径,他们往往会选容易做的事儿。所以我做的很多 skill 都围绕着一个问题:怎么让容易做的事儿就是正确的事儿?怎么让它也是最好的做法?把自己的专业经验提炼出来,把每天做的事情变成流程,这个想法让我觉得特别熟悉。我做 skill 就是在做这件事儿。
我觉得这里有一点值得聊聊,就是很多人觉得随着大家越来越依赖 AI 领域专业知识,现在越来越没用了。你怎么看?在我们开始之前,先大概聊聊你的感受,然后我们再。我其实觉得领域专业知识比以往任何时候都重要。我想我以前在 X 上写过这个,但我有时会这样看待 AI,尤其是模型越来越聪明,能力越来越强,最先进的那些模型已经变得这么好了。
顺便说一句,我很喜欢 Opus 五点五。随着模型变得非常、非常、非常好,感觉瓶颈几乎已经不再是 Agent 了,对吧?瓶颈变成了你能不能把自己的意图和目标表达清楚,让 Agent 理解并且真正执行。所以我觉得,在某个领域有丰富专业知识的人优势非常大,尤其是你对技术还有点好奇心的话。我想到的是医生、律师,或者在某个工程以外的领域有深厚专业知识的人。
如果他们稍微懂点技术,能弄明白怎么用 agent,其实就能做出非常非常棒的产品,对吧?前提是他们脑子里的构想足够清晰,而且能把它说清楚,让 agent 能够把它做出来。我觉得现在真正的瓶颈就是把你的意图和构想传达给 agent。我一直痴迷于语言,基本上是从 agent 推出的时候开始的。我就是特别痴迷,百分之一百同意,我也一样。
我一直在想词语怎么组合,怎么把话说的更精准,还有那些表达里可能藏着什么,就是我用的那些表达。我特别喜欢的是,你找到一个词 agent 就抓住它,然后说好,我要强化这个词,我要把它再用到我的思考过程里。我发现测试驱动开发就是早期的一个例子。最近大家聊了很多测试驱动开发,有人问用 agent 时候该不该用测试驱动开发?
这不重要,你做的事是让 agent 去思考测试驱动开发,让他写测试,让他用跟以前不同的方式安排优先级。所以我觉得不断追问才会有效,因为不断追问是一种对对,他会把那些词从你嘴里引出来,对吧?或者至少能帮 agent 理解你的想法,这样他就能向你提出那些词,你就可以接过来说,对,就是这个。其实我也借用你分享的一些技巧。
你可能在过去几周分享过一个我特别喜欢的技巧,就是减少或者消除那些同一反复的测试。A阵让我特别烦的一点就是他们写的那些没用的测试。这就是一个例子。同意反复这个词,我想可能不是很多人都知道,尤其是英语不是母语的人。但这个词包含了很多意思,几乎就像压缩过一样,对吧?你把很多意图和含义都压缩进了词语里。所以我完全同意你的看法。
其实我一直对语言很感兴趣,比如编程语言、人类的自然语言,还有它们是怎么形成的。特别有意思是,现在有了 agent 自然语言和编程语言,好像交汇到了一起,但底层都是语言,都是沟通。完全同意。我读的是戏剧专业,对吧?所以很早以前我就在思考语言,莎士比亚这些东西了。这一切都让我觉得很熟悉。因为我想向你了解的其实是软件工厂这些事,对吧?
软件工厂是现在特别热门的一个词,我也在思考软件工厂这件事,我也在往这个方向推出一门课程。基本上,就是把自己的产出规模扩大到一个看起来不现实的PR数量。对于不了解这套东西怎么运作的人来说,这个PR数量听着会很离谱。我想探讨的是,怎么从现在只用一到五个agent发展到几百个agent同时运行,以及这样是怎么运作的。
所以我很想听听你用米其林厨房来代替软件工厂的这个比喻,因为我觉得它多少体现了你怎么看这些事。对。我一直不太喜欢“软件工厂”这个说法,不是因为它不准确,而是我觉得很多人想到工厂,并不一定会把它跟品质或者手艺联系起来,对吧?这些对我还有很多做产品的人和技术人员来说都很重要。我们在乎用户体验,也在乎自己做出来的东西。
所以,虽然我确实觉得“软件工厂”这个说法很贴切,但我想它有时可能也会让人产生一些负面的联想。所以我最后选了“米其林厨房”这个说法,我觉得它更让人心生向往,而且我很喜欢这个比喻,因为我喜欢美食。当然,我叫 Potato,我也喜欢做饭,而且我觉得这里面有很多相似之处,对吧?比如说,你给自己做一顿饭,它有实用的一面,就是让自己吃饱,活下去,对吧?
但它也可以变成艺术,对吧?米其林星级厨师,甚至普通的厨师或者做饭的人都能做到这一点,把非常普通的食材做成一顿美味的饭菜,让你回想起童年之类的。所以这几乎就对应着我说的那个新人阶梯。你可以想象自己在家做饭的这一路经历,对吧?在家做饭的时候,所有饭菜都是你自己做,所有菜都是你切,准备工作都是你做,收拾也全靠你。
不管是男是女,真的就是一个人包办。这里有个很有意思的思想实验:假如你要做一顿饭,然后让更多人加入,对吧?你的伴侣加入了,你的兄弟姐妹也加入了。突然间,全家人都在厨房里了。我觉得大多数人都会因此压力很大,对吧?一想到,哎呀,这么多人在我的厨房里瞎忙,他们不不知道各种厨具在哪儿,把厨房搞得一团。我厨房的最大容量糟,就是一个人,任何时候都是对,完全是。
我觉得这个比喻很贴切,因为你会问自己,我怎么从独自做饭。变成有一大堆人,甚至不不用一大堆,只要几个副厨在厨房里帮我。我要怎么考虑分工才能分得合理?我不是为了分工而分工,而是要让大家合起来的效果比各自的成果简单相加更好。所以,在这方面,我觉得米其林厨房这个比喻特别合适。因为当你成了主厨,你就不一定还要自己做所有的饭菜了,而是有点像厨房里的技术负责人,对吧?
主厨要考虑的不只是做饭,还得把整个厨房组织起来。就像厨房的CEO,他们得考虑什么时候订食材,怎么储存,怎么处理,什么时候得准备好,这是一整份工作,对吧?不只是做菜。我觉得这也很像现在工程师写代码的方式,你不再亲自写代码了,你有 agent 对吧?但作为人,你仍然要对最终结果负责,对吧?你做的工作仍然跟你的名字、你的声誉联系在一起,所以你怎么布置自己的厨房,对吧?
怎么配置技能环境和代码库?我觉得这些最终都成了打造产品的新食材。对我觉得你这套做法让我很喜欢的一点,就是你特别重视 agent 所处的工作环境,对吧?因为我觉得很多人会想,agent 已经很好了,我大概也没法让它变得更好。那些像会魔法一样做模型的人,把运行框架和模型搭配好了,我们相信他们就行了。我实在做不了什么,比如我也没法去改 cloud code 内部实现,或者你用的其他什么工具的内部实现。
但你这套做法让我喜欢的地方,也是我一直提倡的,就是你可以改变 agent 所处的工作环境,对吧?你可以修改代码库,也可以给他验证工具,让他验证自己的工作。所以,看那场演讲时,我很喜欢你对验证的重视。你可以从验证入手,开始建立信任。你能聊聊这个吗?具体是怎么做的?我们来看看有哪些实际的办法能让大家改进自己的流程、自己的厨房。
对,其实我经常说,就算你不用 PS Tech,也不用你自己的技能,我觉得你的工具箱里最重要的技能也应该是验证。因为如果没有验证,顺便给不了解这个意思的观众解释一下,验证就是在某种意义上给你的 agent 一双手和一双眼睛。我喜欢这个比喻,agent 可以运行代码,对吧?像普通用户一样,实际跟他交互,还能做调试、记录、追踪信息和快照这些事。
有意思的是,这其实是我加入 Cursor 后做的第一个技能,它才真正让我开始在信任阶梯上往上走了一点。之前我看过或者做过的其他一些技能,并没能让我做到这一点。因为不管其他技能有多好,比如好技能、Y技能、Unslap技能,我还是得靠自己,对吧?由我来当 agent 和输出结果之间的中间人。所以,如果 agent 实际上看不到自己的工作结果,它就根本没法迭代,对吧?
所以这就到了大家开始谈循环、谈循环这个概念的地方。但说实话,我觉得“循环”这个词好像有点抽象。大家会问什么是循环?什么是Agent循环?但对我来说,循环里最重要,让它能形成循环的部分。其实就是验证,因为 agent 能验证自己的工作,这样就不用你参与了。现在我就能做一些事情,比如。我最早用验证做的事情之一,就是优化 Cursor 的 Agent 窗口的性能。
我想做到一种叫“爬山优化”的方式。我觉得各家实验室经常提这个词,意思就是你有一套评价标准或者某种判断打分的方法。现在有了循环,你就可以让 Agent 不断尝试改进。我记得Kapasi Andrej Kapasi也发布过一个很有名的东西,叫Auto Research,里面也有很多这样的思路。所以我会说,验证大概是 PS Stack 和很多其他工具集里最重要的技能。
我觉得这是最值得花精力的事儿。其实我花了很多时间调校 Create Verification Skill。我们内部现在也有很多验证技能,比如 Cursor 或 SpaceX AI 的每个应用都有验证技能,而且还会自动维护。它已经成了我们团队的关键基础设施,因为大家都在用。而且你在这方面做得很深入,对吧?
我在你的演讲里看到,你还专门为此做了一个命令行工具。那这个命令行工具是做什么的?它怎么执行操作?还有你为什么?我是说,这就说明你钻研得有多深了,对吧?说明你在这方面推进了多少?对,这其实是我早期学到的一个窍门。我记得是在一月或者去年年底,那时候大家特别关心的是上下文窗口,对吧?当时大家讨论最多的就是我该怎么管理上下文窗口,因为那时候压缩上下文生成摘要的效果还不太好。
社区里甚至流传着这么一个梗:只要你的 agent 做过一次摘要或者压缩,在这次绘画剩下的时间里,它就会变得有点傻,对吧?所以大家想了很多办法,让上下文用的更高效。这其实就是我在验证技能里做一些命令行工具的初衷。我觉得现在就没那么侧重上下文了,因为agent好多了,或者说运行框架生成摘要的能力进步了很多。
不过,我还是觉得保持上下文窗口干净是有好处的。所以对我来说,命令行工具主要就是把技能里那些做法确定的部分写进脚本或者命令行工具里,省掉原本没必要的判断。说到判断,我觉得 agent 和技能要做的事儿有点像一个连续变化的范围。有些工作完全依赖判断,对吧?这种工作需要思考,把多条上下文信息结合起来进行推敲。
还有一些部分做法更确定,比如说你想重构一些代码,对吧?从一种模式改成另一种,这就是很机械的操作,对吧?你不需要让 agent 每次都思考一遍,再想出一种新做法,对吧?所以。这就是做这个命令行工具的初衷。在我做的很多其他技能里,你也能看到这一点。我会尽量把做法确定的部分提取出来,写成代码,只把真正需要判断的部分留给 agent。
所以,从某种意义上说,我觉得技能有点像一层封装,对吧?这层封装里有一些简单的说明,告诉你怎么使用技能里面的这些定制工具。不过,说实话,我觉得这个技能本身并没有那么有意思。它也不是什么新颖的软件,它只是跟 Playwright 和 Chrome 开发者工具协议交互,调用一些 API,就是一些把它们串起来的代码。
不,我觉得很有意思,因为这是把一些信息从技能里隐藏起来的一种方式。对吧?我想这能让技能更精简,保持很小的体积,然后你就可以把更多复杂但做法确定的工作交给技能里面的脚本。所以你几乎是在压缩信息,让 agent 更稳定的做出一致的操作。这很有意思,对,而且我觉得,如果你在意上下文窗口,这也确实有帮助,因为现在 agent 的不需要重新造轮子了。
因为早期还没有命令行工具的时候,我注意到 agent 虽然会试着验证自己的工作,但它基本上每次都把所有东西从头搭一遍,而且每个 agent 的做法都不一样,我就开始发现这样很低效,对吧?其实不只是上下文用量的问题,还有速度,对吧?因为 agent 得自己去写脚本或者命令行工具,然后测试结果又不能用上一个 agent 做过而且能用,但我把它丢掉了,所以到那时候答案已经很明显了。
我应该把它做成一个命令行工具,放进技能里,这样以后每个使用它的 agent 都能用上同一份现成的工具。但我也觉得这能推动大家去想一想,你的技能和规则里有多少其实可以用确定的方式来执行。这是我经常思考的一条核心原则:怎么高效利用确定性和非确定性,让A阵在非确定性的部分发挥所长,对吧?因为他们就是为此训练的。
而其他那些更机械、更直接的部分,就完全可以用确定性的方式来做。做技术迁移时,你也会看到这一点。这也是我聊过的另一个大话题,就是从一种技术迁移到另一种技术,尤其是迁移到更适合 Agent 的技术。对吧?我觉得这种迁移有很大一部分可以通过脚本、命令行工具这些东西来完成,也就是那些确定性的部分,比如用自动修改代码的工具,便利AST,也就是抽象语法树,然后完全按机械的方式转换代码,对吧?
就是让脚本替你做,而不是让agent做。完全说得通,我觉得这里还有一点,就是你把一些事情从 agent 手里拿走,也算是把他们放进环境里了。比如你发现 agent 总是在某件事上犯错,你就希望通过环境让他根本不可能犯这种错。这其实也关系到代码质量。我经常聊什么才算好的代码库,对吧?什么是好的代码库?
有个定义我很喜欢,就是好的代码库是容易修改的代码库,对吧?改起来很容易,也不会把别的东西搞坏。这就意味着你有很多防护措施,让 agent 或者人只能在很窄的范围内操作。这也是你在演讲里聊到的一点。而且你聊的还不只是自动检查这一块,比如 lint 检查、类型检查之类的,也包括你怎么设计抽象。我记得你们甚至还搭了一个框架,让 agent 在里面工作。
我很想听听你,显然觉得这件事非常重要,对吧?那么,跟你可以做的其他事情相比,比如开发功能、交付成果这件事儿,有多重要?对,我甚至觉得工程师现在的新工作就是花时间建设这个环境。其实我昨天差点就为这事儿发了一条推文,但最后没发。不过我觉得,如果你没有真正花时间建立对 agent 的信任,也没有去做技能和工具,你就可能卡在一种状态里,停留在那个信任阶梯很低的位置,对吧?
你不太信任 agent 做出来的东西,所以在这种情况下,你唯一的应对办法就是专心盯着它,事无巨细的管着它,这非常耗时间。当你卡在这种状态里,就没什么余裕去想更高层面的事情,比如怎么提高自己的效率。我想可以这样打个比方:假设你是个自己写代码的开发者,却从来没花时间了解自己的工具,没听说过 VS Code,也没听说过 Vim,只知道记事本,甚至连 Git 都没听说过。
大概就是这么个比方,就好像你没有花时间把自己的刀磨快,对吧?那当然了,刀钝的话,做什么都会花很长时间。尤其是截止日期快到了,你又没有,你现在就陷进这个困境里了,对吧?刀不够快,工具也不好,却又承受着这么大的交付压力,对吧?所以你只能把注意力都放在交付上。但我确实觉得,如果你能给自己腾点时间,认真想想自己的工作环境怎么配置,这又回到了做饭的比方。
比如说,假如切蒜特别慢,对吧?不是有压蒜器嘛?你可以买一个,把蒜放进去,一挤就出来了,对吧?特别快。机器和工具被发明出来是有原因的,对吧?所以,如果你经营着一家米其林餐厅的厨房,厨师们却没有工具,那当然做什么都极其低效。每个厨师都得自己想一套办法。所以,对我来说,工具和确定性的做法就是把这部分工作拿走。
就像你刚才说的那些约束,对我来说,约束也有点像。其实稍微岔开一下,我觉得我们应该聊聊 TypeScript,因为我们都做过 TypeScript 相关的工作。你显然在 TypeScript 和 Total TypeScript 上做了很多工作,也是这个领域的领军人物。我也很早就开始用 TypeScript,而且很多年前在 TypeScript Conference 上做过一到两次演讲。
其中有一次我讲的就是类型系统和如何约束类型。TypeScript我最喜欢的东西之一,其实就是类型收窄,对吧?也就是说,你从一个很宽泛的类型开始。它可能是任何东西,对吧?然后通过类型守卫、类型收窄和运行时检查,你就能缩小这个范围。说哦,这不只是一个字符串,而是一种很特殊的字符串,它是个常量,对吧?我想我就是通过类型系统来确定这一点的。
我觉得这跟在代码库里设置约束有很多相通的地方,都是在缩小可能的范围,对吧?如果你也从范畴论的角度去想,你是在限制可能存在的类型数量,对吧?你是在说只有一种类型。对吧?我们这边我正在做那个框架叫 Dune,它不是开源框架。我跟别人介绍它时会说它有点像我们内部给 Electron 应用用的 Next.js,不过它有很多非常非常严格的 lint 规则,而且代码库的设计让一件事基本上只有一种做法。
所以,我们用了很多约定好的模式,功能都放在指定的目录里。比如,每个功能都有自己的目录,还有一个东西会通过注册表、便利代码库之类的方式发现这些功能。但这些约定好的模式和 lint 规则,营造了一个很难写出糟糕代码的环境。这既能让你自己少操点心,也让 agent
基本不用再考虑这些事儿。他只要想哦,我想加个新功能,就放进这个新功能的目录里,所有代码都放在那儿,不用往一个包揽一切的大文件里追加代码,对吧?
其实这就是那些功能目录的灵感来源。最早几个版本的 Grokbot 大概由八个这样包揽一切的大文件组成,每个文件至少有一万行,甚至更多。所以我得把它们拆成更小的部分。不过,这其实就是靠观察,观察 agent 是怎么出错的,也是很重要的一点。每次你看到一个错误,看到一件可以做的更好的事儿,就退一步想想,我怎么把它变成一条 lint 规则?
我怎么通过代码库本身让这种事根本不可能发生?对吧?这又回到了我学习 TypeScript 和类型系统的经历,就是我怎么缩小可能的范围,让自己准确的知道正在处理什么。我觉得这里有很多相通的地方。完全说得通,你把 TypeScript 和这种包揽一切的大文件放在同一句话里,还挺有意思的。因为 TypeScript 有个出了名的类型大文件,足足有两万五千行。
对我也意识到这有点讽刺。不过,我不知道他们有没有用Go重写那个文件。我想他们大概已经重写了吧。环境很重要,你得紧盯着你的agent,确保他每犯一个错,你都把这个错变成环境里的约束。而环境的好处就是不会让你的agent背上太多规则,也不会让他有太多需要记住的东西,对吧?规则就在环境里。所以他会碰到这些规则,然后被规则挡回来,在合适的时候遇到这些约束。
我们还没聊那两千五百个PR呢,这些PR是怎么来的?你已经搭好了信任阶梯,也完善了环境,然后你知道好,现在我想扩大规模了,那具体是怎么扩大规模的?你每个月会发起两千五百次对话吗?应该不是这样吧?有没有什么自动触发机制能在你的代码仓库里触发一些任务?你怎么让这个软件工厂自己触发工作?对。我可以肯定的说,要做到这么大量的PR,前提就是环境,也就是我们刚才聊的那些。
如果没有花时间去琢磨这个厨房,还有给agent用的刀具和工具,我肯定做不到,对吧?所以,某种程度上,我觉得这就像我花时间建好了一个厨房、一家餐厅。现在我其实已经不用待在那里了,因为这个环境,还是用刚才那个比喻,对吧?这真是运转的一个很棒的比喻。非常好,对你已经对开启了,我知道连锁连锁,所以嘛,餐厅对吧?
这个对,太棒了,就是这样,对,就是这样,就像你是戈登拉姆齐,你把设计一份好菜单的所有诀窍都交给了行政主厨,厨房也布置的非常好,一切都很完美,现在你就可以开第二家、第三家餐厅了。我觉得我手头的每个项目,每一场大型对话都有点像一家餐厅,对吧?我有好几家同时在运转,我就在他们之间来回巡视,有时有些会多关注一点,有些少一点,取决于我参与的有多深。
不过,我觉得确实有一些外部的触发事件和上下文是这些项目接触不到的。很长一段时间里都是我来充当中间人。我能想到最好的例子就是,有个项目正在开发一项功能,或者你正在修复一个 bug,你陆续收到 bug 报告,但这些报告都是发到 Slack、Linear 或者 X 之类的地方,对吧?这些都是外部系统没有接入你的内循环,所以我喜欢用外循环和内循环来讲这件事儿。
我不知道这样用这两个概念对不对,但对我来说,内循环基本上就是我的工程师,也就是我的 agent 工程师在写代码,朝着我的意图,或者说我在某一刻的意图快照去开发,对吧?问题是这个快照可能会过时,对吧?有了新的信息,我就得充当中间人,把这些上下文传给我的 agent。所以,如果没有这些触发机制把信息拉回内循环,你就得自己承担这个角色,在 Slack X 或者别的地方收集上下文,对吧?
你收集 bug 报告、功能需求的上下文,或者有人说我们的后端基础设施有什么限制,这些信息你都得搬过去交给你的 agent。所以我觉得 Grokbot 这样的工具就很好,因为他们也能帮你把外循环自动化,把这两个循环接起来以后,效果就非常非常强,因为你的 agent 一下子就能自己获取上下文了,对吧?举个简单的例子,你可能用了 Slack MCP,对吧?
或者你自己搭了一套 agent 运行框架,在里面加入了订阅某个 Slack 频道的功能。这样一来,你就可以告诉你的 agent 好订阅这个 Slack 频道,每次有人报告什么 bug,就去做初步排查和分类。对吧?去复现这个问题,对吧?用我们已经花时间建立的验证技能,还有我们配置好的其他所有技能,这些准备让我很有信心,对吧?
我很相信这些 agent 确实能自己去弄清楚这个 bug,确认它在 main 主分支上仍然存在,而不是用户的环境配置或者数据出了问题,也不是比如我也说不准用户没装某个依赖之类的。总的来说,我觉得建立这两个循环,再把它们接起来,是现在工作里非常重要的一部分,尤其是当你在考虑怎么扩大自己的工作规模时。这里一个很重要的主题就是始终去想,在这个流程里,我在哪个环节成了瓶颈?
为什么我的 agent 需要我来回答这个问题?我一直喜欢琢磨这个,所以我会想,怎样才能让 agent 自己回答自己的问题,对吧?但不是靠幻觉,不是靠猜,而是靠真实的数据。很多人会谈到公司大脑这个概念,对吧?或者上下文图谱,我觉得这些说法没必要这么复杂,甚至有点抽象。对我来说,就是 agent 需要一些信息,本来得由我亲自去传给他,那我怎么教会他自己去获取,对吧?
这样就不需要我介入了。所以我能做到两千个PR或者其他数量的PR,就是因为我把这些循环都搭好了,对吧?这样我就能开连锁餐厅了,对吧?我真能让自己同时开展多项工作。我当然不是坐在那里创建两千五百次对话,对吧?其实Cursor有个新功能叫Projects,里面就是这种负责协调的Agent。这些负责协调的
agent 很擅长分派工作,他们自己不干具体的活儿,而是管理监督一份类似任务清单的东西,再启动子 agent 去执行。
所以我就是不断给他们提供上下文,或者教他们怎么自己获取上下文,然后他们就去替我干活了。最后,我想说,能做到两千个PR对我来说最大的突破,就是先问自己,我要怎样才能让我的agent自己合并代码,然后从这个目标倒推。因为我跟别人说上个月我提交了两千个、两千五百个PR,他们自然就会问,这些你是怎么审查的,对吧?
这么多PR要审查,你的团队肯定恨死你了。我们等一下再聊这个,可以吗?因为可以,当然可以。关于这个,我有一个很好的问题。这个比喻真好,我想再往深一点说。以前如果你手动发起所有这些对话,就像你亲手把每一张订单交给厨师,对吧?而如果你有一个 agent,负责协调传菜,你就能自己把整套流程运转起来。那具体是怎么做的呢?
你有这些 Grokbot 订阅频道获取 Slack 消息,听起来你还有几个负责协调的 agent,或者像幕僚长一样的 agent 来监控这些,是这样吗?当你看着电脑管理这些 agent 的时候,你看到的是什么样的?我想现在确实有点让人摸不着头脑,不过我们正在做简化和整合。有 Grokbot,当然你也可以用其他工具。
不过,我基本上把这些工具看作你的外循环,就是 Grokbot 这种带有连接器的工具,对吧?它们就是连接器。我想很多人把它们叫做个人 agent,但它们其实是连接器,能连接你的邮箱、日历、Slack、Plaid,还有各种各样的服务。它们很适合帮你获取工作需要的上下文。这跟人是一样的。假如我是经理,带着一支工程师团队,我以前在奈飞工作时,经理们最常谈的理念之一就是提供上下文,而不是控制。
有意思是,这个理念有很多地方都能用到A阵身上。你当然可以靠控制来达到你想要的结果,比如事无巨细的管着。对吧?但你真正想做的是提供上下文,对吧?教会你的工程师独立做事,你就不用事无巨细的管着他们了。所以我觉得这里有很多相通之处。具体说到 Grokbot,我有一些 Grokbot 会查看我的 Slack 频道 X。
邮件或者Linear,他们有定时运行的订阅任务,所以会一直关注这些内容。我会跟他们说,比如我会留意Grokbot桌面应用里的bug问题。你只要发现这种问题,就把它发到我的 Cursor 项目里。Grokbot 有个很棒的地方,就是它能连接 Cursor。刚才提到 Cursor 有个叫 Projects 的新功能。
说到底,一个项目就是给你一个在云端运行的协调 Agent,它有自己的电脑,主要做的事儿就是管理 Agent。它就像你的行政总厨,对吧?你的幕僚长,他自己不干具体的活。其他子 agent 向这个幕僚长汇报,他负责分派、协调和管理他们的工作。基本上,他就是负责推进工作、管理事情,再把上下文传给他们。所以,如果问题突然涌进来,比如一份传来的数据里一下有三十个问题。
或者在很短的时间里来了三十个问题,协调 agent 就能理清情况,把工作分派出去。对,没错,他收到那三十份左右的数据,就会启动一个子 agent,或者一个协调 agent。他其实可以把 agent 组织成各种不同的结构,并且会找出最好的办法,把任务高效的分配给你的 agent 团队。我经常用 Cursor Projects,也经常用 Grokbot。
Cursor Projects 是我的内循环,Grokbot 是我的外循环。Grokbot 把所有外部上下文收集起来,交给这些项目,因为它其实可以直接给这项目发消息,对吧?你甚至都不用打开 Cursor,你只要跟你的 Grokbot 说为这一系列任务创建一个项目,这些任务都有关联,对吧?举个例子,也许你突然收到一大批问题,全都跟性能有关,对吧?
你的应用运行很慢,这些问题都有关联,对吧?也许有些问题甚至可以用类似的办法解决,对吧?你当然可以给每个任务都启动一个 agent。但这样一来,你就丢掉了他们之间的那条线索,对吧?你可能会重复做同样的工作,也可能没有真正去思考更高层面的问题。有时候修 bug 拿到几份略有不同的 bug 报告会很有帮助。
因为这能让你退后一步,看清真正的问题。只看这一份报告的时候,我以为 bug 在这里,但看到其他一大堆 bug 之后,我发现问题其实,在更上面这一层。对吧?对,明白了。所以这就是你在那个循环里用这么多 agent 的原因,对吧?因为不是说收到一份 bug 报告就启动一个 agent 去看这份报告这么简单,那个 agent 会跟其他 agent 重复做同样的工作。
对吧?因为如果同一件事带来了多份 bug 报告,就可能会重复做同样的工作。对,真有意思,这真有意思。所以真实用户提交真实的问题报告,不断触发工作,就让这个工厂运转的更快,像是给他加了更多订单。除了 bug 报告,你还用其他来源来推动这些 PR 吗?有意思的是,有些其实也是从读代码里来的。我想,我算是有我澄清一下。
那两千五百个PR当然不代表两千五百个功能,对吧?其实很多工作都花在打理代码上,这就像打理花园。我也很喜欢这个说法,就是。我想,如果跟你一起工作的是一个很大的工程师团队,都是人类工程师,那这件事儿就更重要了。就是,这也有点回到了我刚才说的环境,搭建一个很好的环境,不光能帮到你和你的 agent,也能帮到团队里的每个人,对吧?
想想一个刚加入你们团队的新人,他对你们的各种工程实践都不太了解。如果你们的环境很好,他从第一天起就能干出活来,对吧?他不用先提一堆低质量的 PR,他一上来就能写出很好的代码。我好像有点忘了刚才想说什么了。我有个后续问题,就是你会在什么时候触发一个 agent
让他去看代码呢?因为有些人可能会说,那就每小时做一次之类的,或者设个定时任务,还是说……哦,对对对,我也看到你最近发的一些推文,聊了你发的那些推文,用来设置这些例行任务很不错。
我也有一些这样的例行任务。其中一个就是检查代码。再举个简单的例子,你肯定也知道 React 有很多容易踩的坑,所以我有一个 agent 一直在查找不好的写法。这个任务有意思的地方是我其实不会先让他修问题,我让他把问题追加到一份文档里,然后每隔几天我就看一下,说其实这些都是同一个问题,所以你差不多需要一个缓冲区,一个队列。
有时候,这其实比直接启动一大堆子 agent 去修每一个问题更有效,因为当你处在只管执行的状态里,只想着处理那些飞快涌进来的订单时,有时就会忽略全局。所以有时候留个缓冲区会迫使你考虑全局,因为你手头有这些记录和产物,可以自己查看用人的判断力去,或者我想也可以让 agent 来做。不过这样你和 agent 就都有办法看出一些规律。
如果只是一回解决一个 bug,你可能就会漏掉这些规律,对吧?这也是有一个参谋长 agent 真正好处,他除了能具体执行任务,也能看到全局,对吧?真有意思,软件工厂的参谋长这个想法让我脑子有点炸开了。我可能得改一改下周要录的课程内容了。好,我们来聊聊审查吧,因为别人会这样回复你:那两千五百道菜从你面前飞快的端过去时,你每一道都尝过了吗?
我猜答案多少是否定的。对我觉得你不会希望自己以后再也不尝菜了,但要把规模做大,你也不可能把厨房做出来的每一道菜都尝一遍,尤其是你有好几家餐厅的时候,所以重点就变成了抽样,对吧?还有怎么考虑流程?我想也许在这里用工厂来比喻更合适。作为工厂的质量监督员,你不可能检查每一件产品,你会抽样,对吧?你每天进去看看PR的质量,看看Agent写的代码,非常严格的审查。
想想Agent哪些地方做的低效,哪些写法不好,然后再想怎么调整环境。让他回到正确的方向,对吧?不是去纠正那一个 agent,因为如果只是偶发事件,那也没什么,也许没什么需要修的。但如果你真的发现好几个 agent 都遇到了同样的问题,对吧?他们都在抄同样的进路,到处套用同一种变通办法。这就说明你该去想想怎么改进你的厨房或者你的工厂了,对吧?
比如想想你的技能约束、代码检查规则、类型系统,再做些设置或调整,让这个问题不再发生。这样做的次数足够多以后,环境里的约束就会很到位,也能很好的引导你。到那时,你就可以放手离开了。对吧?这就是理想的状态。而且我一定要说,要做到这一步非常难。我不想把它说成只要用了 PS Tech
就能轻松做到的事。你得花很多时间和精力去琢磨自己的代码,看看 Agent 在哪些地方出错,认真有意识的想清楚,再设置好防护措施和约束,让他们默认就会做对。
而你并没有。如果回到软件工厂的比喻,这不是一座黑灯工厂,对吧?灯还是亮着的,对吧?其实,还真有点是对,是吗?对,我觉得如果 agent 会自己合并自己的 PR,那从这个意义上说,他就有点成了黑灯工厂。我去睡觉了,我的 agent 现在却每周七天,每天二十四小时不停的工作。我相当于有十多个参谋长,每个负责不同的领域,对吧?
比如我有一个在负责 Grokbot 桌面应用的性能,还有一个在修用户报告的
bug。还有一个在探索用另一种语言重写它,纯粹是为了好玩,重新想象一下,如果它是个原生应用。会是什么样?这就只是个玩具,但我的意思是,当你花时间把环境搭好以后,我现在已经做到PR合并之后我才去审查,对吧?我会跟agent说用全自动模式,这在PS
Tech里是可以做到的,这样就会触发一个强度很高、很严格的验证循环,为每个PR启动一批验证agent,还会做模糊测试,对吧?
这里说的模糊测试就是它真的会把应用运行起来,到处点一点,试着像真人一样使用它,找有没有原本正常的功能出了问题,找你实现你的 bug,它会尝试找出这东西的问题,然后自己把问题修好,它会再做一遍,最终让这个 PR 达到可以合并的状态,这相当费 token,当然这些都可以调整。比如,你可以不用十个验证 agent,只用一个,对吧?
或者直接让 agent 验证他自己做的工作。但关键是验证这个环节才是真正让我很有信心的部分。我想应该说是验证加上环境,对吧?这两样结合起来,我才能放手离开,说 agent 们去把你们做的东西合并吧。我会早上看提交历史来审查。如果看到问题,我就去调整方向,对吧?我会去回退或者修改代码,添加新的 lint 规则之类的。
所以要做到这一步确实需要时间,但一旦做到了,感觉就很神奇。我跟别人说,我现在睡的好多了,因为第一天开启这种黑灯工厂模式的时候,我特别害怕,心想:哎呀,万一我引发了严重事故呢?对吧?万一我夜里把什么东西弄坏了呢?我觉得要这么做确实需要很大的勇气,但是不知怎么的,我还是做到了。现在我睡觉的时候,我的 agent 已经能自己合并代码了。
但听起来好像,所以我觉得从这个意义上说,它确实是黑灯工厂。对,有时候确实是黑的,对吧?你有时候确实会,确实确实,因为在我看来,黑灯工厂有点像 Capri 最初对 Web coding 的定义,对吧?代码几乎不存在了,你都忘了还有代码这回事儿。我觉得你的做法跟那个完全不同。你认为代码和环境都很关键,如果代码和环境不好,出来的结果就会不好。
输入是垃圾,输出也是垃圾。我明白你的意思了。对,我觉得这是另一回事儿。就像我也说不准,也许有个调光开关之类的,对吧?有些部分很暗,有些部分是亮的。所以也许用厨房来打比方更合适。更合适,用餐厅。来打比方,因为就算你是餐厅老板,你还是可能时不时去自己的餐厅看看、尝尝菜,对吧?我觉得这,我觉得采用抽查的方式,而不是每次都拦下来审,这个思路很重要。
我想你工作的环境显然相当重视安全,非常重视安全。也许有些人在做医疗应用,或者在法律、金融之类的领域工作。我觉得有些PR就像双向门,可以先合并再回退,对吧?成本很低,再走回头路的话。但有些PR就像单向门,对吧?会造成某种数据丢失,或者做出一些很难撤销的改动。假设你的大部分PR都是单向门,这种情况你怎么处理?
你会直接不推荐这种做法,还是你有什么看法?对我觉得这个问题问得很好。我觉得对我来说,这归根结底还是取决于你的agent能把验证做得多好。我觉得在工作成果可以验证的领域里,这件事就更容易,对吧?从某种意义上说,单向门也就变成了双向门。但我想,我也说不准。如果你做的事情很难通过程序来验证,那我觉得你肯定很难做到那一步。
我确实觉得要做到这一点,所在领域的成果能不能验证,是很重要的一个方面。软件工程就是这样一个领域,在很多情况下,成果都比较容易验证,可能也不能完全验证。我觉得数学等其他领域也是例子,当然不是所有数学问题,但数学的某些部分是可以验证的,对吧?比如你写出一个证明,所以我觉得这是个很好的问题,我也确实没有答案。
我觉得整个行业和我们这些工程师都得去想明白这件事。我对未来的期待和预测是,我们会看到越来越多有意思的新编程语言。专门面向 agent,到目前为止我见过的最有意思的语言之一叫 bend,b e n d,bend 这种语言把编程和证明结合了起来,对吧?以前你其实得用另一种语言来写证明。顺便给不熟悉的听众解释一下,这里说的证明就是用数学方法形式化的验证某段代码是正确的,对吧?
尤其是你的代码采用了很典型的函数式编程写法的时候。但在很长一段时间里,你都得用单独的语言来做这件事儿,比如Lean或者TLA
Plus。其他的例子我一时想不起来了。总之就是这类语言,你用它们构建数学证明,然后基本上用一个求解器来检查,对吧?检查你是不是覆盖了所有情况,有没有静态条件之类的问题。我想试着总结一下这个问题:如果你能找到一种方法,让你的 agent 真正验证工作成果,而且验证的让你放心,那你其实就可以让他们合并
PR。
因为如果代码能编译通过,对吧?如果证明已经表明它是正确的,那为什么不直接合并呢?但当然不是所有领域的成果都能验证,对这个问题很难。我觉得我们得考虑收尾了,因为快到整点了。你接下来还有别的安排吗?我是说我接下来还有安排,我得给我儿子准备晚饭。不过。你结束之后还可以再聊一会儿。好,那我们再聊五分钟。我想再问一个问题,就是你怎么看PS Stack以及怎么看Skill这类东西?
我们开播前聊过,大家会觉得这是我的Skill,那是你的Skill。那要怎么把这些框架结合起来呢?怎么把PS Stack和我的这些东西一起用?应该从两边各取哪些部分?因为我觉得Skill基本上就是从流程里提炼出来的,他们只是把流程写成了文字。我很想知道,你会建议大家怎么把PS Tech和我的这些东西拿来用,变成自己的流程。
其实你今天分享了一个技巧,我觉得很切题,就是去看看自己以前的对话记录,对吧?从自己那些记录里挖掘信息,看看你自己给 agent 的 prompt,对吧?看看你在哪些地方纠正他们,哪些地方你的不断介入,然后把这些经验提炼出来,变成可复用的 skill,对吧?这样 agent 就不会重复犯那个错误了。我觉得PS Stack和你的Skill非常互补,我完全同意你的看法。
Skill本质上就是流程,说到底,Skill就是用英语或者别的语言写的一段话,就是Markdown。我觉得你完全可以按适合自己的方式把它们融合组合起来,不过。我确实觉得每个人都该有自己的一套刀,对吧?我总是回到做饭这个比喻,但它实在太贴切了。因为每个厨师换工作,去另一家餐厅的时候,都会带上自己的刀,工具也跟着他们走,对吧?
所以对我来说,信任其实就是信任自己的工具。你花时间把他们磨锋利。把他们摸得特别透,就能做出很棒的东西。每个人的 skill 和工具组合都会不一样,比如有人可能会把你的 grill me with docs 或者 wayfinder 这个 skill 和 stack 里一些负责执行的 skill 组合起来,效果很好。
有人可能更多用你的 skill,有人可能更多用我的 skill。我觉得说到底还是要看你有多信任我和 Matt,对吧?如果你信任我们俩,那当然可以用我们的 skill。但我也鼓励你看看自己的对话记录,让 agent 看看你用过的各种做法,还有那些你不得不介入的地方,让他建议怎么把这些整理成 lint 规则或者新的 skill,对吧?
我经常说,过去的聊天记录就像一个上下文宝库,因为它把流程实实在在的呈现出来了,对吧?那是真实的流程,不是你脑子里的一个抽象想法,是实实在在的东西,对吧?你能看到它在实际操作中是怎么发生的,从中提取出很多信息。这些信息多到让我在 PS Tech 里做了一个叫 Recall 的 Skill,专门做这件事。
它来自我处理类似问题时反复遇到的一种情况。具体来说,当时我在做 Cursor 应用里的虚拟化,遇到了很多 bug,所以每次开始新的聊天,我都会想,哎,可是上一次聊天里有那么多有用的上下文,我想把它们带到新的聊天里,该怎么做呢?查看过去的对话记录,这个做法就是这么来的。然后 recall 就是把这套工作流程浓缩、压缩成一个 skill,这样我就不用每次都写一大篇,先说去看看这些聊天记录,对吧?
然后再说一堆这个那个,所以我基本上把 skill 看作是把工作流程写下来,尤其是随着 agent 的能力越来越强。去年的skill更多是在讲实现细节,比如你应该用哪些具体的脚本命令,对吧?我觉得用最新的模型,你可以把那些部分直接删掉,把重点放在工作流程上,对吧?skill就更像是一连串步骤,是你自己流程里的各个环节。
我觉得随着时间推移,skill会越来越小,越来越精简,而且彼此很容易搭配使用。或者你愿意的话,为什么不读读我们的skill,再自己把它们组合起来呢?对吧?把we finder和potato模式组合起来,做出你自己的自定义模式,对吧?我喜欢skill的一点就是,它们特别容易改。你想怎么做都行,它就是语言,完全同意,他们没什么神奇的,对吧?
就是文字。如果说有什么神奇之处,那也就是选了哪些词,用了哪些表达,还有为了把抽象的流程变成语言而做的那些思考。一旦这些思考做完了,东西就摆在那儿可以用了,也都看得见,你直接拿来用就行,Lauren。太谢谢你了,这次聊得太棒了。是,啊,这次聊得特别开心,我真的很开心,真的很开心能跟你聊天。希望真的聊得很开心,我们还能再聊一次。
我很想再聊一次,我很想再聊一次。当然了,我们再碰个面时间嘛,我也不知道几个月后有空。对,周一,就这么定了。好啊,就这么定了。第二期。非常感谢,我这就结束直播了。Lauren和我会留在这儿再聊一会儿。不过非常感谢大家观看,聊得太棒了。