Skip to content

结课:从 10 行代码到 Agent 六大支柱

约 18 分钟

这门课是从 10 行代码开始的。

讲 Agent 本质的那一篇,我们写下了这个最小循环:

typescript

复制

typescript
while (true) {
  const response = await llm.chat(messages)

  if (response.toolCalls.length === 0) {
    break
  }

  for (const toolCall of response.toolCalls) {
    const result = await executeTool(toolCall)
    messages.push(result)
  }
}

当时我说,别小看这个循环。

三十多篇过去了,现在我想请你做一件事:把这段代码再读一遍

你可以一行一行读。

如果这门课起了作用,你现在看到的东西应该跟第一次完全不同。当初它只是一段普通的 demo 代码,而现在,每一行背后你都能看到一整片工程世界。

说实话,这就是我能想到的最好的结课方式——不灌新知识了,我们把学过的所有东西,沿着这 10 行代码重新串一遍。你会发现它们原本就长在一起。

第一行:while (true)

为什么用 while(true),当初我们聊过——你不知道任务要跑多少轮,Agent 必须是开放式的,干完为止。

这一行同时也是 ChatBot 和 Agent 的分界线。循环的控制权从人手里交到了模型手里,人退到副驾驶的位置,只在关键节点踩刹车。谁掌控循环,谁就是 Agent。

但控制权交出去的那一刻,新的问题跟着就来了:它不会自己停。

你应该还记得保险丝那篇的场景——一个替换 console.log 的小任务,Agent 反复改同一个文件,15 分钟跑了 200 轮,50 美金没了。所以生产级的循环里要埋保险丝:死循环检测(同样的工具配同样的参数反复出现,哈希一对比就知道)、token 预算(烧到 90% 时 nudge 它收尾)、输出截断的递进恢复。Claude Code 给这个循环设计了七种退出路径,每一种对应一类"该停了"的场景。

一个 while(true),从"它怎么跑起来"到"它怎么停下来",这就是 Agent Loop 那一章的全部内容。

第二行:await llm.chat(messages)

整段代码里最不起眼的一行,藏的工程量最大。

这个 await 等的是一个随时会挂的远程服务。429 限流、529 过载、连接超时、流推到一半断掉——API 容错那篇讲的三层防线(指数退避重试、流式降级为非流式、跨模型 failover),全裹在这一行里。

而且在生产环境里,这一行拿到的也只是一条 SSE 事件流。流式那篇我们拆过:tool call 的参数是 JSON 碎片一片一片推过来的,得攒完整才能解析;Read 可以并发执行,Edit 必须串行;结果要按调用的顺序返回,哪怕后调的先跑完。"边说边执行"这四个字,背后是一整套并发设计。

还有钱的问题。同样一行 llm.chat,Prompt Cache 命中和不命中,成本差接近 10 倍。这就是为什么我们专门花了一篇成本控制,尤其是 Prompt Cache——前缀稳定才有缓存,有缓存成本才压得住。

第三行:response.toolCalls

Function Calling 那篇的第一个认知纠偏,我希望你还记得:模型从来没有"调用"过任何函数。 它只是生成了一段符合 JSON Schema 的文本,表达了一个意图。真正去执行的,从头到尾都是你的代码。

意图和执行之间相当于隔着一条河,这条河上我们架了很多东西。

七步执行管线——参数校验、业务校验、输入补全、前后 Hook、权限检查。模型说要跑 rm -rf /,你真的就执行了?权限那篇的四层防线,本质上是在给一个概率性的系统加确定性的边界。

还有工具数量那个反直觉的结论——工具从 10 个加到 50 个,选择准确率从 95% 掉到 50% 以下。于是有了 Deferred Loading 按需加载,有了 Tool Profile 按场景裁剪,有了 Manus 的 "Mask Don't Remove"。于是你能理解为什么 MCP 协议很好、但 token 占用和注入风险是实打实的硬伤;也能理解为什么 Skills 走"让模型读文档"这条它最擅长的路,就接管了大量原本要靠协议解决的事。

第四行:messages.push(result)

如果让我在整段代码里选最贵的一行,那就是它。

每一轮循环都在往 messages 里塞东西。这个数组就是上下文,而上下文是 Agent 系统里最稀缺的资源——比 CPU 稀缺,比内存稀缺,甚至比钱稀缺,因为注意力的稀释连模型自己都控制不了。

Context Engineering 是这门课最重的一章,全部围绕这一行代码:

什么东西有资格被 push 进来(入口管理,几十 K 字符的工具结果先截断再进门);满了怎么办(压缩是续命,重置是重生);进来之后怎么排(静态在前、动态在后,要照顾好缓存);以及能不能干脆先不 push,需要的时候再去拿(JIT 按需加载,拿 grep 和文件系统当外挂大脑)。

