李博杰的 Agent 开源书,94 个实验全藏在 monorepo 里
- 采用 monorepo 结构,书与 94 个实验代码同仓,一键环境安装
- 构建 provider 抽象层,一个实验可切换七种模型,仅改--provider 参数
- 固定 SHA 复现管线,22 个外部依赖克隆后锁定不可变 commit 并校验
- CI 按依赖触发,空字符串 API key 测试防止静默通过,fail-fast 关闭
- 将教学项目作为软件工程维护,版本锁文件 CI 翻译一致性检查
2025 年 9 月,李博杰在 GitHub 上开了个仓库,放他写的《深入理解 AI Agent:设计原理与工程实践》。不到一年,28319 star,2991 fork,13 种语言翻译,连续多天霸占 GitHub Trending 日榜。一本书能火到这个程度,不是内容写得好就够的,它背后的工程结构才是真正有意思的部分。
它到底在解决什么问题
Agent 这个领域不缺教程。缺的是一套从原理到代码、能跑、能复现、还能跟着版本演进的学习路径。你看完一篇博客讲 ReAct,想动手试试,发现要自己配 API key、找模型、写 prompt、搭测试环境,光准备工作就耗掉你所有的热情。
ai-agent-book 的做法是把整本书和 94 个配套实验放进同一个 monorepo。book/ 目录里是 10 章正文的 Markdown 源码,chapter1/ 到 chapter10/ 是每章的配套代码实验。你读完第一章想跑实验,不需要跳到别的仓库,直接 uv sync --locked --extra ch1 就能把第一章的环境装好。
核心公式很简单,Agent = LLM + 上下文 + 工具。全书围绕这个公式展开,大脑负责决策,眼睛负责感知,手脚负责执行。听起来朴素,但真正让这个仓库脱颖而出的不是书的内容,而是它把这些概念工程化的方式。
provider 抽象层,一个实验跑七种模型
94 个实验里大部分需要调用 LLM。如果每个实验自己管 API key 和 endpoint,94 个实验就是 94 份配置代码,改一次模型列表要改 94 个文件。ai-agent-book 的做法是在 agentbook/providers/ 里建了一个共享的 provider 抽象层。
registry.py 是纯数据模块,定义了七个 provider 的注册表。每个 provider 是一个 Provider 对象,包含 base_url、default_model、key_vars、base_url_var 四个字段。SiliconFlow 的 endpoint 是 https://api.siliconflow.cn/v1,默认模型 Qwen/Qwen3.5-397B-A17B;Kimi 的 endpoint 是 https://api.moonshot.cn/v1,默认模型 kimi-k3,key 环境变量同时支持 MOONSHOT_API_KEY 和 KIMI_API_KEY(后者是向后兼容)。加一个 provider 只需要在这个字典里加一条记录,chapter CLI 的 --provider 参数会自动从 SUPPORTED_PROVIDERS 生成,不需要改 argparse 代码。
resolution.py 是策略层,决定用哪个 provider。它的核心函数 resolve_backend 实现了一条优先级链,注释写得很直白,「the order of its steps is the entire behaviour: swapping two of them silently changes which endpoint a chapter talks to」。这条链包括本地 Ollama 直连、直接 API、OpenRouter 降级。特别有意思的是 _needs_openrouter_for_gpt5() 这个函数,它检测到 GPT-5 请求时,如果用户没有 OpenAI 组织验证,会自动降级走 OpenRouter,因为 OpenAI 直连 GPT-5.x 需要组织验证,大多数读者没有。
这个设计让一个实验能跑七种模型,换模型只需要改一个 --provider 参数。说真的,这是我在开源项目里见过的最干净的 provider 抽象之一。
固定 SHA 的复现管线
94 个实验里有一部分依赖外部仓库。第 7 章的训练框架需要 minimind、verl、SandboxFusion,第 9 章的机器人实验需要 XLeRobot、RoboCrew,第 10 章的多 Agent 实验需要 generative_agents。这些仓库加起来 22 个,分散在 GitHub 和 HuggingFace 上。
ai-agent-book 没有把它们做成 submodule,而是提供了一键克隆脚本,每个 clone 命令后跟一个 git checkout --detach <SHA> 固定到不可变 commit。更狠的是,九个关键仓库的 clone 命令还带 rev-parse HEAD 相等性校验,checkout 完会验证当前 HEAD 和目标 SHA 完全一致,不一致就失败。
README 里有一句话特别清醒,「源码存在或安装成功都不是实验完成声明」。它把实验分成三类,✅ 可运行、📖 复现、🚧 设计,明确标注哪些实验需要硬件、哪些需要授权 API、哪些还在本地预检阶段。比如实验 6-9 的「组件 × 模型 × 评估器的 4×3×2×60 全矩阵」标注为 🚧 未完成,实验 5-12 的「能创造 Agent 的 Agent」有正式对照但「预期的质量与效率双重严格优势未观察到」。
这种诚实程度在开源项目里很少见。大部分项目 README 只写「能做什么」,很少写「我们试了但没做到」。
CI 怎么防回归
94 个实验的回归测试是个大问题。ai-agent-book 的 CI 策略是按依赖关系触发,而不是全量跑。
provider-adoption-tests.yml 专门测试 agentbook/ 包的改动。它的触发条件是 agentbook/**、chapter2/ 的三个实验、chapter3/ 的一个实验、pyproject.toml 这几个路径。注释解释了为什么只测这四个实验,「a change to agentbook/ able to break six experiments at once, in code paths none of their own tests would flag as related」。agentbook/ 是共享包,改一行可能同时打断六个实验,但那些实验自己的测试不会发现,因为它们不知道自己依赖了共享代码。
matrix 策略用 fail-fast: false,一个实验失败不阻断其他实验的测试。测试运行时把 MOONSHOT_API_KEY、KIMI_API_KEY、OPENROUTER_API_KEY 全部设为空字符串而不是 unset,注释写得很明确,「a resolver bug that reads a key from the runner environment must fail here, not silently pass」。空字符串和 unset 的区别在于,如果 resolver 有 bug 会从 runner 环境读到一个真实 key,unset 会让它静默通过,空字符串会让它报错。
还有两个实验被故意排除在 matrix 之外,chapter2/kv-cache 和 chapter2/agent-skills-ppt,因为它们在没有 API key 时会 exit(1),或者依赖 python-pptx 无法在共享安装下 import。注释说这需要 Phase 6A 的 test/manual split 先解决,而不是在这里 workaround。
i18n-check.yml 负责多语言一致性。13 种语言的翻译容易出现主仓库改了某章 README,翻译版没跟上的漂移问题。这个 workflow 跑 scripts/check_i18n_consistency.py 和 scripts/site_i18n.py,检查静态站导航和 UI 翻译的一致性。
这本书的工程哲学
拆完这个仓库,我最大的感受是它把「教学」和「工程」做到了一种很少见的统一。
传统技术书是单向输出,作者写、读者读,代码是附赠品。ai-agent-book 的做法是把书本身当成一个软件项目来维护。书有版本(Release 按时间发),代码有锁文件(uv.lock 保证可复现),实验有 CI 测试,翻译有一致性检查,外部依赖有 SHA 固定。你不只是在读一本书,你在 clone 一个持续迭代的工程项目。
resolution.py 里的 provider 抽象展示了一个可迁移的模式。当你有 N 个实验都要调用同一个外部服务,不要让每个实验自己管连接逻辑,建一个共享的抽象层,数据(注册表)和策略(解析链)分开,加一个 provider 只改数据不改代码。这个思路不只适用于 LLM 调用,任何需要多后端适配的场景都能套,数据库连接、消息队列、支付网关,道理一样。
固定 SHA 的复现管线则展示了另一个模式,可复现性是工程承诺,不是文档措辞。很多项目在 README 里写「我们支持复现」,但 clone 下来的代码跟着 main 分支漂移,三个月前的实验今天跑不通。固定 SHA 加相等性校验,是把「可复现」从一句口号变成一个可验证的 CI 步骤。
如果你在学 Agent,这本书值得从头到尾读一遍,重点是跑它的配套实验,不要只看正文。如果你在做开源教学项目,这个仓库的工程结构值得参考,尤其是 provider 抽象和固定 SHA 复现这两块。但要注意 94 个实验里有不少需要 GPU 或真实硬件(第 7 章的训练实验、第 9 章的机器人实验),CPU 友好的 all 组合不代表每个实验都能跑。
评论互动