Matt Pocock:用软件工程基本功驾驭 AI Agent

说明:本稿根据英文自动字幕完整翻译整理。保留段落级时间戳,便于回看原视频。自动字幕可能存在人名、产品名和断句误差,正式引用前建议核对原视频。

一句话摘要

Matt Pocock 结合自己从声乐教练、TypeScript 教育者到 AI Skills 创作者的转型,解释如何用 Grill Me、Wayfinder、反馈循环、领域语言与经典软件工程原则,把 AI Agent 从代码生成器变成可控的软件生产系统。

核心观点

章节

可读转写稿

[0:00] 真烦人,该死,兄弟。>> 每个人都有一个关于「Grill Me」的故事。它就是会产生这种奇怪的涌现行为:模型开始稍微跳出固有框架思考,[音乐] 然后不断向你抛出想法。>> 我想,「曳光弹」这个概念就像一颗会留下痕迹的曳光弹。>> 我只是在和 Agent 对话时,开始在提示词里使用这些短语,[音乐] 然后我注意到,它也开始把这些短语说回来。它会说:「好,我会把它变成一颗曳光弹。」这就是我所说的「引导词」:你只需要重复一个简单的短语,就能引导 Agent。我该如何找到那些真正重要、值得反复回归的基本原则?>> 这真的很难,因为战略式编程一直都非常难学。我觉得,学习战略式编程有点像面前摆着一张巨大的调音台,[音乐] 上面有许多不同的推子。你把它调高,就会得到更多微服务;把它调低,就会得到一个单体架构。这有点像在混音,但你要到九个月后、等那些错误找上门来时,才能听出哪里出了问题。>> 你要如何说服非工程岗位的利益相关者,让他们相信投资软件基本功很重要?你需要某种指标来判断这件事。我认为,第一步是——

[1:05] 我在用 Grill Me Skill 构建一个相当简单的 API 端点时,经历了这辈子最狠的一次拷问。它问了我 35 个问题,真的一点都不夸张。整个过程既激烈又烦人,也逼着我思考得更多。今天的嘉宾就是这个热门 Skill 的创造者 Matt Pocock。Matt 从开发者转型为教育者,因其 Total TypeScript 系列而广为人知,如今也凭借他的 AI Skills 和教学视频受到关注。[音乐] 今天我们会聊到 Matt 不同寻常的科技行业经历:在成为开发者之前,他做了多年声音教练,还为自己的教练业务开发过一套自制软件;我们也会聊到 Matt 广受欢迎的 Skills——Grill Me、Wayfinder,以及这些 Skills 为何传播得如此广泛;还会聊到如何从几十年前的编程书籍中汲取灵感,借助 AI 构建更好的软件,以及更多内容。如果你想了解,在与 AI Agent 协作时,哪些软件工程基础方法依然非常有用,那么这一期就是为你准备的。本期节目由 Turbopuffer 赞助:构建在对象存储之上的向量与全文搜索服务,速度快、价格低,而且扩展性极强。本期节目也由 Linear 赞助。我想带你回到过去,提醒你我们以前是怎样完成工作的。那时,每一行代码都由像你或——

[2:06] 我这样的工程师亲手编写,任务跟踪工具的职责,是让大家保持同步,同时又不拖慢任何人。Linear 从一开始就追求快速、低摩擦,而这一点你能切实感受到。在去年的《The Pragmatic Engineer》调查中,Linear 是最受喜爱的任务跟踪工具,而 Jira 则因性能迟缓成为最不受欢迎的工具。来自《The Pragmatic Engineer》受众的数据也显示,Linear 开始从现有工具手中赢得市场,尤其是在初创公司和中型企业中。从那以后,Linear 逐渐成熟起来。他们加入了大型公司管理工作、项目、计划、路线图和客户请求所需的全部功能,大公司也开始转向它。例如,医疗保健公司 Oscar 帮助 600 名工程师从 Jira 迁移到了 Linear。OpenAI 最初只购买了 100 个席位,后来在没有任何强制要求的情况下,全部 3,000 名员工都迁移了过去。Coinbase、Cash App、Brex 和 Ramp 也都在使用 Linear。其中许多公司把 Linear 视为整合工具的一种方式,用一个工具把规划与构建连接起来。现在,让我们快进到今天。当公司内部有 AI Agent 时,这些 Agent 需要上下文才能顺利工作。它们需要访问规格说明、客户——

[3:07] 请求、历史记录之类的信息。等等,这些内容本来就全在 Linear 里。因此,当 Agent 出现后,Linear 就成了理想的上下文层。如今,Linear 中 80% 的企业工作区都已经采用了 Agent。你可以使用 Codex、Claude Code、Linear Agent 或你自己的 Agent。Coinbase 和 Ramp 都构建了自己的内部 Agent,并把 Linear 描述为这样一个地方:他们的 Agent 会在开始工作前先去那里获取上下文。访问 linear.app/pragmatic,看看它是如何运作的。>> Matt,很高兴邀请你来做客这档播客。>> 我也很高兴终于来到这里。我是你的忠实粉丝,看过很多期节目。我觉得这里就像软件工程师版本的 Tiny Desk,你明白我的意思吧?这可是件大事。所以,我很高兴来到这里。>> 能再次见到你也很开心,因为大约一年前,我们在 Microsoft Build 之后一起吃过午饭,那次也非常愉快。现在终于可以正式聊聊了。首先,我想问问你的背景。你和很多科技行业从业者以及本播客的嘉宾不同,一开始并不是学计算机科学的,对吧?

[4:07] >> 完全不是。在成为开发者之前的六年里,我是一名声音教练。我在伦敦和我上大学的埃克塞特做歌唱教师。我教口音、歌唱和声音训练,还读了这个专业的硕士。我曾花了很长时间,以为这就是我未来的职业。你知道,我对科技完全没有任何念头,也根本没怎么想过这件事。我自己运营过网站之类的东西,但也就仅此而已。所以,我做这份工作做了很久,它对我的人生,乃至我的性格,都产生了极其重要的影响。>> 能再深入讲讲吗?你是怎么进入声音训练这个领域的?声音教练具体做什么?哪些人会来找你帮忙,他们需要哪类帮助?>> 我最初是歌唱教师。大学时我参加过乐队之类的活动,所以多少有一些歌唱经验。于是,我在大学期间成立了自己的公司,开始做这些事情。来找我的,都是想把歌唱得更好、想

[5:08] 在合唱团里更好地运用声音,或者只是想把唱歌当作爱好的人,并不是什么特别专业的训练。后来我去读了这个专业的硕士,并开始到戏剧学校教人们表演莎士比亚作品之类的内容,也会接待一些想学习公开演讲的人。我还为几家咨询公司做过几次大型培训,你知道,就是去教他们如何发表演说,以及怎样把话说得更好。那段经历很疯狂。你知道,我之所以离开这个行业,是因为我意识到,如果想把它做到像样的水平,就必须住在伦敦。但我不想住在伦敦。我试了大概两年,实在太讨厌那里了,真的很讨厌。我不是在伦敦长大的,我想回到乡村,回到自己的家乡。后来我确实这样做了。于是,我基本靠自学成为了开发者,好让自己拥有一份可以远程完成的工作。>> 所以,你当时其实是在寻找一种即使身处伦敦以外也能从事,同时又有职业发展空间和前景的工作。>> 没错。而且,为了让自己的课程对学生更有帮助,我之前已经自学过如何做一些东西,用 JavaScript 做过一些非常基础的——

[6:09] 小项目。我做过一些小型抽认卡应用。我开发的第一个应用,可能是我尝试过的最有野心的东西:一个网页音频分析器。我可以用它分析你声音的频谱图,看看出现了哪些共振频率,判断你的 T1 和 T2 是否得到了恰当平衡,诸如此类。它非常深入,运行起来糟糕透顶,但确实让我的课程变好了一点。所以,我从一开始就在以很糟糕的方式做颇为硬核的事情。后来我意识到这一点,于是开始浏览招聘信息。我想,好吧,我会一点 JavaScript,会一点 Sass,也会一些零零碎碎的东西。然后我就直接投身其中了。我辞掉工作,休息了几个月,最终找到了一份工作。那大约是在 2017 年,当时在英国找工作比现在稍微容易一些。之后我就这样一路走了下来。>> 我想,从某些方面来说你也很幸运,因为那正是一个高峰期。当时对工程师的需求非常旺盛,参加几个月训练营、只有几个月经验的人也能找到机会;我觉得,那些有冲劲、有动力又聪明的人,能从很多地方获得机会,对吧?

[7:09] >> 对。而且,因为我有与人交流的经历,这给了我难以置信的优势,对吧?我真的可以走进面试现场,表现得像一个通情达理的人,而不是一个刚拿到计算机科学学位、可能还不具备这些能力的人。所以,我形成了一种很奇怪的组合:技术知识为零,或者说一开始几乎为零,>> 在最初的时候,>> 但却有能力向别人解释技术知识,对吧?>> 所以,我基本只需要稍微增加一点技术知识就行了。我对这件事非常有热情,因此技术知识增长得很快。然后,这似乎就成了一种不太公平的能力组合,因为我在不同公司里晋升得非常快。我也说不清,我就是觉得自己和共事的其他软件开发者不太一样,如果这样说得通的话。>> 那么之后你是怎样一步步向上发展的?也就是说,你决定要走这条路,开始自学,参加了一些面试,然后得到了……我猜那肯定是一家小公司,对吧?

[8:09] >> 对。一家很小的公司,里面有几位非常鼓舞我的软件开发者。主要是其中一个人——我不会说出他的名字,因为他喜欢保持匿名——他总是穿着凉鞋,还在一艘运河船上住过很长时间。你知道,就是那种留着长发、非常硬核的人。那正是 Microsoft 收购 GitHub 前后的时候。我记得他有一天来上班,几乎都要哭了。[笑声] >> 他讨厌 Microsoft。>> 对,绝对是。你知道,很典型。记得他让我做的第一件事,就是在我的 Windows 电脑上安装 CentOS 6。>> 那是一款相当硬核的 Linux 发行版。>> 真的是非常硬核的 Linux 发行版,因为我们的应用当时在云端运行时用的就是它之类的,你懂的。他是一个非常可爱、非常棒的人,也从一开始就教会了我很多东西。后来那家公司陷入财务困境,所以我很快就不得不跳到一家代理公司,而且在那里得到了一份级别更高的工作。九个月后,我又去了另一家代理公司,之后又换了一家。就这样,我在不同代理公司之间辗转,然后我开始——

[9:11] 从事开源工作,这算是故事的下一部分。>> 你在那些代理公司工作时,用的是什么技术栈?>> 当时用 TypeScript 和 React。>> 哦,那时已经有 TypeScript 了吗?>> 嗯,其实几乎从第二份工作开始,我就已经是 TypeScript 的坚定拥护者了。我当时还会做一些关于 TypeScript 重要性的分享。我们在为一家汽车制造商开发学习管理系统,对吧?你知道,就是代理公司那种典型的无聊项目,对吧?当时前端团队相当小,我们还有一个后端团队在葡萄牙,对吧?这就是典型的前后端分工。后端团队进展飞快,而我刚加入时,前端团队却非常缓慢。我们有一大堆缺陷,后端团队还总是在不通知我们的情况下修改接口约定,于是我们觉得需要某种东西把双方更好地衔接起来。TypeScript 显然就是最合适的选择。等我们把它上线之后,开发速度一下子就提升了。你知道,我们变得比后端团队还快,最终他们甚至把一些人从我们的团队调走了,因为我们的速度实在太快。所以,这就是我和 TypeScript 的经历,也算是我与它之间的起源故事。