学到这里你也该看清一件事了:上下文管理是应用层和模型层之间最清晰的分界线。 模型能力你改不了,但喂什么、什么时候喂、按什么顺序喂,全是你作为 Agent 开发者的决策。

循环结束之后:被丢掉的 messages

代码跑完,break 跳出循环,messages 数组随着进程退出被丢弃。

用户第二天回来,Agent 又一脸陌生地问:"这个项目用什么包管理器?"

Memory 那两篇就是从这个缺口长出来的。把对话里值得留的东西沉淀下来——文件派用 MEMORY.md,可读、可 git diff、可审计;数据库派上向量加全文索引,量大了还能做语义检索。再往外一圈是 RAG 和编译知识库:模型没见过的资料,检索回来;查过的好答案,反写回 wiki,让知识有复利。

这一章还有一条我反复强调的原则,值得你带走一直记着:记忆是线索,不能当事实用。

一个循环装不下:开第二个循环

分析一个 200 个文件的仓库,一个上下文窗口塞不下,怎么办?

Multi-Agent 那章给的答案,到今天我依然觉得是全课最重要的认知纠偏之一:拆 Agent 拆的从来都是上下文,角色分工只是顺带的。 子 Agent 在自己的窗口里烧掉几万 token 做探索,最后只把 1-2K 的结论带回来——10 到 20 倍的压缩比,父 Agent 的上下文始终干净。

只有当子任务之间需要中途协商时,才升级到 Swarm:Mailbox 通信、共享任务列表、权限代理回 Leader。

包住这一切的壳:Harness

最后,把上面所有东西装进一个容器,这个容器就是 Harness。

Harness 那篇我们给过正式定义:每一个组件,都编码了一个"模型自己做不到"的假设。 保险丝假设模型不会自己停,压缩假设上下文会退化,MEMORY.md 假设模型记不住你,Evaluator 假设模型评不准自己的产出。

往后的几篇都是这个壳的具体切面:Hook 和可观测性是它的感知系统,部署和调度决定它跑在哪里、什么时候跑,ACP 是别人接入它的标准插座。再回头看框架——LangGraph 也好,OpenAI Agents SDK 也好——你会发现它们只是把这些问题用不同的方式打了个包:有的包了 Loop 和持久化,有的包了 Memory,但 Context 这一层几乎全是空白,还得你自己来。

全课知识地图:六大支柱都长在这 10 行代码上——Agent Loop(心跳)、Tool System(手脚)、Context Engineering(血液)、Memory & RAG(长期记忆)、Multi-Agent(分身)、Harness(外壳)

把这张图摊开看一眼。中间那个小循环,就是你第一天写的 10 行代码。外面一圈圈长出来的,是这三十多篇的全部内容。

串完之后,三条暗线浮出来了

知识点串完了。但如果只串知识点,这门课的价值会衰减得很快——产品会变,源码会变,今天的实现细节明年就过时了。

所以结课之前,我想把我在设计这门课程的时候,藏在所有章节底下的三条暗线挑明跟大家说一说。这三样东西,比任何一个具体机制都活得久。

第一条:几乎所有问题,拆到最后都是上下文问题。

你想想我们一路遇到的麻烦:

工具多了选不准,是因为几十个 Schema 挤在上下文里稀释注意力;MCP 的硬伤,是工具描述全量塞进上下文;Multi-Agent 的真正动机,是上下文装不下;Memory 解决的是上下文活不过这次会话;Prompt Cache 省钱靠的是上下文前缀稳定;连 Harness 里那个"成功沉默、失败发声"的原则,本质也是在保护上下文别被无用信息淹没。

六个看似无关的问题,拆到最后是同一个根本问题——Context Engineering:让模型在正确的时间看到正确的信息

六大支柱,看着是六个方向,其实有四根半都在回答同一个问题:怎么让模型在正确的时间,看到正确的信息。 这就是我在课程开头说 Context Engineering 是真正护城河的原因——它压根不局限于某一章,它串通了整个系统。

第二条:每个组件都是一个假设,而假设会过期。

Anthropic 的 Harness 从 V1 走到 V3,删掉了 Sprint、删掉了上下文重置、删掉了 Contract 协商——模型变强了,"模型没法做长程规划"这个假设失效了,编码这个假设的组件就该删。

这条暗线给你的提醒很直接:你在这门课里学到的每一个机制,都有保质期。压缩的触发阈值会变,工具加载的策略会变,甚至某一天压缩这件事本身的形态都会变。

但方法不会变:Agent 犯错,分析根因,加一个最小组件防止再犯;模型升级,逐个重测,删掉不再需要的。学会这套"提出假设、编码假设、验证假设、淘汰假设"的循环,比记住任何一个组件都重要。

