18.3 回顾与路线
18.1 让整台机器跑了起来,18.2 交代了怎么给它接上真实燃料。到了最后一节,该停下来回一次头:这一路我们到底造了什么、学会了什么、还有哪些没做。回看不只是为了告别,更是为了看清下一段路该怎么走——卷一只教了「Agent 是怎么跑起来的」,卷二和卷三要教的是「怎么让它真的上生产」「怎么和成熟框架对接」。
本节把 minagent 收进书架的最后一格:逐条盘清 18 章把 minagent 推进到了哪里,讲明「从零手写」的得与失,预告卷二、卷三的路线,并留下一份自测清单——如果你能答上其中的大多数,卷一的目标就达成了。
18.3.1 18 章推进表:minagent 长成了什么样
把全卷的推进压缩成一张表,你能一眼看到 minagent 是如何从一个空壳长出肌肉的:
| 章 | minagent 推进到 | 你现在会做的事 |
|---|---|---|
| 1 | 仓库骨架、Message / Role / ToolCall、第一轮假模型 | 建好工程、定义消息、跑通假模型 |
| 2 | Model 协议 + FakeModel + 可选供应商适配器 + token 预算 | 把「调模型」抽象成可替换接口 |
| 3 | 朴素循环 → 五条停止条件 → Agent 类 | 让循环自己跑、自己停、有身份 |
| 4 | Tool / ToolRegistry:schema、分发、校验、并行 | 把任意函数接成模型可调的工具 |
| 5 | ReAct / Plan-and-Solve / Reflexion 三种循环变体 | 按任务挑推理模式 |
| 6 | 指令分层、上下文裁剪与摘要、结构化输出 | 控制喂进去的上下文 |
| 7 | 流式事件、Session 状态、检查点续跑 | 把运行过程流出来、存盘续跑 |
| 8 | 缓冲 / 摘要记忆、检索注入、写入策略 | 让 Agent 记住该记的 |
| 9 | 本地嵌入 + numpy 索引、混合检索、记忆即工具 | 手写一个可离线的语义检索 |
| 10 | 文档切分、search / read 工具、带引用回答 | 让 Agent 查资料并标注来源 |
| 11 | 任务分解 DAG、计划执行器、重规划 | 把大任务拆成子任务再执行 |
| 12 | 最小图引擎:节点 / 边 / 条件跳转 / 人机在环 | 把流程编排成图 |
| 13 | supervisor / worker、进程内消息总线、协作拓扑 | 让多个 Agent 协作 |
| 14 | 错误分类重试、超时取消、幂等工具 | 让 Agent 出错能收拾 |
| 15 | span 树、结构化日志、成本核算 | 让运行可见、可算钱 |
| 16 | 确定性测试、评测集、对比实验 | 把改动量化成分数 |
| 17 | 稳定接口 + FastAPI/SSE + TS 客户端 | 把引擎服务化、跨语言复用 |
| 18 | 端到端带引用回答 + 可选真实冒烟 + 回顾 | 把这一切装成一台机器交付 |
这张表本身就是卷一的答案:minagent 不再是一个示例,而是一台你能看懂每一行、能改每一处的最小 Agent 引擎。
从这张表还能看出卷一的节奏:第 1–5 章打地基(消息、模型、循环、工具、推理模式),第 6–10 章补能力(上下文、状态、记忆、检索、引用),第 11–14 章上编排(规划、图、多 Agent、鲁棒性),第 15–17 章做工程(观测、评测、服务),第 18 章收束交付。每一块都建立在前面之上,没有一块是可以跳过的——这正是「从零手写」路线的价值:你走的是唯一一条不会迷路的路径。
18.3.2 minagent 的模块版图
推进表是「按时间」看的,模块版图则是「按结构」看的。卷一的 minagent 最终长成了这样一份文件清单——核心五文件从第 1–3 章就固定,后续章节只叠加、不改名:
| 文件 | 职责 | 首次出现 |
|---|---|---|
minagent/types.py | 消息协议:Role / ToolCall / Message / ModelResponse / Model / Step / RunResult | 第 1 章 |
minagent/model.py | FakeModel 假模型,以及可选的真实供应商适配器 | 第 1–2 章 |
minagent/tools.py | Tool 与 ToolRegistry:schema、分发、错误回灌 | 第 4 章 |
minagent/loop.py | run() 主循环与停止条件 | 第 3 章 |
minagent/agent.py | Agent 类:配置、状态与回调 | 第 3 章 |
minagent/memory.py | 缓冲 / 摘要记忆、检索注入、写入策略 | 第 8–9 章 |
minagent/rag.py | 文档加载切分、search / read 工具 | 第 10 章 |
minagent/planner.py | 任务分解 DAG、计划执行器、重规划 | 第 11 章 |
minagent/graph.py | 最小图引擎:节点 / 边 / 条件跳转 | 第 12 章 |
minagent/multiagent.py | supervisor / worker、进程内消息总线 | 第 13 章 |
minagent/observability.py | span 树、结构化日志、成本核算 | 第 15 章 |
minagent/eval.py | 确定性测试、评测集、对比实验 | 第 16 章 |
minagent/service.py | 稳定接口 + FastAPI / SSE 落点 | 第 17 章 |
一个值得留意的设计:全卷核心引擎只用标准库(dataclasses / typing / json / asyncio / sqlite3 / math / re / hashlib),只有 numpy(第 9 章向量索引)和「可选」章节的 pydantic / httpx / anthropic / fastapi 是第三方依赖。这不是洁癖,而是为了让每一块都能被你看懂——没有依赖替你藏起任何细节。
这份版图还有个隐含的顺序:越靠上的文件越稳定,越靠下的越可替换。types.py 从第 1 章定稿后就再没大改过;而 service.py 只是 17.1 稳定接口的一种落地方式,你完全可以换成别的 Web 框架甚至换成 CLI。稳定的内核 + 可替换的边缘,正是这套骨架敢让你直接迁移进生产项目的底气。
18.3.3 从零手写,得到了什么
有人会问:市面上框架那么多,为什么还要自己写一遍?因为从零手写换来的不是代码,是四样框架给不了的东西。它们的共同点是:都无法通过「读文档」获得,只能通过「亲手做一遍」长进肌肉里。
第一,一套不会被术语唬住的判断力。 你亲手写过循环,所以当某个框架说「我们有 ReAct 支持」时,你知道那不过是 5.1 节那个 while 循环换了个包装;它说「智能规划」,你能立刻问出「计划存在哪、失败了怎么重规划」。框架替你做的每一步,你都做过一遍——这是读文档读不来的。
第二,确定性复现的能力。 FakeModel 让 Agent 的行为第一次变成可断言的对象。你可以在 0.1 秒内跑完六条回归用例,可以断言「模型在第 3 轮看到了什么」,可以把一次线上 bug 固化成一条永久用例。这套方法不依赖任何框架,是通用的工程素养。
第三,一条清晰的排查链路。 从 15.1 的 span 树、15.2 的结构化日志到 15.3 的成本表,共用一套 run_id:从成本异常出发 → 跳日志看经历了什么 → 跳 span 树看卡在哪 → 回到成本表看该砍哪。这条链路让你在 Agent 出错时不是抓瞎,而是像调试普通程序一样有据可循。
第四,一份可迁移的代码骨架。 全卷核心只用标准库,意味着这套骨架可以直接拷进你的项目:types.py 的消息协议、tools.py 的注册表、loop.py 的停止条件,一行都不用改就能承载你自己的工具与业务。你不必为了「用 Agent」而先背下一整套框架的概念,先把这份骨架跑通,再按需替换——这是最省心的起步方式。
一句话概括:你学到的不是「怎么用某个框架」,而是「一个 Agent 引擎该由哪些部分组成」。有了这个心智模型,任何框架在你眼里都会变得透明。
18.3.4 卷一的十个关键设计决定
如果只让你记住十件事,就是下面这十条。它们不是知识点,而是日后写任何 Agent 都会反复用到的判断:
| # | 决定 | 一句话理由 | 章节 |
|---|---|---|---|
| 1 | 消息列表是唯一状态 | 没有隐藏变量,每一步都是对同一列表的追加 | 3.1 |
| 2 | 把 Model 抽成协议 | 假模型与真模型可互换,循环一行不改 | 2.1 |
| 3 | 工具错误回灌而非抛异常 | 一次坏调用只消耗一轮,不终止会话 | 4.1 |
| 4 | 控制流属于程序,不属于模型 | 模型无状态,循环是外面这层代码跑出来的 | 3.1 |
| 5 | 停止条件是显式的、带 reason 的数据 | 「为什么停」比「停没停」更重要 | 3.2 |
| 6 | 假模型驱动确定性测试 | 可复现是评测可写的前提 | 1.3 / 16.1 |
| 7 | 追踪是横切关注点 | 用 contextvar 挂 span,不污染业务逻辑 | 15.1 |
| 8 | 成本按 run / 会话 / 工具三维核算 | 三个维度驱动三类决策 | 15.3 |
| 9 | 引用让回答可核对 | 把「信不信」拆成机器可粗筛的两步 | 10.3 |
| 10 | 复杂编排只在真正需要时引入 | 能一个循环解决,就不要上多 Agent | 13.3 |
这十条是卷一的「脊椎」。它们会一路跟着你进入卷二、卷三,也会在你看任何框架源码时帮你快速定位「它在哪一层、替谁做了决定」。
如果你只带走一句话,就带走第 4 条:控制流属于程序,不属于模型。它解释了为什么 Agent 可以被测试、被追踪、被成本核算——因为真正在「跑」的是你写的循环,模型只是一个可以被替换、被 mock、被计价的零件。想通这一点,卷一后面所有的设计都会显得顺理成章。
18.3.5 还差什么
诚实地说,卷一只做到「会用 + 能用假模型复现」。真实的 Agent 系统还有不少卷一刻意没碰的东西:
| 缺口 | 卷一只做到 | 真实系统还需要 |
|---|---|---|
| 并发 | 会用 asyncio.TaskGroup、能复现 | 高并发下的调度、背压、限流 |
| 持久化 | 检查点存盘续跑(7.3) | 状态落库、崩溃恢复、多副本一致 |
| 服务化 | FastAPI/SSE 单机(17.2) | 鉴权、多租户、灰度、扩容 |
| 可观测 | 内存里的 span 树(15.1) | 接 OpenTelemetry、接真实追踪后端 |
| 评测 | 小评测集 + 假模型(16.2) | 持续回归、真实轨迹回放、指标看板 |
| 框架 | 一律不依赖(卷一刻意) | 与 PydanticAI / LangGraph 等对照 |
| 前沿 | 未涉及 | durable execution、computer use、A2A、Agent RL |
这张表不是「卷一的失败清单」,而是卷二、卷三的目录。卷一故意把边界划在这里,是因为这些缺口每一个都值得单独展开,塞进入门卷只会两头不讨好。
还有一点值得说清:这些缺口不是「卷一做错了」,而是「卷一刻意不做」。入门卷最怕的就是一上来铺满术语、让你在还不理解 Agent 是什么的时候就被「多租户」「背压」「OpenTelemetry」淹没。卷一选择先把最核心的那台引擎讲透,把工程细节留到你有手感之后——该来的都会来,只是顺序问题。
18.3.6 卷二预告:工程化
**卷二《AI Agent 工程化》**要回答的是「怎么让这台机器真的上生产」。它会把卷一的单机骨架往工程化方向加固:
| 主题 | 从卷一的哪里出发 | 卷二要走到哪 |
|---|---|---|
| 服务化 | 17.2 的单机 FastAPI/SSE | 鉴权、多租户、限流、灰度 |
| 持久化 | 7.3 的检查点存盘 | 状态落库、崩溃恢复、多副本 |
| 并发 | 14.2 的 TaskGroup | 高并发调度、背压、资源隔离 |
| 可观测 | 15.1 的 span 树、15.2 的日志 | 接 OpenTelemetry 与真实日志系统 |
| 评测回归 | 16.2 的小评测集 | 持续回归、真实轨迹回放、看板 |
| 部署 | 17.1 的稳定接口 | 容器化、配置管理、发布流程 |
一句话:卷一教你「Agent 怎么跑」,卷二教你「Agent 怎么稳」。 卷一的每一块零件,卷二都会把它们从「能跑」推进到「扛得住」。
举个具体场景:卷一里你的 Agent 一崩,检查点文件就停在原地,重启后手动续跑;到了卷二,你会让它崩溃后自动从最后一个成功步骤恢复,且两个副本同时运行也不会重复扣费。再比如卷一的成本表只写进内存,进程一退就没了;卷二会把它落库、按租户聚合、在超预算时主动熔断。这些都不是新概念,而是把卷一已经理解的东西补上工程细节——你依然看得懂每一处为什么这么写。
18.3.7 卷三预告:框架与前沿
**卷三《AI Agent 进阶》**处理的是「当你不满足于自己造轮子时」。它分两条线。
框架对照线:拿 PydanticAI、LangGraph、Claude Agent SDK 等主流框架重写卷一的 minagent,逐处对照「框架替你做了什么、代价是什么」。比如同样的 ReAct 循环,框架帮你省掉了哪几行、又在哪几处加了约束;同样的检查点,框架的持久化和你 7.3 的手写版差在哪。有了卷一的手写基础,这一遍你会看得格外透。
前沿主题线:覆盖 2026 年 Agent 领域最活跃的四个方向——
| 方向 | 解决的问题 | 与卷一的连接 |
|---|---|---|
| durable execution | 长流程断点续跑、可重放 | 7.3 检查点的生产级延伸 |
| computer use | 让 Agent 操作图形界面 | 工具调用从函数扩展到「看屏幕、点鼠标」 |
| A2A | Agent 与 Agent 的通信协议 | 13.2 进程内消息总线的跨进程延伸 |
| Agent RL | 用强化学习训练 Agent 策略 | 16.x 评测从「打分」升级成「训练信号」 |
框架不是洪水猛兽,前沿也不是空中楼阁——卷一只是一块地基,站上去你才够得着它们。
需要强调的是,卷三不会只给你「框架 API 速查」。每讲一个框架,它都会先带你回忆卷一对应手写版的样子,再逐行对照框架的取舍:它是为了省事牺牲了透明,还是为了规模增加了约束。这份对照能力,比会用一个框架值钱得多——因为框架会更替,判断力不会。
18.3.8 学完卷一,你应该能回答这些问题
下面这份清单是卷一的「结业自测」。它刻意不考记忆,而是考判断——每道题都对应一个你写代码时会反复遇到的岔路口。如果你能不翻书答上其中的大多数,就说明这一路没白走:
| # | 问题 | 对应章节 |
|---|---|---|
| 1 | Agent 循环的心跳是哪三步?控制流属于模型还是程序? | 3.1 |
| 2 | 为什么开发 Agent 要先造一个假模型?它和真实适配器什么关系? | 1.3 / 2.1 |
| 3 | 一个健壮的循环需要哪几条停止条件?各自拦的是什么? | 3.2 |
| 4 | 工具出错时为什么不抛异常,而要回灌 {"error": ...}? | 4.1 |
| 5 | ReAct、Plan-and-Solve、Reflexion 三种模式各适合什么任务? | 5.1–5.3 |
| 6 | 对话一长就「忘事」,有哪几种裁剪与压缩手段? | 6.2 / 8.1 |
| 7 | 一次运行为什么是「一棵树」而不是「一串步骤」? | 15.1 |
| 8 | 成本该按哪三个维度切?分别驱动什么决策? | 15.3 |
| 9 | 一个 Agent 的「输出」到底该断言什么?为什么不能只断言终值? | 16.1 |
| 10 | 评测集为什么要故意包含失败用例? | 16.2 |
| 11 | 把 FakeModel 换成真实供应商,循环要改几行?为什么? | 2.2 / 18.2 |
| 12 | 带引用的回答解决了什么信任问题?校验分哪两层? | 10.3 |
| 13 | 什么时候才值得上多 Agent?为什么卷一反反复复劝你克制? | 13.3 |
| 14 | 「两层测试」指什么?各自负责回答什么问题? | 16.1 / 18.2 |
如果某几条答不上来,别急着往下走——回到对应章节重跑一遍那节的代码,比再读一遍文字有用得多。Agent 工程的知识,落在代码上才记得住。
18.3.9 把 minagent 用起来:一份迁移清单
学完不等于会用。如果你想把 minagent 装进自己的项目,可以照这份清单一步步来——每一步都对应卷一的某一节,随时能回去翻:
| 步骤 | 做什么 | 参考章节 |
|---|---|---|
| 1 | 拷入 types.py / tools.py / loop.py,跑通第一个假模型循环 | 1.3 / 3.1 |
| 2 | 把你的业务函数包成 Tool,写清 description 与 parameters | 4.1 |
| 3 | 为每个工具补一条确定性测试,先断言「模型看到了什么」 | 16.1 |
| 4 | 接上真实供应商适配器,密钥只从环境变量读 | 2.2 / 18.2 |
| 5 | 挂上 Tracer 与 CostTracker,让每次运行可追溯、可算钱 | 15.1 / 15.3 |
| 6 | 若需要查资料,加 search / read 工具并要求带引用 | 10.2 / 10.3 |
| 7 | 把回归用例攒成评测集,每次改动前先跑一遍 | 16.2 |
| 8 | 需要对外提供时,用 17.1 的稳定接口包一层服务 | 17.1 / 17.2 |
清单背后的原则只有一条:先让它在假模型下确定地跑通,再逐块接上真实世界。反过来做——一上来就接真模型、边跑边改——是卷一一再提醒要避免的路径,因为那时你分不清是模型的问题还是代码的问题。
迁移时最容易踩的两个坑也一并提醒:其一,别急着改内核,types.py / loop.py 是稳定的,绝大多数需求靠「加工具、加记忆、加评测」就能满足,改内核往往意味着你误解了某个设计;其二,别跳过测试,第 3 步的确定性测试是后面一切的地基,跳过它,接真模型后你会付出十倍代价去定位问题。慢一点,反而快。
18.3.10 继续前行的三条建议
在翻开卷二之前,给三条可操作的建议——它们都不难,但决定了你从「读完」到「学会」的距离。
建议一:留一份自己的 minagent。 把卷一的代码从 content/posts/books/ 里拷出来,放进一个独立仓库,边读边改。书里的代码是「读过」,你自己的仓库才是「拥有」。日后遇到任何框架,你都有一份可对照的基线。
建议二:挑一个真实的小场景跑通。 不要停在书里的示例上。选一件你日常真要做的事——比如「读一份 PDF 回答问题」「查日志定位报错」——用 minagent 实现它。真实场景会逼你面对示例里没有的边界,而这正是成长的时刻。
建议三:把评测集当成习惯。 每加一个新工具、改一处提示词,先跑一遍 16.2 的评测集。这不是负担,而是让你敢改的底气——没有回归网,你改每一行都会心虚;有了它,你才敢大胆试。
这三条建议的共性,还是那句话:让知识落到代码上。卷一已经替你铺好了全部原料,剩下的路,靠你一行一行走出来。
好,回顾到此为止。下面是卷一的最后一次「真实模型」对照,也是整卷的收束。
18.3.11 三个常见疑问
收尾前,把学完卷一后最常冒出来的三个疑问一次答清。
「我照着写了一遍,但还是不会用框架,是不是白学了?」 恰恰相反。你写的是「原理版」,框架是「封装版」。看不懂框架,往往是因为不知道它封装的原始形态长什么样——而你恰好知道。接下来卷三会带你把这个优势用起来。
「假模型到底有什么用?我直接接真的不行吗?」 假模型的价值在第 16 章已经演示过:它让 Agent 的行为变成可断言的对象。真实模型的输出每次都不一样,你没法写「第 3 轮必须看到 search 工具」这样的断言。先有可复现,才谈得上优化。
「18 章、54 节,学完要多久?」 取决于你跑不跑代码。只读不跑,一周能翻完;认真跑完每一节的代码、做完全部练习,两到三周更现实。但这个投入是值得的:你得到的不只是「会写 Agent」,而是一套能迁移到任何框架、任何项目的心智模型。
18.3.12 真实模型下会怎样
最后再谈一次真实模型,作为整卷的收尾。卷一全程用假模型,不是为了逃避真实,而是为了先把可控的部分做扎实,再去面对不可控的部分。真实模型带来的不确定性——措辞漂移、步数浮动、偶发失败——正是卷二、卷三要系统处理的:卷二用工程手段(重试、超时、持久化、观测)把不确定性圈进可控范围,卷三用框架与前沿方法把它转化为能力。
所以这本书的路线是刻意的:先用假模型把「确定的东西」钉死,再带着这份确定性去驯服「不确定的东西」。当你有朝一日把 minagent 换成真实供应商、在线上跑起来时,卷一的每一块拼图都会回到你手里——循环、工具、检索、追踪、成本、评测,一块都不会白写。
卷一到这里就结束了。18 章、54 节、一台从零手写的引擎,都在你手里了。接下来怎么走,你已经有了判断的底气。
如果你此刻还有点意犹未尽,那就去把 18.1 的 demo_e2e.py 再跑一遍——看着那棵 span 树、那张成本表、那份评测报告,你会意识到:这些不再是书上的示例,而是你能读懂、能修改、能据为己有的东西。这份「我能看懂」的踏实感,就是卷一最想给你的礼物。
阅读导航:上一节:18.2 真实 API 冒烟(可选) · 下一节:回到目录 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。