[10:11] >> 你是怎么开始参与开源的?是在工作中,还是业余时间?>> 嗯,我一直在业余时间尝试开源项目,也对不同的东西很感兴趣。那时我已经开始使用 Twitter,会在网上观察不同的人,心想:这个人是我想要模仿的对象,是我想要关注的人。有一个人进入了我的视野,他叫 David Khourshid,就是 Twitter 上那位研究状态机和 TypeScript 的人。他人非常非常好,认真说来,我的职业生涯在很大程度上都要归功于他。当时我在做一个项目,我想那是我的第四份工作,那个项目需要状态机。那是一个非常复杂的应用:你会与某个人进行视频通话,同时双方还可以通过某种 Matterport 集成,一起实时浏览一栋房子。跨越网络边界需要进行大量协调,状态也非常复杂。所以,我当时使用了一个名为 XState 的库,也就是 XState 第 4 版。我觉得那次应用取得了巨大成功。于是我——

[11:11] 开始想:好吧,我怎样才能让它的类型更加安全?所以我着手围绕它构建一些工具,做各种尝试,还构建了一个围绕它生成内容的 CLI。这引起了 David 的注意,后来我成为了 XState 核心团队的一员。我开始参与议题讨论,也开始讨论这个库的未来。这让我接触到了一批水平之高、过去从未见过的开发者。David,以及另一个叫 Mateusz Burzyński 的人,他在 Twitter 上的名字是 Andarist。他们是我见过最有才华的开发者,完全是另一个层次。后来,David 想以此为基础成立一家公司。他想在状态图和可视化编程上下一场大赌注,把它们视为未来的开发方式。他们拿到了一些融资,这也成了我的第一份……算是第一份拿美国水平薪酬的工作,[笑声] 对我来说是一次巨大的跃升。>> 是的,正如我们所知道的,这和欧洲公司,甚至英国本地公司提供的薪酬很不一样,因为,是的,我们……我也报道过一些——

[12:12] 这也体现在软件工程薪酬的三模式性质中:美国公司,尤其是相对于欧洲而言——甚至美国公司彼此之间——对于薪酬和所创造价值的理解方式都不一样,对吧?>> 完全正确。它改变了我的人生,无论是我思考金钱的方式,还是我看待灵活性的方式。那意味着我在做一件自己充满热情的事。我在那里工作期间,也开始多做了一些推广,因为那家公司显然很小。呃,我做了大量开发工作,但也想为它发声,因为我相信它。你知道,我至今仍认为,状态图对于某些类型的工作而言是一种极其强大的基础原语。尤其进入 AI 时代后,我对它们的信念稍微有所回调,不过当时我确实做了更多这方面的推广。这引起了 Vercel 几个人的注意,因为当时 Vercel 负责开发者教育的是 Lee Robinson。他们有一支非常出色的团队,包括 Delba de Oliveira、Lydia Hallie——她们二人现在都在 Claude Code 团队。对。>> 嗯,还有 Lee 本人。后来我在那里找到了一份工作,直属于……

[13:14] Jared Palmer,担任类似……嗯。>> 哇,是那个 Jared Palmer。>> 就是那个 Jared Palmer。对。嗯,他其实是我的一个好朋友,后来去了 GitHub。堆叠式差异比较或者说堆叠式 PR,就是由他发起或主导的;他现在则在 Cognition。>> 对。他去了 GitHub,发布了堆叠式差异比较功能,然后离职,拒绝进一步解释,现在人在 Cognition。就是这样。>> 对。不过他也是业内传奇。没错。>> 没错。我的意思是,他人很好,我在 Vercel 跟着他工作的时间并不长。我在那里只待了大约三个月。我之所以能从那里离开,是因为我在 Vercel 拿到了一份很特殊的合同;在此之前,我就已经开始考虑 TypeScript 这件事,思考 TypeScript,也在想或许可以制作 TypeScript 教学材料。>> 我在 Stately——也就是开发 XState 的公司——工作时,就产生了一种想教东西的冲动。你知道,在那之前我教了六年课;而到当时为止,我已经有四五年没有教学了,可能甚至有六年。我心想,我需要……

[14:14] 重新做这件事。我很想念它,你知道,而且我喜欢创作内容,喜欢制作内容,也喜欢教别人。于是我开始做了,并从高级类型入手。为了强行让 XState 实现类型安全,我接触了很多疯狂的类型技巧,以及大量真正高级的 TypeScript 内容。这是一项非常非常困难的工作,我认为它基本上不可能彻底完成。于是我做了几条小技巧,做成两分钟一条的短内容,发到 Twitter 上,然后它们就火了,那种反响是我以前从未感受过的。我意识到,好,这里存在一个市场。因此,有一个星期天,我一口气做了大概十三到十五条这种两分钟技巧,然后把它们排好队,在接下来的几周里陆续发布。我的关注者数量从大约四千涨到了一万之类的规模。你知道,你会突然感觉到,人们对这件事有极大的兴趣,对吧?>> 没错。一股巨大的浪潮出现了。可能是我的表达方式和我讲授的材料共同作用,产生了我从未体验过的契合感。而这种事在我的职业生涯中,其实只发生过两次。

[15:15] 所以我当时已经在考虑制作一门课程,而且我知道自己能把它做好。我知道,只要找对受众,只要它能引起共鸣,我就能做出一门非常棒的课程。于是我加入了 Vercel。最开始,我拿到的合同是每周只工作三天,为期三个月,这非常罕见。那是你主动想要的吗?还是说,你知道,Vercel 大概也想先试试水,看看效果如何?>> Vercel 一开始就希望我全职加入。>> 但你知道自己还有另一件事要做,所以你想,如果可以的话,就用这种方式两边都留一手,对吧?>> Vercel 居然成了我那件事的奇怪备选方案。[笑声] >> 这对我来说太不可思议了。>> 对大多数人来说,这会是一份梦寐以求的工作,对吧?>> 我知道。>> 所以,这么说有点令人难为情,因为这显然是太多人的理想工作,但我加入时的想法就是:“好,我需要一份稳定的朝九晚五工作,每周做三天,同时试验另一件事。”不过公平地说,我……

[16:16] 觉得这很理智,对吧?比如我们回到你当时所处的位置:你职业生涯中有很长一段时间都在做声乐教练,姑且说是六年;之后又做了五年软件开发。你热爱这件事,也觉得自己做得不错。呃,你认为自己或许也能教好,但谁知道呢,对吧?在那个时候,你说,好吧,让我赌一把,去做这件可能成功、也可能失败的事;但如果你能在保有稳定工作的同时把它做起来,而且它开始获得关注,那情况就完全不同了,对吧?你知道,很多工程师都有抱负和想法,尤其是软件工程师可以远程工作;你可以把自己的想法做出来,创办一家公司。于是他们会想,好,我到底该不该直接跳进去?要不要辞职?所以从某种意义上说,我想这是一种颇为独特的模式——如果你能够做到的话。我的意思是……>> 当时的情况极其离奇,因为事情很快就变得非常明确:我基本上不可能继续留在 Vercel。所以……

[17:16] 我在 Vercel 工作大约两个月时,正好经历了一段非常动荡的时期,因为我在那里时,他们发布了 Turbopack。我实际上写了 Turbopack 的一部分初始文档,也见到了团队里的一些人。>> 那就是速度快得多的构建系统,对吧?>> 对,它本质上是一个构建系统。嗯,当时他们试图让它与 Webpack 竞争,那正是他们在推进的工作。我最初在那里参与文档建设。我飞去了旧金山,参加了他们宣布这件事的 Next.js Conf。你知道,那是一段很盛大、很有趣的经历;大家为此做各种准备时,我和所有人都在那里。于是我一边做这些事,脑子里其实已经在想:我看到新闻简报里与 Total TypeScript 相关的数字不断增长。我明白了,好,这里有一件非常重大的事情。当我做预售时,情况一下子就爆发了。假设我在 Vercel 的收入是 X,那次预售收入大概就是它的三十到四十倍……

[18:16] 之类的量级,你知道,几乎是立刻发生的。>> 而且你在 Vercel 的 X 本来就已经是一份非常非常优厚的薪酬了。>> 当然,我对此非常非常非常满意。但对,所以这显而易见,我没有其他选择。我很喜欢在 Vercel 工作。呃,我将来某个时候可能还会回去,但当时我不可能留下来,所以我必须去做这件事。>> 那跟我讲讲 Total TypeScript 吧。你有了这个想法,呃,然后开始每周用两天,以及在周末做它,接着又进行了这次预售。那到底是怎样的……>> 我基本上一直尽量不在周末工作。我在这件事上非常激进。我就是……我不知道。我的意思是,我觉得自己大多数时候都没做到,因为我是一个相当容易着迷的人。我喜欢努力把一件事做成,但我不是那种实行……那个叫什么来着?旧金山那种说法,人们会说什么一周工作九十六天?>> 996。>> 996。它让我反胃,你知道?我就是讨厌那一套。比如,我做所有事情时,都是在努力打造一种……

[19:16] 生活方式,打造一种能让我把大部分时间都花在家人身上的生活。这就是我的目标。我先把这点交代清楚,希望从这个角度看,我后来做出的所有决定都会更容易理解。说到 Total TypeScript,当时我和一个叫 Joel Hooks 的人合作。Joel Hooks 是个极其有趣的人,也对我产生了极大影响。到现在我已经和他合作很多年了。Egghead 是他创办的;他还与 Kent C. Dodds 合作制作过课程。他是一位藏在幕后的、极其成功的课程创作者。我主动联系他,说:“你愿意一起制作这门课程吗?”他说:“当然愿意。”于是我们就从那里开始了。所以我在 Vercel 工作的同时,也在和 Joel 合作。我们做了这次预售,如我所说,它一下子就爆了。我意识到,好,我必须全身心投入这件事。时间来到大约 2023 年 1 月或 2 月,我们……

[20:17] 发布了完整课程。我不知道,我觉得自己需要看看当时的图表,不过它很快就达到了七位数收入。当然,这笔收入由我和 Joel 分成,里面也有各项开支,但就总收入而言,那令人极其兴奋。>> 对,不过七位数就是一百万美元。我的意思是,这是一个不可思议的里程碑,对吧?>> 太疯狂了,你知道,那足以改变人生。我意识到,好,我早上醒来后,这些钱依然会继续进来。你知道,这是我长久以来一直梦想的事。我当声乐教师时,也梦想制作可以在网上出售的材料。你知道,这是我长期追求的一件事:一种高杠杆的工作方式,我可以把工作完成,然后抽身回去陪伴家人。接下来的几年里,我一直围绕 TypeScript 工作,扩充这门课程,又出售了几门补充课程。对,这基本上就是 Total TypeScript 的发展过程。所以说,我在……

[21:18] 过去四年里的成功,主要就来自 Total TypeScript,以及不断把它发展壮大。>> 对,而且 Total TypeScript 非常鼓舞人心,尤其是你公开分享了总收入达到 250 万美元这个重要的里程碑。再次强调,我觉得对很多软件工程师而言,你知道,我们当然明白这是与合作者分成之前的收入,而且其中也有各种开支,但它的潜在收入显然高于很多优秀的软件工程工作。当然,不一定高于所有这类工作,特别是考虑到美国以及一些 AI 实验室之类的地方,不过那些大概属于例外。但确实存在这样一个市场,并且可以围绕它做成一门生意。我感觉从某种意义上说,这是一种相当坦诚的模式:嘿,我创造了这个东西,人们因为想学习而付费;而且他们应该确实从中得到了价值,否则就会要求退款,对吧?>> 没错。我们提供期限非常长的退款政策。我通常也不太愿意接受其他形式的收入。我不一定喜欢做赞助……

[22:19] 内容。我不会说自己永远都不做,你知道,但我确实不太想做。我有一个 GitHub Sponsors 页面,不过我其实很想把它关掉,很久以来一直都想关掉。我喜欢这种想法:我就是一个有这些产品可供购买的人,你可以用这种方式支持我。希望它能给你带来十倍的回报,因为这是一个利润丰厚的行业,对吧?很多人都有可以使用的教育预算。如果你愿意把一部分教育预算花在我这里,那基本上就是我的模式。许多购买课程的人,花的其实都是自己的教育预算。你知道,是一些公司过来,嗯,在教育上投入大笔资金。Joel 非常积极地推动我进入这个市场,并让我认识到这一点。你知道,我原本不太了解这个行业里到底流动着多少钱,尤其是在那个时期;坦白说,现在也是如此。但它在短短几年内就如此迅速地达到那个里程碑,我的意思是……