Agent 工程假设的生命周期:犯错→分析根因→加最小组件→模型升级→逐个重测→删掉失效假设,一个闭环

第三条:概率的归模型,确定的归工程。

回头看那些"绝对不能出错"的地方,我们用的全是确定性手段:权限靠白名单和规则匹配,循环检测靠哈希对比,多 Agent 并发写文件靠文件锁,崩溃恢复靠 append-only 的 JSONL 日志。

模型负责把事做对,工程负责错了也别出大事。这两层职责一旦混了——比如让模型自己决定要不要放行一条危险命令——系统的安全下限就从"确定"滑向了"概率性事件",在有些严肃的工程场景下这是不能接受的。

现在,拿到一个真实需求,你该怎么想

认知归认知,最后还是要落地。假设明天你的上级找你:"我们要做个 Agent。"你的第一步是什么?

依然轮不到选框架,也轮不到选模型。先用六个问题给需求定位,每个问题都直接对应一根支柱上的投入:

任务通常要跑多少轮?5 轮以内,裸消息数组就够用;超过 50 轮,完整的上下文管理系统一个模块都省不掉。

需要跨会话记忆吗?很多场景压根不需要,直接省掉一整层复杂度;需要的话先文件派,量大了再上向量。

需要拆多个 Agent 吗?默认一个。上下文真装不下了再用父子模式;子任务之间要动态协商,才考虑 Swarm。

要调什么工具?读写文件加跑命令,十几个原子工具足够;接第三方服务考虑 MCP;要被外部系统接入,考虑 ACP。

还有,Agent 跑在哪?本地 CLI 最省心;服务端长任务用长驻进程加 SSE,不要用 Serverless。

最后,是框架还是自研?看你要在哪一层掌控。需要精细控制上下文的话,目前的框架基本帮不上忙,自研要踏实很多。

六个问题答完,架构图基本上自己就长出来了。下次再有人问你"做 Agent 该用什么框架",你大概率会先把这六个问题反问回去。这也是这门课最想交付的东西:一套评估和设计的思维框架。 产品的使用说明会过时,这套框架不会。

通关

我们来盘点一下你这一路打过的"怪"。

最开始,你能跑起来一个 10 行的循环,建立了基础的认知。后来你知道了流式怎么处理、API 挂了怎么办、循环怎么不失控,也就是说你能造简单的轮子了。再后来,压缩、缓存、记忆、检索、权限,你下到了深水区。最后,Multi-Agent、Harness、可观测性、部署、协议——你已经在用架构师的视角看整个系统了。

现在再有新产品发布,自媒体刷屏的标题再唬人,你的第一反应也不会是焦虑了。你会安静地把它拆开:Loop 怎么退出的?工具怎么加载的?上下文怎么管的?记忆放在哪?多 Agent 怎么隔离?Harness 壳里包含了哪些假设?

六把尺子一量,五分钟,这个产品在你面前就是完全透明的,你能非常轻易地看透任何 Agent。

这就是通关的感觉——世界没有变小,但你手里有地图了。

说两句心里话。写这门课的这段时间,我自己其实也被迫把这些知识从头到尾重新想了一遍。很多东西用的时候觉得理所当然,落到纸面上才发现根本三两句讲不清,又回去翻源码、翻各种资料,然后进行输出。某种程度上,这门课也是我自己的一次通关。

同样,在课程配套的 AI 私教面前,你也是一样的,我设计这个私教产品的初衷,就是引导你思考,引导你用自己的话讲清楚,这个输出的过程,会让这些知识深深刻在你的脑子里面,即使时隔多年都不会遗忘。希望你也能理解我背后的良苦用心,祝你学有所成。

最后,谢谢你陪我走完这门课。

接下来

课程收尾了,但这个领域才刚刚开场。

第二条暗线其实已经把方向指出来了:模型在变成通用品,竞争在往壳上移。Harness 这一层——长任务怎么编排、质量怎么验收、Agent 怎么自我进化———是我判断里接下来几年最值得深挖的主战场。这门课只用了一章给它开了个头。

所以我接下来的计划,是围绕 Agent Harness 做一批更偏向"怎么用好 Agent"的内容,这和"怎么开发一个 Agent"几乎是两个完全独立的领域,讲的是如何用好 AI,如何编排好自己本地的开发工作流,成为 AI 超级个体。如果你学完这门课觉得意犹未尽,那我们顺着这条路往前接着走。

下一个课程见。

在那之前,给你留一个真正的结课作业:挑一个你每天都在用的 Agent 产品,用六大支柱把它拆一遍,写下来,或者自己完整脱稿讲一遍。

写完/讲完你就知道,你真的毕业了。

参考资料

上一页社区各大框架全景:用六大支柱透视任何 Agent 框架