[23:19] 这足以改变人生。>> 嗯,我的意思是,这听起来像一个很棒的故事。它原本可以有一个童话般的结局:你余生都继续创作教育内容,而且市场需求一直很旺盛。但后来 AI 出现了。>> 对。>> 正如我们所知,它正在改变我们的许多工作方式,也在改变我们寻找信息的方式。比如,我现在已经不太使用 Google 了。我实际上会使用 AI Agent、深度研究或者其中一些工具。我听说过一些教育工作者、在线教育者的经历,他们说自己的收入、市场份额和心智份额都在不断下降,因为当人们直接求助机器人就能得到答案时,他们可能不愿再从头到尾看完课程或培训。你如何看待 AI 对这个行业、对人们学习方式的影响?它又如何影响你的业务,以及身为教师的你?>> 这很复杂,因为 AI 已经改变了游戏规则,对吧?它改变了知识的重要程度,更具体地说,也改变了哪些类型的知识更重要。所以,当我在课程中教学时,我大致会把它理解为……

[24:19] 这其实分为两个层面。显然,我既在讲语法,也在讲“是什么”,但背后还有一个“为什么”,对吧?而且,如果完全不涉及“是什么”,就很难讲清楚“为什么”——如果这样说你能理解的话。所以,我所采用的媒介大概是:我会教你这些语法,而你也许能从中领会围绕它的某种智慧。对吧,我在传授知识,但同时也在努力传授智慧。如今获取知识的成本已经很低了,对吧?非常非常低。你查一下就能找到。你知道,你可以构建……我有一个 teach skill,它可以直接带着你学习,教给你所需的知识。但智慧并没有因此变得更容易习得,对吧?它仍然散落在那里。即使有了 AI,如果你过去不具备那种智慧,现在还是会遇到同样的问题。所以,从 Total TypeScript 为我带来的收入占比来看,它显然已经下降了,因为我认为人们对这类材料已经没有那么感兴趣了。而且我觉得,教授这类材料的人会发现事情变得很棘手,因为再说一次,那些知识真的非常非常……

[25:20] 难以获得。我之所以能够坚持下来——倒也不一定能说是“生存下来”——是因为我花了很长时间,才弄清楚自己想在 AI 领域处于什么位置。我不是 OpenAI 的研究员,也没有足够的资历真正去谈论这些东西,尤其是在 2023 年末,也就是我开始关注它的时候。起初,我制作的是关于如何把 AI 集成进应用程序的课程。我当时想:好吧,我开发前端应用已经很多年了;AI 正在让这方面发生一些变化,所以这样做很合理。后来我逐渐看清,这个押注是错的。我没有看到自己预期的回报,而且……课程内容是好的,我也为它感到自豪,但我不认为自己还想继续制作更多同类内容。到了去年 12 月——很多人都会提到这个时间点——哦,没错,我们都知道;或者就像我们所说的,那是一段“寒假”,所有人回来时都已经吞下了 AI 红丸。[笑声] >> 对,完全没错。Pieter 假期,对吧? >> Pieter 假期。 >> OpenClaw 假期,那时 Opus 4.5 已经……

[26:22] 发布了。人们有很长的休假时间,于是开始疯狂使用它,然后意识到:哇,好吧,事情真的开始发生了。我也是如此。我意识到,AI 现在已经足够好了,你可以把工作委派给它。你确实可以围绕 Agent 搭建结构,而 Agent 能够处理知识、语法以及我所谓的战术性工作。>> 嗯。然后你可以负责战略性工作,也就是长期思考。>> 我经常使用这种区分。我知道你曾邀请 John Ousterhout 来参加这个播客。我一直很想亲自和他聊聊;他对我的影响非常大。他谈到战术性编程与战略性编程之间的区别。在我看来,AI 已经基本吞噬了战术性编程,而战略部分需要由我们来负责。我于是意识到:好吧,在战略这一层,我可以做一门课程。当时我正在研究 Ralph 循环;Geoffrey Huntley 正在开发一些非常酷的东西,你可以让 Agent 循环运行,使它持续遵循这些目标。

[27:23] 我想:好吧,这里肯定有可以讲的内容。我只需要找到一个结构,把这些内容装进去,再弄清楚该如何围绕它进行组织和探索。>> 我还记得,关于 Ralph 循环,你也制作过一段视频,它在 YouTube 上非常受欢迎,到处都有人看。你在里面基本上是说:“好,下面是我如何创建一个 Ralph 循环的。我这里有一个项目,里面有很多待办事项。”你做得非常好——我们会把那段视频的链接放在下方的节目说明里——你说:“好,我们通常会这样尝试让 Agent 工作:先制定计划,然后逐步实施每一步。”也就是那种传统的自上而下规划方式。然后你指出,问题在于:当你开始实施时,甚至当 Agent 开始实施时,它会意识到:“等一下,我还需要做更多事情。”那么,你要如何修改计划?这时 Ralph 循环登场了。你给出了当时采用的结构:里面有一个 Markdown 文件,Agent 会持续往里添加内容,并以某种方式逐步处理它,同时又不断添加新内容。那其实让我相当大开眼界:啊,原来可以用这种方式思考该如何……

[28:23] 构建这些 Agent。>> 实际上,我那几年尝试把 Agent 集成进应用程序的经历,在这方面非常有帮助。因为当你试图构建一个包含 Agent 的应用程序时,你总是在思考数据流。你会思考数据要如何进入、采用什么结构、优先级是什么,以及要把它放进系统提示词还是用户提示词。你工作的层次比平时使用各种 Agent 框架时更底层。所以,当我开始使用这些框架时,我觉得:“哦,这感觉太熟悉了。我只需要弄清楚,状态要存放在哪里?要怎样把状态传给 Agent?它应该是什么结构?我要怎样压缩或清除它?”你知道,那时 Claude Code 还处于相当早期的阶段;当时它才推出五六个月。>> 所以这一切感觉非常自然。从那以后,我就痴迷于这些东西——我想,我们现在会称它们为循环,但其实它们只是流程,是把多个 Agent 串联起来的不同方式。这有点像画图,对吧?如果你能从一个东西向另一个东西画出箭头……

[29:24] 你就可以称它为循环,尤其是在有一条路径返回前面的时候;你也可以称它为工作流、流程,或者随便什么,对吧?>> 我会称它为有限状态机。你知道,它和我一直在 XState 上做的工作感觉非常相似:以流程为基础、以状态为基础,有时也以事件为基础。比如底部有一个 Agent,它会调用一个事件,把流程送回顶部。我开始从中看到非常好的结果。我会做一些实验,尝试搭建自己的流程,并用它开发某个功能。你知道,我有几个用于扩展自己工作的应用程序,比如一个定制视频编辑器,还有一个……你知道,一个非常庞大的东西、一个巨大的代码库。我也有几个开源项目。我会不断构建这些小循环和小流水线,有时又把它们丢到一边,回去使用默认配置。然后我发现两者之间存在巨大的差异。我当时就觉得:哇,好吧,我在这里做的这些事,真的让我更容易取得成功。于是我开始思考,分发这些东西的最佳方式是什么……

[30:25] 我怎样才能更好地与其他人分享?就在这时,我逐渐认定 skill 可以作为这些东西的分发机制。>> 嗯。这些就是供 AI Agent 框架使用的 skill,通常你可以定义它们;现在安装之后,还可以通过斜杠命令调用。>> 没错。skill 实际上就是一个由 Markdown 文件组成的文件夹,可以放在电脑里的某个位置。Agent 既可以自行调用它们——也就是由模型调用 skill——你也可以创建一些 Agent 并不知道、但由你亲自调用的 skill,也就是用户调用的 skill。我开始看到这种 skill 集合到处涌现,比如 Superpowers,还有你可以安装的 Claude Code 插件;我想 GStack 也是如此。我意识到:好吧,也许我可以把自己掌握的这套流程作为一组 skill 分发出去,看看大家有什么反应。最初我只是把它发布出来,然后去做其他事情了。我当时正在制作一门课程。后来我回来查看,发现:哦,它获得的 star 已经比我做过的任何其他东西都多……

[31:25] 而我甚至几乎没有真正宣传过它。你知道,它就那样独自放在那里。大概是靠口碑传播吧。我写了一点文档,但真的不多,而它已经迅速爆发了。所以我想:好吧,也许我应该再投入一点精力,也许我应该谈谈这些 skill。[清嗓子] 大约在 4 月,我在 AI Engineer London 做了一场演讲——我想我们上次就是在那里见面的。演讲的标题是《软件基本功依然重要》。那段演讲现在大概已经有 120 万次观看了。我在其中提到了这套 skill。如今这套 skill 已经获得 23 万个 star,是全球 star 数第二高的 skill 代码仓库。我想,在有史以来 star 数最多的所有代码仓库中,它大概排在第 20 到第 25 位。哇。你明白我的意思吗?这是怎么回事?所以,人们显然对这类东西有强烈需求。这是我职业生涯中第二次产生这种感觉,就像当初发布那些 TypeScript 短视频时一样:哇,这里有一股势头,有些事情正在发生。所以,我觉得自己必须……

[32:25] 加倍投入。关于这些 skill,你是怎样编写它们的?它们是不是在尝试捕捉你的工作流,以及你对于怎样与 Agent 有效协作的理解?你知道,不只是你现在的理解;你显然还会思考状态,也会思考自己以前如何把 AI 集成进应用程序。那件事并没有真正大获成功,但你从中学到了东西。所以,这算不算 Matt 的工作流,也就是 Matt 认定对自己有效的做法?>> 是的,就是这样。首先,我会考虑人们将会使用这些 skill,也会修改它们。那么,我怎样才能做出最简单的一组 skill,让人们很容易审查?我会思考,怎样才能最大限度地让人们采用这些 skill,并在工作中使用它们。比如 grill-me skill,也就是其中最受欢迎的那个。我不知道你是否用过,不过……>> 我也用过,对。>> 好吧。[笑声] 它真的很烦人——该死,它可把我盘问惨了。我只是对它说:“我想公开一个 API 端点。我已经有了一些基本身份验证;这个端点要能告诉任何持有已认证 token 的人,某个电子邮箱地址是不是我的邮件列表订阅者。因为我想把它接入自己举办的一场活动,让付费订阅者获得优先权。”

[33:27] 这很简单,对吧?然后 grill-me 就开始真正盘问我:“好,那么身份验证怎么办?你想使用 Bearer token,还是把 token 放在 JSON 里?后者没有那么安全”,等等。好吧,那就是需要做出的一个决定。接着,我们把所有这些决定逐一过了一遍,而且讨论得非常底层,其中甚至包括:“好,那么我们要如何强制实施速率限制?说到速率限制,你是希望每天达到 1000 次时就精确截断,一次都不再允许吗?这样做会增加复杂度。”我突然意识到,我已经很久没有和一个团队或工程团队进行过如此深入的设计讨论了。通常,只有当某人拥有深厚的领域知识时,你才会展开这样的讨论。我既觉得烦:“这件事明明很简单!不,别担心那个问题。”但同时又很惊叹:这个东西、这个 AI、这个语言模型,竟然能够通过一连串提示词做到这一切。

[34:27] 我的意思是,每个人都有一个关于 grill-me 的故事。我在各种会议上听到过太多这样的故事。人们会说,你知道,这个 skill 非常非常简单,实际上只是要求 Agent 围绕一个话题不依不饶地采访你。它是一个非常小的 skill,但它却表现出这种奇特的涌现行为:模型会开始稍微跳出框架思考,并不断向你抛出想法。我想,我最初是从一位叫 Tariq、从事 Claude Code 工作的人那里得到这个点子的。他大意是说:让 Agent 采访你,你就会看到更好的结果。于是,我把这个想法编码成了一个小 skill。然后我意识到:哇,好吧,它比我用过的任何东西都要好上大约十倍。grill-me 是第一个让我想起自己第一份工作中那些讨论的 skill。你知道,就是和那个穿凉鞋的人讨论;像是有一位非常资深的工程师待在房间里,真正促使我全面思考自己做过的每一件事。这是最接近于真正和某个像 XState 的 Anders Rake 那样的人一起工作的感觉。你知道,就好像一位真正优秀的开发者正在向我提出这些好问题。然后我想……

[35:28] 哇,好吧。接着我开始在此基础上进一步思考:我要怎样从这个 Agent 身上挖掘出更多软件基本功方面的东西?我要怎样让它表现得更像一名真正的开发者、一名真正的资深工程师?我要怎样触发正确的潜在空间,才能让它改变行为,并以有趣的方式挑战我?因为,如果你能做到这一点,如果你能提高自己与 Agent 对话的质量,也就能提高输出的质量。我喜欢 grill-me skill 的一点是,它会迫使我做出那些只要认真思考、我其实知道该怎么做的决定,但决定权仍然在我手上。它和另一种情况不同:当我告诉……当你使用 /go 命令,说“构建这个东西”时,它会自行离开去完成任务,并替你做出所有决定,或者至少做出大多数关键决定。而我喜欢 grill-me 的地方在于:决定既是由我做出的,但它有时也会提醒我一些我没有……

[36:28] 想得太多;又或者,它会提醒我应该做一点研究。比如,它问我想采用哪种身份验证方式:bearer token、通过 POST,甚至通过 GET。然后我就会想,等一下,我要去查查它们有什么区别,或者另开一个会话,让它来教我。所以,它确实让我成为了更专业的人。呃,我确实相信,在与 AI 协作时,只要我们还在学习,我觉得就没问题。一旦我们停止学习,把学习这件事外包给它,麻烦可能就会在几个月或几年后酝酿出来。>> 完全同意。这里有两件事,对吧?我觉得,所有人都低估了你和 Agent 之间存在的沟通鸿沟,对吧?你们之间是有一道屏障的。你会觉得,因为 Agent 不是人类,而你又理解自己的价值层级,所以 Agent 自然就会领会这些,对吧?人们会有一种感觉:对,相信模型就行。尤其是面对顶级模型时,你知道,相信模型就好。但无论 Agent 多么优秀,无论模型多么聪明,

[37:29] 即便是最强的模型,它也读不懂你的心。它读不懂你的心。所以,你必须通过某种流程把自己的价值观传达给 Agent。因为很多时候,当你只给它一个目标,只是说:“好,随便给我批量生成些代码,给我一些垃圾代码”,Agent 产出的东西会与你的需求完全错位,因为它不明白你认为什么才重要。所以,Grill Me 不只是关乎实现细节,它还要明确:好,要做这个;这个在范围之内;这个不在范围之内;这是我认为重要的事情。也就是说,这是 Agent 了解你的过程。>> Matt 刚才描述的是 Grill Me skill。我用这个 skill 设计一个 API 端点时,它最先问的是:这个端点可以做什么、不可以做什么,以及它可以为谁执行这些操作。就我的情况而言,我相当清楚自己想要什么,但让 Agent 自行决定身份验证和授权通常是个糟糕透顶的主意,而它们往往确实会这么做。接下来有请本季赞助商 WorkOS。你要如何授权 AI Agent?你面临的问题是:该怎样控制 Agent 的权限范围。

[38:29] 难点在于,权限是静态的,但 Agent 要执行的工作是动态的。因此,团队只能在两个糟糕的选项中二选一。要么你阅读提示词,然后逐个手动批准每次工具调用;接着再读提示词,再次手动批准,如此反复,直到你最终不再阅读提示词。要么你直接采用 YOLO 模式,放手让它执行,只能祈祷 Agent 做的任何事情都不是不可逆的。但现在有了更好的办法。WorkOS 刚刚推出了 Airlock——面向 Agent、基于意图的访问控制。你可以用自然语言编写规则。例如:“可以读取代码仓库和 PR 上的评论。任何涉及作者计费的操作都需要审批。绝不推送到 main 分支。”Agent 发起的每一次调用,都会结合它的任务进行判断,并被允许、拒绝或转交给人类。Airlock 会记录每一次判定。Airlock 的巧妙之处在于,它没有预先授予的权限范围,也没有需要分派的规则。任务本身就定义了 Agent 可以做什么。WorkOS Airlock 目前处于抢先体验阶段。请前往 workos.com/airlock 申请体验。

[39:29] 我还想介绍一下我们的冠名赞助商 Turbopuffer。Matt 和我正在讨论一个根本问题:怎样才能让 Agent 记住重要的信息?这里有一个思路:与其构建复杂的记忆系统,何不直接让 Agent 搜索自己的全部历史记录?这听起来成本会非常非常高,但使用 Turbopuffer 就不会。Turbopuffer 原生基于对象存储的架构,意味着获取会话转写稿的边际成本几乎为零,因此,为全部聊天历史建立索引在经济上是可行的。而且,由于 Turbopuffer 的命名空间几乎可以无限扩展,你可以为每个 Agent 创建专属的搜索索引。这里有一个很好的例子。Entire 也是本播客本季的赞助商,它为数以亿计的 Agent 会话转写稿建立索引以供搜索,然后让编程 Agent 检索所需内容,从而回忆起某项工程决策是如何做出的,以及为什么这样决定。Entire 展示了这样的结果:与使用 Git 历史记录和 CLI 相比,使用 Turbopuffer 后,它的 Agent 准确率更高、使用的 token 更少,查找记忆所花的时间也更短。Agent 记忆是一个复杂且不断演变的应用场景。但也许这里存在一条

[40:29] “苦涩的教训”:最好的解决方案或许就是最简单的那个——搜索每一份转写稿。有了 Turbopuffer,这确实可以做到。如果你正在尝试解决 Agent 记忆问题,请通过 turbopuffer.com/pragmatic 联系 Turbopuffer 团队。你还创建了哪些其他 skill?所以从那里开始,我就在想:好,我怎样才能把那场对话转化成代码?我立刻就有点害怕,因为我一直在使用那些尚未足够好时的模型,也就是去年 12 月那个“寒冬”之前;后来情况真的变得非常好了。所以,我仍然受此前使用体验所形成的限制影响。我知道,比如说,你提供给 Agent 的上下文越多,它的表现就越差。我知道你曾邀请 Dex Horthy 来过这档播客。>> 对。Dex 对我的影响非常大,尤其是他提出的“智能区”和“愚钝区”概念。>> 智能区和愚钝区。对。>> 对。为了简单解释一下这个想法,这样你就不必去完整收听那期播客——尽管你应该去听——本质上,你提供给 Agent 的

[41:32] 上下文越多,每一个 token 都在争抢注意力。你让越多声音进入这个房间,就越难听清那些重要的声音。因此,模型会开始丢失事物之间的联系,并由此犯错。你可以把它看成一种缓慢的衰退。不过,上下文窗口中确实存在表现更好的区段,也有表现更差的区段。所以会有一个“智能区”;就目前而言,我认为前沿模型的智能区大约是最开始的 15 万个 token。>> 在一个拥有 100 万 token 的窗口里?>> 对。无论 token 窗口有多大,任何大小都一样。上下文窗口的大小并不重要。关键只在于 token 的绝对数量,以及注意力关系的绝对数量;越往后的部分,表现就会越来越差。>> 于是我开始思考,怎样把超过 15 万 token 的工作——其实这并不算很大——拆分到多个上下文窗口、多个会话中完成。为此我尝试了很多次,反复调整过许多不同的方法。Ralph Loop 就是其中一种

[42:33] 形式。Ralph Loop 的设计目标是充分利用智能区,因为本质上,你只需给 Ralph Loop 一个目标,然后告诉它:做出能让我们朝这个目标继续前进的最小改动,接着清空上下文。>> 然后清空上下文,重新开始。>> 没错。严格来说,你并不是完全从头开始,因为代码库还在,对吧?文件系统和环境里保存了一小部分状态,但模型里基本没有。这就是它的思路。于是我开始思考,怎样采用 Ralph Loop 的理念,同时让它更稳定一些,再把它转化为 skill。后来我意识到,我需要两种不同类型的文档。你需要一份描述前进方向的文档,也就是目标文档。>> 我以前把它叫作产品需求文档,现在则称它为规格文档。>> 因此,这份规格文档会声明你何时算是抵达终点。然后,你需要把这份规格拆解成独立的工单,每个会话处理一张工单。所以,我有一个非常简单的 skill:先转成规格,再转成工单。也就是说,你把已经完成的那场追问式讨论转化成一份

[43:33] 规格文档。比如说,这份规格文档可以覆盖三四十张工单。你可以有非常庞大、非常大的工作块,而它们全都与这份规格关联。这就是核心思路。你先进行追问,把追问所得转化成规格,然后针对这些工单运行某种实现循环,直到完成一大块工作。追问结束后,你还会让用户提供意见吗?或者说,在整个过程中会吗?>> 这要视情况而定。我设计这套流程主要是为了让它替用户运行,也就是让用户彻底离开键盘。>> 因为这里有一种“白班”和“夜班”的理念。你听说过吗?>> 没有,没有。>> 这很棒。基本上,与 Agent 协作的最佳方式是:白班时做规划,然后让 Agent 在夜班时工作,对吧?这样一来,希望你早上醒来时,就能看到漂亮、整洁的代码。这正是我试图优化自己流程的方向,因为我真的受够了自己过去的做法——某种程度上现在仍然如此——不停地在各个终端之间切换,不停地切换上下文,就这样砰、砰、砰、砰、

[44:33] 砰、砰地忙个不停。我想要的,也是我努力优化的方向,是先集中完成一大块规划工作,然后让 Agent 工作几个小时,这样我就可以去做其他工作;我可以用完整的时间段、每次 15 分钟专注做一件事、规划一些事情,之后再回来审查代码,诸如此类。所以,在做 Ralph Loop 时,我一直试图朝这个方向优化;而我在 12 月意识到的最大变化是:这些家伙已经足够优秀,可以把任务委派给它们,因此我可以让它们在我离开键盘时运行。然后你还有另一个更有雄心的 skill,叫作 Wayfinder skill。我们能聊聊它吗?>> 当然。和实现工作需要拆分到多个会话中完全一样,我注意到,有时你在通过追问厘清某件事时也会触及极限。比如你要追问厘清这样一个任务:“给我构建一个 Stripe 的克隆产品”,对吧?你一定会触及极限。你不可能在 15 万个 token 之内把它规划完。因此我就在想,怎样才能把它拆开,让追问会话可以无限延长,

[45:34] 对吧?怎样拆分追问过程,才能让它以这种方式运转?于是我又提出了这个想法。我本质上是在思考信息的流动:要想在一场追问会话中表现良好,它需要什么?它可能需要准确理解这场追问会话的目的是什么,同时也需要了解目前为止已经做出了哪些决定,还需要知道此刻可能正在进行哪些其他追问会话。于是,我想到了“地图”这个概念。这张地图会成为所有事务的中心点,容纳你正在做出的所有决策所需的信息。有了地图之后,你就会意识到:好,在我试图寻找通往目的地的路时,有些事情是我知道自己必须决定的,有些节点就像地图上的里程碑。同时还存在战争迷雾。这个美妙的隐喻就这样一路引导我设计出了这个 skill 的其余部分,对吧?因为你有地图,也有战争迷雾;你大致知道自己要去哪里,而每进行一次追问会话,地图上就会展开

[46:34] 更多节点。于是,你会逐步弄清前进的方向。这有点像一张有向无环图:你沿着图不断向下走,直到抵达最终目的地。所以你有一张地图,而其中的每个独立会话都是地图上的工单。然后我意识到:好,追问很有用,但如果你需要制作原型呢?如果你需要做研究呢?如果你需要执行某种任意任务,比如配置一些基础设施,又该怎么办?那么,它们就是地图上不同类型的工单。Wayfinder 基本上就是引导你完成这个过程。我用过一些地图,其中有五十张、一百张左右的工单,直到我最终抵达目的地。实际上,我也一直在用它规划课程,也就是处理非技术性的事情,效果非常好。我还在用它为自家花园建一间花园办公室。对。你知道,对于许多这样的 skill,我们会说:好,它们很适合工程工作。然后你会意识到:好,工程本身只是一门专业;我们在这里究竟是在做什么?我们只是在讨论某件事,在现实生活中执行各种操作,比如在

[47:34] 网站上到处点击之类的。你会意识到,这套方法可以多么轻松地映射到其他领域。所以,也许我们稍后可以再谈谈这一点,也就是我正在思考:这些东西可以在多大程度上迁移到不同专业和生活的不同领域。Wayfinder 一直非常好用。>> 对。不过,如果我们想一想工程和软件工程,一个很有意思的地方是:Hillel Wayne 来这档播客时,他采访了一些他认为是“真正工程师”的工程师,比如化学工程师、机械工程师和土木工程师,想弄清楚软件工程算不算真正的工程。最终,他发现它或许确实算。但他说,软件有一个非常有趣、而且与其他所有工程专业截然不同的地方,那就是我们使用的材料。在机械工程、土木工程乃至化学工程的每一个领域,你面对的材料都有各种指标的阈值。你并不确切知道它是什么样的,只知道它大概可以承受这么大的载荷,等等。但在软件领域,材料就是软件,而它就只是像程序那样运行。我的意思是,以

[48:34] ……并非确定性的,这或许会把我们带回更多工程领域。不过,软件和代码不同:你把它运行一千次,它一千次都会做同样的事,而在其他领域却不是这样。他说自己看到了很大的差异。但现在有了 LLM,我想我们或许也面对这样的东西:把它运行一千次,就会出现大多数工程领域都会有的这种变化。所以,谁知道对 LLM 有效的方法,是否也会对其他工程领域有用——毕竟,那些领域原本就存在这种变化——或者,我们能否借鉴其他工程专业的一些方法,让它们很好地适用于 AI 这种材料。>> 我完全同意。我觉得软件工程很有意思,Agent 之所以擅长它,是因为它的所有输入和输出全都以文本为基础,一切都是如此。输入包括代码、文档、告诉 Agent 要做什么的指令,全都以文本为基础;输出则是更多代码、测试套件,以及……

[49:36] 类型检查结果、代码检查结果,所有这些都是基于文本的。Agent 真正难以处理的是任何不以文本为基础的东西。但是,你也知道,我们会看到一些令人惊叹的演示:有人一次就生成了完美的用户界面。可要是那个界面存在交互问题呢?比如你把鼠标悬停在某个东西上面,动画看起来不对,那要怎么把这个问题交给 Agent?我的意思是,我想你可以录一段视频,然后让它在某些画面上暂停,诸如此类。嗯,但就视觉能力而言,它目前其实还没有那么好。因此,任何不以文本为基础的东西,Agent 处理起来都很糟糕,它就是应付不了。所以我认为,在那类专业中,如果你能把……我猜他们会做模拟,对吧?我猜他们会进行某种……你知道,我不知道是否存在一种能检查建筑图的代码检查器,但我相信你们一定有某种类似的东西,对吧?某种模拟。如果你能让它基于文本,如果你能把日常工作中的互动转化成文本——反正其中大部分本来就是文本——那么……

[50:36] Agent 就会做得相当不错。我现在正在尝试的一件事,就是把自己使用的所有服务都接入 Agent,对吧?让 Agent 能够使用它们。不过,是的,我们越能让工作适合 Agent,就越能得到更好的结果。回过头来谈谈整个 AI,以及它究竟改变了什么。它改变了太多事情,但谈到 AI 时,尤其是研究人员和 AI 公司从业者,常常会提出一种观点:面对 AI,不要预设先验;应该放下过去所知道的一切,因为这个东西不一样。要从头开始,过去的方法可能无效;事实上,不妨先假设它们无效,再想出新方法。你在 AI 出现之前就做过开发者,而且你确实非常关心如何打造高质量的优秀软件。你认为 AI 在多大程度上改变了一切,包括那些基本原则?我以前也这么想。我想,没错,AI 改变了一切,我要把孩子和洗澡水一起倒掉……

[51:38] 对吧?我觉得我们需要用全新的方式重新审视一切。我开始这么做,尤其是在研究规格驱动开发。你知道,我对它的感受有些复杂;我觉得这个术语很奇怪,涵盖的东西太多了。我当时想,好吧,也许英语就是炙手可热的新编程语言,对吧?>> 这句话曾在 Andrej 发出来之后火过一阵。>> 没错。也许我只要写一份规格说明,这份规格就会一直保留下来,成为我可以编辑的东西,然后随着进展,让 Agent 按照它进行修改。我做了很多实验,也尝试了很多次,但得到的结果就是比我手写代码更差,而且也没有越来越好。我注意到,每当我运行一遍这种循环——修改规格、观察代码变化——代码就会变得更糟。当然,按说你不该看代码,但我看了,代码就是一堆垃圾。我心想,Agent 在这种情况下怎么可能表现良好?这套方法怎么可能奏效?因为反馈循环对 Agent 至关重要。如果你的测试套件很差,Agent 就会……

[52:38] 从中得到糟糕的信号,就像人类一样。我开始想,怎样才能改善测试套件?怎样才能避免这套流程每次都不断产出垃圾?于是,我打开了书架上的一本书。我想,第一次把它拿出来时,它甚至还包着塑封,就是《程序员修炼之道》。嗯,大家都叫我读这本书。所有人都会说,你知道,这是有史以来最棒的书,你就是得读一读。于是我买了,却不知为什么一直没读。我打开它,发现里面有整整一章、整整一节都在讨论软件熵。软件熵这个概念是说,你知道,熵意味着事物会趋向于更加无序的状态;相比进入有序状态,进入无序状态的可能性更高。我意识到,好吧,软件熵不可避免。我在这里看到的是,Agent 正以前所未有的速度制造软件熵。我开始继续钻研那本书,几乎每读一句都会想:哇,这感觉就像是为今天写的。你真的应该回头看看那本书。里面有很多理念,比如不要让车速超出车灯照亮的范围、始终在反馈循环之内工作、偶然编程、示踪弹……

[53:40] 还有许多聪明的理念。我意识到,这本书已经出版 25 年了,对吧?这些内容很可能已经存在于 Agent 的先验知识中。也许我只要提到其中一些概念,尤其是那些非常精炼有力的概念,比如示踪弹——它表达的理念是,你应该始终迅速获得有关当前工作的反馈。示踪弹的意思大概是:就像示踪弹会留下轨迹一样,你先实现一条能够工作的路径,也就是软件中一个重要部分的完整路径;而不是先构建数据库层,再构建应用层,再构建那个……我也不知道,随便什么层,把三层全都建好之后再拼到一起。你只构建每一层的一小部分,但这些部分应当能够协同工作。这正是我在 Agent 身上看到的问题:即使使用 Ralph 循环让它构建一套软件,它也会先把整个数据库全部建好,然后在上面构建整个应用层,再构建整套 React 组件库。只有到了最后,它才真正开始把这些东西连接起来,并获取有关自己所做工作的反馈。这让人抓狂,因为数据库里的内容会影响……

[54:40] 你在前端显示的内容。你知道,只有看到它跨越这些集成层时,才真正知道这些东西是否合理。另一个概念是垂直切片,对吧?与其在不同的可部署单元之间进行水平切片,不如做一个垂直切片,让它立即获得对当前工作的反馈,再从那里逐步扩展。于是,我在和 Agent 对话时,开始把这些说法用进提示词里,并注意到它会把这些说法复述给我。它会重复我的用语。它会说:“好,我会把它做成一颗示踪弹,因为这就是一颗示踪弹。我会这样做。”它会在自己的推理轨迹中使用我所用的词。因此,我把它称为“引导词”,也可以叫作“主导词”;这是一个有点花哨的文学术语,意思是你只需在技能或提示词里把一个简单短语重复几次,就能引导 Agent 改变行为。示踪弹就是一个绝佳的例子。于是,我开始深入阅读不同的书,尽可能搜罗所有找得到的书,试着从中挖掘引导词。

[55:41] 另一本是 John Ousterhout 的《软件设计的哲学》,我从中学到了大量很棒的东西,比如“深模块”,这对我来说极其重要。值得思考的是,这些 Agent 显然已经用那些书训练过——那些书现在仍在出版销售。当然,对于他们如何使用这些书等问题也存在争议——但如果书中的内容存在于训练数据里,而且 Agent 在训练过程中把这些不同概念全都联系了起来,那么,是的,我想这些引导词就能唤起那些概念。我也在想,这和讨论某个主题时与专业人士交流究竟有多大差别:你作为外行努力描述自己想要什么,专业人士说出一个能够概括它的词,另一位专业人士马上就懂了。这就是术语,对吧?从一方面说,刚加入一家公司时,术语确实不太友好;但我们使用术语,是因为它能让事情更快、更容易,减少误解。>> 没错,这个想法也把我带到了另一个方向。因为显然,这些引导词存在于 Agent 的……

[56:42] 先验知识中,对吧?比如示踪弹以及所有类似概念。那该怎样描述我的应用?怎样描述我的代码?怎样才能让 Agent……因为 Agent 实在太啰嗦了,对吧?尤其是 Opus 5,不知道为什么,人们总是批评这个模型太啰嗦,而它也确实如此。我当时在想,怎样才能让它少说一点?我和 Agent 怎样才能开始使用一种共同语言,再次跨越这道沟通障碍?这把我带到了 DDD,也就是领域驱动设计。>> 领域驱动设计。Eric Evans 那本出色的书谈到了通用语言。这套语言同样深深存在于 Agent 的先验知识中,Agent 对它理解得非常好。我开始尝试一个想法:也许可以稍微改造一下 Grill Me,因为 Grill Me 是一个非常简单的技能。但是,如果我们在构思、思考准备构建的应用时,也同时建立一套领域语言,会怎么样?如果我们同时确定应该使用哪些恰当的术语,会怎么样?这最后变成了一个名叫 Grill with Docs 的技能,这个名字起得很糟糕……

[57:43] 但它本质上会随着过程推进创建这套领域语言。如果你让 Agent 使用领域语言,效果会有天壤之别,因为你们突然开始说同一种语言了。你可以用少得多的字来描述自己想修改的东西。比如,我有一个偶尔会做一做的应用,其中存在一种复杂交互,涉及“幽灵课程单元”和“真实课程单元”。如果把一门“幽灵课程”中一个“幽灵章节”内的“幽灵课程单元”变成“真实课程单元”,会发生什么?这意味着“幽灵章节”也需要变成真实的,“幽灵课程”也需要变成真实的。你要怎样解释这个过程?好吧,这就是“实体化级联”,对吧?>> 这些术语是你想出来的?>> 是和 Agent 一起想出来的,对吧?Agent 其实非常擅长提出这些术语。所以我有一个领域建模技能。我们说它是术语,但它实际上是领域语言。如果你能把它整合进来,不仅融入你谈论应用的方式,还融入应用代码本身,那就真正开始有意思了,对吧?这非常、非常令人兴奋,而且意味着 Agent 可以更轻松地浏览……

[58:43] 你的代码库。它只需要使用一次简单的 grep,就能找到提及某个特定领域术语的函数,实在太漂亮了。所以,我一直在把 DDD 融入整套配置的每一个部分。但这件事太有意思了:为了让这些 Agent 更高效地工作,或者建立能让你用更少错误产出更好软件的工作流,你开始回望过去,找到了这本如今已有——我想想,多少年了,20 年、30 年还是 40 年?——历史的书。而且,你还在继续回溯,从我们过去的成果中寻找珍宝。我相信你迟早会读到《人月神话》。>> 是的,我已经有了,当然。那本书现在已经超过 50 年了(笑)。你还在努力寻找描述事物的正确词语,这很耐人寻味,因为我和 Kent Beck 聊到他与 Ward Cunningham 当年如何编程时,他们那时正在提出设计模式这个概念,身边会放着一本同义词词典,然后翻阅它,试图找到……

[59:43] 一个含义准确的词,那本词典就放在他们桌上。现在,这感觉像是我们又回到了基本原则,回到了人们一直追问的“如何做”这个问题。每隔一段时间,就会有人把答案写进书里,它也会以智慧的形式逐渐传播。现在,我们又回到了最开始的地方,也就是你正在尝试……

[1:00:44] ——把你引向了一些非常有趣的路径。结果发现,软件开发的基本原则一直在说:我们从始至终不就是一直在努力做这件事吗?对吧?我完全是——我也不知道该怎么说——Eric Evans 派的。我完全信奉软件开发的基本原则。我们确实稍微改变了一些规则,但也许,我们只是更加重视那些我们明知应该遵守、却可能没有真正遵守的规则。我觉得这非常耐人寻味,也确实非常有趣。好,那么我觉得沿着这条思路,理解基本原则为何重要并不难,但究竟是哪些基本原则?如果我是一名工程师,尤其可能是那种一直埋头编程、更专注于技术性编码的人,我该如何找到那些真正重要的基本原则?回到刚才的问题,你发现哪些方法有效?这是个非常难的问题,真的很难,因为战略性编程向来非常难学。原因在于,它的反馈周期非常长。你经常会发现,有些人在工作六个月后就离职了,他们在战略层面犯下的——

[1:01:46] ——错误根本来不及追上他们,对吧?也许一个战略错误要过九个月才会反噬你。我觉得,学习战略性编程有点像面对一张巨大的调音台,上面有许许多多不同的推子。其中一个推子可能代表可部署单元的数量。往上推,你就会有更多微服务,对吧?往下拉,你得到的就是单体架构。你该如何做出这个决定?这个推子究竟该放在哪里?因为这有点像你正在精通某件事。你正在混音,却要到九个月之后才能听出哪里不对,对吧?要等错误找上门来才知道。所以我认为,唯一能缩短这个反馈周期的方法,就是加快推进速度。如今 AI 能让你推进得更快,对吧?于是,你的战略错误也会更快地找上门。它们之所以会更快地找上门,是因为 AI 能够生成海量代码。因此,你需要认识到:你的代码就是 Agent 的运行环境。你应该始终思考如何改善这个环境,思考怎样才能把它做得更好。当然,这需要一定的战术知识,对吧?你——

[1:02:46] ——需要理解代码是什么、各部分如何组合、内存限制是什么,以及诸如此类的事情。但要提高战略性编程能力,你只需要一直站在这个层面思考。我还会建议阅读这些书,因为仅仅是拥有一套能够解释这些问题的语言,并理解运用战略方法与不运用战略方法之间的差异,就已经是全部关键所在。我的意思是,在 AI 出现以前,对于高级开发者、高级工程师或资深工程师而言,他们往往就是这样一群人:你通常看不到工作经验不足五年的高级工程师,因为即使身处节奏很快的环境,你通常也需要那么长时间,才能经历足够多的反馈周期、犯下足够多属于自己的错误。等人们成为资深工程师时,往往已经有十年以上的经验。有些人会更早做到,但他们通常已经浑身都是战斗留下的伤疤。比如有人启动一个新项目时,他们会走进去,只做一个小小的调整,别人当下根本看不出原因,而他们会说:“这件事相信我。我们是在避免未来生产环境、值班响应之类的环节发生灾难。”但所有这些——

[1:03:48] ——都来自亲身经历。如今 AI 加快了进程,也让纠正错误变得更容易。所以我在想,这可能会带来怎样的变化。一方面,我能看到它如何加速经验积累:有些人、有些团队一年内交付的项目,可能比过去四年还多,或者大致相当于过去三四年的数量,所以你能获得多得多的经验。但我也在想,有时你犯下的错误可能不会那么严重,因为你很快就能修复它们。于是我又会怀疑,学习效果是否反而没那么深刻。还是那句话,其中一些战斗伤疤、这些惨痛故事,往往来自一次极其严重的服务中断:因为没有保证幂等性,我们损失了很多钱。当然,从此以后你就知道幂等性是什么了。它并不是一个容易理解的概念,但如果你曾被它伤害过,它就会变得非常重要,诸如此类。你想想,如果你现在是一家公司,想培养下一位初级开发者——因为战略性编程知识如今价值极高,你可以用它发挥高得多的杠杆作用——你——

[1:04:49] ——真的会雇用一个不具备这种知识的人吗?你为什么要这么做?前几天我采访了 Uncle Bob,也问过这个问题。他的建议是:好吧,你先雇一个人,然后在一段时间里把他们当作 Agent 对待。你只管把任务委派给他们。让他们暂时停留在战术执行的思维模式中,直到他们犯下的错误开始反过来找你的麻烦。但对人而言,这实在是在浪费一大笔钱,对吧?因为软件工程中的战术性工作,在许多国家的价值已经降到最低工资以下。所以答案是什么,我也不知道。我只知道,战略层面的东西、对代码的理解、对长期视角的理解,如今比以往任何时候都更有价值,对吧?因为你能借此获得巨大的杠杆作用。我向大家征集了他们想问你的有趣问题,其中一个与此高度相关。这个人问:“你要如何说服非工程部门的利益相关者,让他们相信投资软件开发的基本原则很重要,即使从纸面上看,这样做可能会降低速度和生产率?”我想,这个问题的意思是,有些人可能会主张:“听着,我们确实希望把基本原则——

[1:05:50] ——做好。这意味着我们想放慢一点,认真思考决策,也许还要让自己多学些东西,而不是只顾着不停产出。” >> 我的意思是,十年前你也完全可以问同样的问题,对吧?它在当时依然成立,你明白我的意思吧? >> 不过,那时我们想到的某些要素,可能会表述为“偿还技术债”。 >> 没错,这其实是同一件事,对吧?我们一直都在进行同样的讨论,这一点让我颇感欣慰。我的意思是,你需要某种指标来弄清这件事。如今要弄清它稍微容易了一些,因为 Agent 能让你更快地推进。第一步,是在整个组织中建立对每一个 Agent 的可观测性,了解它们各自在做什么,以及各自的成功率和失败率。 >> 我们过去从来无法像这样观察开发者。你知道,对开发者这么做多少有些侵犯性。 >> 是的,但对于 Agent 来说,这应该没问题。 >> 没问题,对吧?我们在为这项服务付费,对吧?我们需要了解自己对它的优化效果如何。这里的第一步,是在整个组织范围内围绕 Agent 建立一个测试框架或可观测系统,从而判断——

[1:06:50] ——什么有效、什么无效。你很可能需要一个人,把查看这些数据、弄清楚我们正在做什么,作为其全职工作或部分职责。也许你们组织中的某些代码仓库,成功率比其他代码仓库更高,那么你就提炼其中的经验,再把它们推广出去。我还认为,大多数组织都需要围绕一套共同的 skill 聚集起来。你需要一套共同的软件工作流程,让每个人都能反过来为它做贡献,也让你们能够开展实验。你可以做 A/B 测试。你知道,可以让一支团队采用一套做法,让另一支团队采用另一套做法,之后再询问他们的情况。因此,任何组织中与 Agent 协作的人都需要具备这种实验思维。你需要思考:怎样才能从我们花费的这些 token 中榨取更多价值?而可观测性就是第一步。 >> 是的。我还在想,这里是否也存在某种人类反馈循环。我的意思是,直接和同事聊聊就行。我们设立各种惯例、团队会议和全公司会议是有原因的,比如彼此分享:“这是对我有效的做法,这是它没奏效的地方,这是我正在学到的东西。”归根结底,规则由我们负责制定:我们决定如何使用它们、在哪里使用、在哪里不用,以及在哪里明确说“不,这件事——

[1:07:50] ——需要由人类百分之百接管,我们甚至不会让 AI 参与”。当然,这在每个地方都会有所不同。 >> 而且还不止如此:现在很多事情已经不需要人类始终参与了,对吧?要逐步构建一个更好的代码库,你其实不需要投入那么多时间来委派任务。我设置了一些循环流程,基本上每天早晨都会运行我的 improve-codebase-architecture skill,然后针对代码库中某项可以改进的内容给我一份提案。接下来,我只要按一下按钮就行。我可以说:“好,把它转换成任务单,然后我们来交付它。”这相当容易做到,也很容易把它和其他工作一起持续纳入流程。所以我在想——我不知道你是否需要把百分之二十的时间用来关注那个负责构建软件的“工厂”,同时也关注软件本身——因为我觉得,这是对未来杠杆效应一项极其可观的投资,而且——

[1:08:51] ——它不仅能提升你自己工作的杠杆效应,也能提升你所在团队的杠杆效应、理解能力,以及掌握这些 skill 的水平。当然,你需要拿出成果,而且可能要先把这项工作藏一阵子,之后再向大家揭晓:“这就是我们一直在做的事……” >> 嗯,这取决于你所处的环境,不过,是的。 >> 如果你回来告诉大家:“哦,顺便说一下,各位,我还做了这件事。”不会有人生你的气。 >> 对,没错。 >> 我想问问你具体是怎么使用工具的。第一个问题是:你使用的是本地还是云端的编程 Agent?你最近发了一条相当有挑衅意味的推文,我来引用一下:“我正在放弃本地开发环境。它对我来说毫无意义。”那么—— >> 很多人问我:“你怎么让自己的 skill 支持协作?怎样开展一场协作式盘问?”答案是,你不能只有自己和终端,对吧?我们现在处在这样一个阶段:每位开发者仿佛都有一百个终端可用。这听起来很疯狂。我感觉,这一百个终端需要对整个组织开放。你需要能够——

[1:09:52] ——在共享空间中协作。你需要能够邀请某个人加入你的盘问会话,然后说:“好,做这件事。”所以,对我而言,把许多这类互动放到你原本就在使用的工作场所里,非常合理,比如 Slack、Discord、Teams,或者 Linear。这确实是促使我探索这条路线的主要原因。我自己并没有特别和某个团队一起工作,但我理解这样做的价值,而且一直在尝试把它融入自己的流程。所以,坐火车来这里的路上,我就在 Discord 里和我的 Hetzner 服务器聊天,你知道,一边为课程构建内容,一边修复学生遇到的错误。现在,如果我有这样一套环境,可以把端口转发进去,并且在开发服务器做出更改时查看它,我就越来越看不到只在本地做这些事情的价值了。我不知道,我只是觉得,相比买一台非常非常昂贵的笔记本电脑来完成这些工作,这种方式合理得多。那感觉像是在浪费算力。尤其是在那台远程服务器上,我可以设置定时任务。我知道那台服务器会一直开着。我还会——

[1:10:52] ——每天早上和我的 Agent 开站会,由它为我安排一天的日程,而且它了解我所有的 Discord 对话以及诸如此类的信息。是的,对我来说,把这些放在远端就是合理得多。如今我唯一还在本地做的事,就是调试远程机器人的问题。 >> 是的。我在想,问题或许在于:要在云端复现一些更复杂的本地环境,究竟有多容易?但一旦这件事变得可行,它大概只是时间问题,而不是会不会发生的问题。 >> 是的。而且真要说的话,人们使用本地环境时也面临类似问题,对吧?比如上千个 Git worktree 不停塞满硬盘;又比如,我怎样才能拥有一个需要运行五个 Docker 容器才能启动本地开发环境的 worktree?其实在云端,这往往反而稍微容易一些,因为你可以按需配置所需资源。顺便说一下,我们已经看到 Ramp、Stripe、Uber 等公司设有平台团队,他们成功把开发者完整的本地环境搬到了云端,放到一台云端机器上。现在,你可以通过在 Slack 里提及它,或者通过一个网站来调用这套环境。

[1:11:53] 他们发现,除了前端工作之外,人们越来越多地使用这些 Agent。前端工作仍然需要那种反馈循环——确实有少数例外情况,为了延迟之类的问题,你会很想拥有本地开发环境——但他们也发现,大约 70% 到 80% 的开发者会自愿选择云端。>> 是的。我的意思是,你可以直接通过隧道连接;如果云端正在运行开发服务器,就让它显示在你的本地机器上。这和把它放在本地有什么区别,对吧?>> 好吧。>> 我不知道。我想我没有试过这样做,但当我谈到这个问题,说“哦,也许前端是个很好的例外”时,我立刻得到的就是这个回答,而且我觉得很有道理。>> 我想问问你对规划和需求的看法。你非常相信 Grill Me,也很重视规划、事先做好规划,或者先得到计划,再让 Agent 工作。但这里也有一种反方观点:Agent 实现东西的速度非常快。实际上,你甚至可以让几个 Agent 分别实现不同的架构。那这种思路怎么样:既然它们实现得这么快,那么我也许

[1:12:54] 不需要预先做那么多规划,可以边走边修正方向。这取决于你在做哪种工作,对吧?因为我认为你不该事事都使用 Grill Me。从根本上说,当实际要做的东西会非常庞大,而且很难撤回时,你才需要 Grill Me。如果你觉得,好吧,这个功能也许是一个全新的页面,也许是一项大型功能;而且你认为,如果 Agent 做错了,那么错误的代码就会进入它的上下文窗口,影响之后的一切。事后再回去编辑那些东西,并在完成后再进行对齐,其成本会很高。那么在这些情况下,先对齐就很合理:先回答所有棘手的问题,比如你的 JWT cookie,或者不管什么身份验证 token,然后再动手。但在某些情况下,比如简单的错误修复,或者只是把这个按钮向左移动三个像素,显然就不需要事先对齐。如果只是

[1:13:54] 改动五行代码之类的小事,你可以事后再对齐。所以我的思路是:只要可以,就应该尽可能把对齐右移到后面。实际上,我确实有一些这样的功能:在我的视频编辑器里,有一个按钮可以让我提交反馈。我经常用它处理非常简单的任务。我提交反馈后,它会进入一个 GitHub issue,随后立刻被一个实现 Agent 接手并直接处理。接着,一个代码审查 Agent 会进来审查代码,最后我能看到这个东西实际修复后的样子,并在那时进行对齐。这种方式非常适合那些很容易描述、不需要深入追问的事情。所以,你有这些选择:事情是否足够小,可以事后对齐?如果是,就不要使用 Grill Me。它是否能在单个会话中完成?如果是,就使用 Grill Me。它是否跨越多个会话,我是否需要对整个事情进行对齐?如果是,就使用 Wayfinder。这很有意思,因为它与一些科技公司多年前最终采用的做法并没有太大不同,

[1:14:55] 也就是 PRD,也就是产品需求文档。如果事情微不足道,那就直接做。如果需要团队参与,比如范围达到了团队级别,那就写一份 PRD,发给团队,也许再抄送其他一些团队,但不把它设为阻塞项。如果事情更大,那它就是阻塞项:我们需要等待反馈。基本上,我们会这样说:听着,如果这是一个为期一个月的项目,那就花两天时间规划;花一两天进行规划并不是坏事,因为这会为我们节省时间。但如果这是一个只需一天的项目,那就算了。如果这是一个为期一年的项目,我的意思是,我们到底在做什么?它是不是应该拆得更小?>> 完全同意。当你这么说时,我仿佛能听到房间外面传来一点批评:这听起来难道不像瀑布式开发吗?当我谈论 Wayfinder,或者在构建任何形式的规格说明时,在走到那一步之前,我都会做大量积极的前期原型开发。这个质疑一次又一次地出现:“这不就是瀑布式开发吗?我们这是要回到 20 世纪 70 年代吗?”但 Agent 让你能够

[1:15:56] 大量产出粗糙的东西,对吧?有时你可以利用这一点,因为原型的作用,就是让你感受一下它应该是什么样子。你可以构建三四个不同的版本,挑一个自己最喜欢的,然后在它的基础上迭代,继续不断地做、不断地做、不断地做。这可以成为一种非常强大的工作方式,是我们以前并不真正具备的,对吧?制作原型过去一直成本高昂,而现在它比以往任何时候都便宜。对我来说,实际制作这些原型,是编写规格说明必不可少的一部分。>> 是的。不过说到对瀑布式开发的批评,我想 Grady Booch 可能也对我说过这件事:别忘了,我们不该批评瀑布式开发。比如,包括 Amazon、Microsoft、Google、Meta 等在内的许多大型科技公司,也就是那些规模最大的科技公司,在 AI 出现之前就在某种程度上采用“小型瀑布式开发”:我们制定一个计划,就计划达成一致,然后构建它、发布它。这一切会在两周、一个月、两个月或三个月内完成;三个月基本上已经是极端情况了。但 Grady Booch 说,瀑布式开发的问题从来不在这里。问题

[1:16:56] 在于,规划真的会花上一年,然后实现再花三年;等到四年后终于做好时,它已经不是我们想要的东西了。这才是问题所在。他的意思是,问题不在于用瀑布式开发方式做一个一两个月或一周的项目;问题一直在于,我们谈论的是数年之久。他还说,这个行业已经几十年没见过那种瀑布式开发了。所以,我们现在使用这个词,听起来有点像是在批评它,或者说许多小型瀑布式开发也因此受到批评。但实际上,那未必是坏事。你明白我的意思吗?>> 就像我们竖起了一个稻草人,然后对着它猛打之类的。>> 是的。它是一个早已不复存在的皮纳塔。它也许仍存在于某些疯狂的企业项目里,那些项目身处受监管行业,我们谁都不了解。但我觉得,即使在那里,它大概也已经过时了。>> 是的。我觉得,如果我们是在击打皮纳塔,那把它挂在那里其实是有用的。它像一个有用的幽灵,或者一个有用的警示故事,对吧?因为哪一种方式更符合 Agent 式的工作模式?

[1:17:58] 应该是敏捷开发,对吧?因为劳动力成本已经下降了这么多,我们可以非常、非常快地进行修改。我不知道,但对我来说,这似乎是恰当的比喻。所以,即使已经没有人真正采用瀑布式开发了,我也不介意继续批评它。>> 还有一样东西刚刚过时了。我们并不讨厌它,但它就是过时了,那就是测试驱动开发,也就是 TDD。你怎么看待把它用于 Agent 相关的工作?我和 Kent Beck 交谈时,我们谈到过,出于很多原因,它可能非常适合这类工作,但我仍然没看到人们真正使用它。我看到人们编写测试,Agent 也会事后编写测试,而大多数人就是这么工作的。但我想,你一直是 TDD 的倡导者,对吧?>> 是的。我有一个 TDD skill,我建议使用它。这正好很应景,因为我一直在思考这个问题,只是还没有真正发帖谈过。TDD 是为非常小的工作记忆优化的,对吧?你写一个测试,而且这个测试应该失败。这意味着,即使你分了心,出去喝杯咖啡之类的,或者出去走了很久,回来时测试仍然处于失败状态,提醒你实现工作进行到了哪里,

[1:18:59] 并引导你去做下一件事。Agent 不需要这个。Agent 的一大优势是,它们的工作记忆比人类大得多,对吧?它们实际上能在脑中同时容纳比人类目前多得多的内容,这非常有用。但它们的工作记忆并不是无限的。而且我认为,TDD 所瞄准的问题有些不对。不过,Agent 真正需要的是反馈循环。它们需要看到自己正在做什么,以及所做的事情如何与代码所处的环境交互。它们需要不断进行探测。让 Agent 先构建出失败场景,也让 Agent 很难在这件事上作弊。因此,你不只是在迫使 Agent 构建自己的反馈循环;随着工作的推进,Agent 也在向你提供证据,证明这个东西确实有效。即使我没有直接采用 TDD,也就是你知道的,先编写失败的测试,

[1:19:59] 然后修复它,再重构,我也经常会说:“请提供证据,证明你的改动确实实现了它声称要实现的功能。给我 TDD 证据,对吧?证明如果没有这项改动,它就会失败。”这对改善反馈循环一直非常有效。因为 Agent 在 TDD 上还经常犯另一个错误:它们往往只会编写糟糕的测试。尤其是,它们经常写出同义反复式测试,也就是测试只是对实现本身作出断言,完全像是实现的一个副本。你知道,它先写了一个常量,然后说,预期这个常量等于这个值。我的意思是,这种测试有什么意义?它只是在对实现作出断言。所以,是的,我对 TDD 的态度很复杂。我仍然推荐它,只是因为从人的角度来看,它能让你对自己正在构建的东西多很多信心。不过,是的,我开始理解那些反对意见了。>> 我们来谈谈技术债。Y Combinator 的 Jared Friedman 写了

[1:21:00] 一条推文,我引用一下:“过去,只要代码库足够大,技术债就是你不得不忍受的东西。现在不再是了。”而你回复他说:“没错,现在即使在一个很小的代码库里,你也可以忍受技术债。”[笑声] >> 这句不错。其实我把它大声念出来了。你确实把那句话的感觉传达出来了。嗯,是的,让 Agent 产出垃圾实在太容易了,对吧?即使是非常聪明、能力很强的 Agent 也一样,因为它们无法从战略层面思考,只会专注于眼下正在做的事情。它们非常容易制造技术债。嗯,什么是技术债?技术债就是任何会让代码库随着时间推移变得更难修改的东西。好的代码库应该易于修改,容易在其中做出改动,而且改动不会引发级联故障,对吧?所以,一个测试覆盖扎实、测试套件良好的代码库,就是一个容易修改的代码库。>> 是的。>> 但 Agent 实在太容易让代码库随着时间推移而变得更糟。

[1:22:01] >> 是的。这是一个非常棘手的问题,而且需要用战略思维来考虑,因为我发现有一种方法非常有效,那就是自动化审查。你让一个实现 Agent 去完成工作,然后让另一个自动化审查 Agent 介入;它会贯彻你的编码标准,寻找这些同义反复式测试,并逐步提高测试套件的质量。但你又怎么知道这个自动化审查 Agent 是否做得好呢?所以,即使在很小的代码库里,甚至只是改动一行代码,Agent 也可能产出垃圾。你知道,我认为这就是我们需要接受的事情,也是我们需要不断与之斗争的事情。>> 这也不完全是坏事。当你了解好代码是什么样子、能够识别技术债时,我们就能带来很多价值。>> 而且,这也是一个我们一直都有的问题。你明白我的意思吗?比如,>> 它并没有消失。>> 没有消失。你知道,我就是这种感觉:我们只是在重复过去 20 年里一直进行的那些讨论,只是现在房间里多了一头新的大象。我

[1:23:01] >> 我想问问你关于生活在英国和 AI 的问题。这也是一位读者提出的问题。现在你住在英国,而且不在伦敦,但你如今正在教授 AI 相关知识。远离 Silicon Valley 和那些实验室的总部,对你而言是让事情变得更容易,还是更困难?>> 我其实只是在努力耕耘自己的一亩三分地。我很早就意识到,自己没有能力预测未来,对吧?因为我离这些事情太远了。我只是一个在一线使用这些东西的人。我没有办法知道接下来会发生什么,对吧?我不知道模型会不会进步,也没有获得这些东西的特权访问权。所以,我只是努力专注于当下真正有效的东西。正因为如此,我认为自己的关注范围缩小了一些。这意味着,我只需要努力让自己的东西正常运转。让我颇感意外的是,它们运行得竟然这么好,你知道,因为我并没有这种特权访问权。我只是

[1:24:02] 努力让这一种方法奏效。所以我想,是的,你大概说得对。如果我住在旧金山,我或许确实能做这些事,但那样我就不得不住在旧金山。你知道,我不想那么做,那太痛苦了。我在这里的生活条件很好,父母就住在不远处,儿子也能在乡间长大。所以,现实就是这样。嗯,是的,你骨子里是一名教育者。你看到教授或培养软件工程师这门生意发生了哪些变化?人们想要的学习方式又发生了哪些变化?如果你观察到过什么趋势的话,比如你刚开始时,我感觉你赶上了在线课程和视频学习变得越来越流行的时期;再往前大约十年,人们可能更偏爱教程,而更早以前则是书。当然,这些形式现在依然存在,只是人们的偏好有所不同。是的,大约在新冠疫情期间,视频教程真正兴盛了起来。我觉得人们想要丰富得多的学习体验,而我想自己差不多正好赶在那波浪潮之后。

[1:25:02] 我认为,人们的学习方式其实没有发生太大变化,对某些材料类型的需求也没有改变。让一个 Agent 直接出现并把一切都教给你,这种想法听起来非常诱人。它在某些情境下确实有用,但你真正需要的是策划,对吧?你需要一个人介入,理解信息流动的顺序。我总是把信息看成一种图,对吧?一条信息依赖另一条信息,后者又依赖再一条信息。而把这张图转化成一条线性路径,就是我对自己这份工作的理解。我的工作只是教你如何在图中找到 Dijkstra 算法式的路径,让你能以最合理的方式学习。这种程度的策划同样属于战略层面,对吧?这并不是 AI 特别擅长的事情。所以,我显然已经做出了一次巨大的转型,从 TypeScript、从战术层面的内容,真正转向了这个战略层面。

[1:26:04] 对我而言,目前进展还可以。我确实没法替其他从事这类工作的人发言,而且我知道很多人并没有取得这种程度的成功。我想,这说明 Agent 已经彻底改变了人们看重什么、优先考虑什么;这个行业在七个月内发生的变化,比我认为它以往任何时候都要快。你知道,这是一次巨大的转变。这并不意味着我们需要抛弃原有的工作实践,但确实意味着我们需要关注的重点已经不同了。我觉得自己很好地跟上了这种变化,而其他一些人没有做到,因为他们关注的是不同的事情。我在想,就你而言,无论是 Total TypeScript,还是更早围绕 TypeScript 和其他一些主题分享内容时,你其实都是在帮助人们使用当时非常流行的工具。TypeScript 的市场份额正在增长,当时有从 Java 迁移到 TypeScript、从 Python 迁移到 TypeScript 等各种迁移项目。

[1:27:04] 所以,很多开发者——或者说其中最顶尖的 10% 或 20%,比例随你怎么说——都想把 TypeScript 掌握得非常、非常好,也在寻找高效的学习方法。现在 AI 出现了,正在改变软件工程师的工作方式。我认为,构建软件依然有价值,但眼下更迫切的问题是:我怎样才能更高效地使用这些工具?而不是:我怎样才能高效地编写 TypeScript?尤其是在有 Agent 的情况下。所以我在想,你似乎只是再次做了一个小小的转向:就像你曾经从配音表演——那是你在伦敦以外无法从事的工作——转向一件可以在伦敦以外做、同时仍然属于教学的事;如今你只是改为教授另一个领域,而这个领域此刻同样萦绕在许多人的脑海里。我觉得自己基本上只是很幸运,在恰当的时间选对了事情。其实,我本来很容易走上另一条路;而且我当时是被劝了相当久,才开始转向 AI。大概几年前,是我的商业伙伴 Joel 一直在推动我,跟我说:“你真的得试试这个,它其实相当不错,而且你可以拿它做各种各样的事。”

[1:28:05] 我真正开始尝试之后,试了又失败、失败了又试,大约过了三个月,我才意识到:“好吧,这东西太棒了。”我只是觉得自己非常幸运,在正确的时间落在了正确的位置。我尽量不把这件事编成一个事后看来顺理成章的故事。我不会想:“干得漂亮,Matt。你真聪明,恰好在正确的时间走出了正确的一步。”因为我本来也可能走向别处,而且我确实也犯过好几次错误,很容易就会进入另一个领域。其实那也不是什么坏事,我只会回去继续当工程师,那也是我热爱的工作。现在,请你设身处地回到自己刚入行时的状态。对于今天刚入行、尚处于职业生涯早期的初级从业者,你会建议他们采取哪些战术层面的具体行动?他们会知道:“听着,我想积累那些经验,形成那种判断力、品位,掌握那些基本功。我需要反复练习。”如果你现在处在他们的位置,会怎样处理这个问题:“我想成为一名创造者、一名软件工程师,而现在又有这么多 AI 工具之类的东西。”这会让人困惑,因为现在的问题混杂在一起:我是该用这些 AI……

[1:29:06] ……工具直接替我完成事情?还是应该去打基础,尽管那样比较慢?是的,我是说,我非常希望自己现在就是个初级工程师。我很想回到 2014 年前后自己所处的那个位置,当时我正在为学生制作这些工具,对吧?前几天我想到这件事时,真的非常怀念。我想,我很愿意回去教一些声乐,因为现在完全可以这样做:一节课结束后,我只要向 Agent 发出提示:“好,这个工具刚才没有完全按照那种方式工作,也许我可以稍微修改一下。”然后就能看着它开始运行。我认为正确的做法就是尽可能多地使用这些 Agent,因为今后人们就是会这样工作。我觉得自己的技能组合之所以有价值,是因为你始终与正在发生的变化保持接触。Grill Me 不仅意味着你在与一位高级开发者讨论,对吧?这对那位开发者有帮助,对你也有帮助,它会让你持续思考这些更深层的理念。而我当时用自己的频谱图分析工具做出来的那些彻头彻尾的垃圾……

[1:30:06] ……如果当时能有一个 Agent 与我协作,一定会好得多。它运行起来慢得像头猪,性能糟糕透顶。如果当时我能说:“好,现在帧率已经降到了每秒 10 帧,我该怎么修复?”它就会看到那六层嵌套的 for 循环,然后说:“好吧,也许你应该换一种做法。”所以我认为,从来没有哪个时代比现在更能赋予从事这类工作的人力量——只要你感兴趣的不只是自己产出的代码,还包括创造代码的过程。对于成为一名不断向内审视的程序员而言,从来没有比现在更好的时代:你可以不断思考自己的流程,不断自省。所以听起来,如果你有动力,应该能比过去学得快得多。绝对如此。关键就在于保持好奇、保持适应能力。我看到在这个新环境中蓬勃发展的人,和十年前蓬勃发展的其实是同一类人,因为他们对这项工作感兴趣,对打造更好的软件感兴趣,也对自己的过程感兴趣。

[1:31:06] 说到对打造更好的软件感兴趣,我想问问你关于“园艺”的看法。X 上有一位软件工程师 Lauren 发过一条帖子,我来引用一下:“每个团队都需要一名园丁。这个人默默观察着不断流入代码库的 PR,留意其中的坏味道,也留意那些像常春藤一样在你精心照料的花园里蔓延的 lint 抑制标记。他用稳定的双手照料杂草,否则这些杂草终将吞没整个花园。”对此你回复道:“要我说,你的团队唯一需要的就是园丁。”你可能确实还需要另外几个人。是的,是的。(笑声)但更具体地说,我想问你这个“园艺”的概念。我真的很喜欢 Lauren 描述杂草侵占花园以及把它们清除出去的方式。我想自己前段时间发过一条帖子,当时我在思考 Ralph,以及让 Agent 围绕任务不断循环。我们现在本质上只是 Ralph 的平台团队,对吧?这就是我们如今的角色。我们是自己那些 Agent 的平台团队,正在努力为它们构建能够取得成功的环境。你就应该这样看待这件事。同样,这是战略层面的工作。这个园丁的比喻很好,因为,你知道……

[1:32:07] ……花园本身很容易遭受熵增,对吧?它会长出杂草,出现诸如此类的情况。所以,在这些问题真正成为代码库里的麻烦之前就理解并诊断它们,是一种必不可少的技能,甚至可能是最核心的技能。只要你能把工作排进 Agent 的队列,只要你能构建这些循环——现在我们已经开始看到这样的流程:Agent 会根据错误报告和反馈来改进代码库——在我看来,这就是非常酷的工作,也是高尚而有趣的工作。我们今天谈到过一些非常杰出的软件工程实践,它们给了你启发,你也从中学到了东西。你认为,哪些技能组合、经验和方法能造就一名优秀的软件工程师?我举一个例子:Lars Grammel,他在 Vercel 负责 AI SDK,我前几天刚和他聊过。他正在为自己那个极受欢迎、会收到大量问题反馈的开源……

[1:33:07] ……库打造一整套软件工厂。我们又回到了管道和园艺的话题,讨论的是软件开发的流程。如果非要用一个词来概括,我想那就是“自省”。也就是审视自己,并且有能力把自己所做的事转化成 AI 可以使用的东西。你本质上是在努力把自己的流程诉诸文字。这就是我一直在用技能做的事,也是我一直试图通过自己创建的自动化流程去做的事。我只是观察自己在做什么,然后想:“我怎样才能把这件事做得更好?另外,我怎样才能把它编码进眼前这个奇怪的动物里?怎样才能让它按照我的期望工作?”这种态度对我非常、非常有帮助,也是 Lars 身上让我重视的品质;当与我合作的所有人使用 Agent 时,我同样看重他们身上的这种品质。最后,有哪一本或哪几本书是你会推荐的?我会选《程序员修炼之道》、John Ousterhout 的《软件设计的哲学》,以及 Eric Evans 那本 DDD 著作的前三章,也就是讲“通用语言”的那一本。尤其是最后这本,其中关于通用语言的概念非常精彩。至于领域建模以及真正把它编码进代码的部分,我没有那么喜欢,不过这三本就是最重要的三本。

[1:34:08] 太棒了。Matt,谢谢你。这次交流真的很有意思,也非常愉快。很高兴终于登上这个播客。是啊,终于见到了那位名人本人,太棒了。当然,我们以前见过,但很高兴来到这里。能坐下来和 Matt 交流实在太好了。我必须说,知道他曾经是声乐教练和演员以后,我终于明白他为什么说话如此流畅,也明白他的声音为什么如此悦耳。这次对话中最有意思的部分,大概是 Matt 在寻找如何更好地与 AI 协作时,发现真正有用的并不是现代方法。相反,他回到了那些经典的软件工程书籍:《程序员修炼之道》《软件设计的哲学》和《领域驱动设计》。颇具讽刺意味的是,那些记录于二十多年前的最佳实践,比如战术式编程与战略式编程之间的区别,不仅至今依然有效,而且在使用 AI Agent 编写代码时变得更加重要。

[1:35:08] 我还想强调一个相关的观点:在使用 AI 时,引导性词语非常重要。当 Matt 开始使用“曳光弹”或“垂直切片”之类的术语时,模型在规划阶段就能更好地跟随他的思路。仔细想想,这很合理,因为软件工程文献是 LLM 训练材料的一部分,所以这些术语也属于模型的先验知识。同样有趣的是,使用恰当的词语来描述问题并不是一个新概念。例如,Kent Beck 做客这个播客时曾谈到,三十或三十五年前,他和 Ward Cunningham 的桌上放着一篇论文,他们会借助它为自己正在描述的特定事物寻找最合适的词。这又是一个首尾相接的时刻,说明措辞确实很重要。最后,我很认同 Matt 强调的观点:你应该希望自己的代码库保持整洁。这不仅因为它更便于人类浏览——尽管我认为仅凭这一点,你也确实应该把它做好——还因为有一个很方便的事实:Agent 并没有……

[1:36:08] ……长期记忆,每次开始新的运行时,它们都会像第一次一样查看你的代码库。在结构良好的代码库中穿行,要比在杂乱不堪的代码库中容易得多。请查看下方的节目说明,其中有对《软件设计的哲学》作者 John Ousterhout 的采访——这是一本我非常喜欢的书——还有关于 AI 工程和上下文工程的相关深度解析。如果你喜欢这一期节目,请务必在你使用的播客播放器中订阅;如果愿意提交评分,我们也始终非常感谢。谢谢,我们下期再见。

原始字幕说明

英文自动字幕原始 JSON 保存在本地:/tmp/youtube-4DhcSPkEbwI/raw-transcript.json。本文保留了全部 96 个段落级时间戳,逐句回查以原视频为准。