写在前面
写给谁:天天用 Claude、Codex、Cursor,但说不清它们背后发生了什么的开发者。需要有一门编程语言的基础,不需要机器学习基础,也不需要懂数学。
读完能干什么:
- 能用原理解释模型的各种"怪行为",而不是靠玄学调 prompt;
- 能用 Go 从零手写一个能读代码、改代码、跑命令的 coding agent;
- 能看透 Claude Code 和 Codex 的设计取舍,并把它们用到极致;
- 知道什么时候该用 Agent,什么时候该果断放弃。
实战语言:Go。不熟悉 Go 也没关系,循环和 HTTP 调用的逻辑放到任何语言里都一样。
配套代码:一个仓库 agent-from-zero,每篇实战文章对应一个 tag,读者可以随时 checkout 到对应进度。
路线图
flowchart TD
A["第一部分 认知篇
01-05 先把名字理清楚"] --> B["第二部分 原理篇
06-13 LLM 到底在干嘛"] B --> C["第三部分 上下文工程篇
14-18 模型只认识上下文"] C --> D["第四部分 协议篇
19-23 Function Calling 与 MCP"] D --> E["第五部分 手写 Agent 篇
24-31 用 Go 从零造一个"] E --> F["第六部分 用好成品篇
32-34 拆解 Claude Code / Codex"] F --> G["第七部分 工程化篇
35-38 验证、评测、成本、安全"] G --> H["第八部分 放弃篇
39-40 天花板与结业"] style E fill:#ffe0b2,stroke:#e65100 style H fill:#ffcdd2,stroke:#b71c1c
01-05 先把名字理清楚"] --> B["第二部分 原理篇
06-13 LLM 到底在干嘛"] B --> C["第三部分 上下文工程篇
14-18 模型只认识上下文"] C --> D["第四部分 协议篇
19-23 Function Calling 与 MCP"] D --> E["第五部分 手写 Agent 篇
24-31 用 Go 从零造一个"] E --> F["第六部分 用好成品篇
32-34 拆解 Claude Code / Codex"] F --> G["第七部分 工程化篇
35-38 验证、评测、成本、安全"] G --> H["第八部分 放弃篇
39-40 天花板与结业"] style E fill:#ffe0b2,stroke:#e65100 style H fill:#ffcdd2,stroke:#b71c1c
整个系列都围绕下面这张核心图展开,后面会反复回到它:
flowchart LR
U["用户任务"] --> M["LLM
只负责想"] M -->|"输出:我想调用工具 X"| H["Harness
负责做"] H -->|"执行工具"| T["文件 / 终端 / API / MCP"] T -->|"结果塞回上下文"| M M -->|"输出:完成了"| R["最终回答"]
只负责想"] M -->|"输出:我想调用工具 X"| H["Harness
负责做"] H -->|"执行工具"| T["文件 / 终端 / API / MCP"] T -->|"结果塞回上下文"| M M -->|"输出:完成了"| R["最终回答"]
每篇文章的固定结构
- 开场一个现象:从一个你一定遇到过的怪事切入;
- 原理拆解:讲清楚为什么会这样,配一张 Mermaid 图;
- 动手环节:每篇至少一个能跑起来的实验;
- 踩坑记录:作者翻过的车,读者就不用再翻了;
- 一句话总结;
- 放弃指数:★ 到 ★★★★★,提前告诉读者这篇有多劝退。
第一部分 认知篇:先把名字理清楚(01-05)
01. 大模型、Chatbot、Agent:一次把名字理清楚
要点:
- 模型是一个无状态的函数:文本进,下一个 token 的概率出。
- 应用等于模型加界面加工具。
- Agent 等于模型加循环加工具加上下文管理。
- "Claude"一词三义:Opus/Sonnet 是模型,Claude.ai 是应用,Claude Code 是 Agent。Codex 同理:Codex 是 Agent 产品,背后跑的是 GPT 系列模型。
- 动手:把你用过的所有 AI 产品列一张表,标出它属于模型、应用还是 Agent。
- 放弃指数:★☆☆☆☆
02. Agent 的最小定义:一个 while 循环
要点:
- 一段 20 行的伪代码讲清 Agent 的本质。
- Harness 的概念:模型只会"说"自己想调用什么,真正执行的是外层程序。
- 状态存在哪里?答案是全在消息历史里。
- 动手:手画一遍 Agent 循环的时序图,标出每一步状态的变化。
- 放弃指数:★☆☆☆☆
03. Agent 简史:从 ReAct 到 Claude Code
要点:
- 2022 年 ReAct 提出推理与行动交替进行,2023 年的 Toolformer 让模型学会用工具。
- 同年 AutoGPT 引发全民狂热,然后迅速幻灭。当年为什么不行?模型能力不够、上下文太短、工具协议也不统一。
- 同样在 2023 年,function calling 进入官方 API。
- 2024 年底 MCP 发布;2025 年编码 Agent 全面爆发。
- 动手:读 ReAct 论文里的示例 trace,数一数 Thought、Action、Observation 各出现了几轮。
- 放弃指数:★☆☆☆☆
04. Workflow 还是 Agent?大部分场景你不需要 Agent
要点:
- Workflow 是预定义路径,Agent 是由模型自主决策路径。
- 五种常见模式:链式、路由、并行、编排者-执行者、评估-优化。
- 一条原则:能用 workflow 解决的,就别上 Agent。
- 动手:拿自己的三个日常需求,分别判断适合用 workflow 还是 Agent。
- 参考:Anthropic《Building Effective Agents》
- 放弃指数:★★☆☆☆
05. Agent 能力地图:为什么编码 Agent 最先成熟
要点:
- 四大方向:编码、浏览器操作、电脑操作、深度研究。
- 编码 Agent 跑在最前面,原因有三:结果可验证(编译器和测试会告诉它对不对)、环境是纯文本、训练数据极其丰富。
- 动手:给自己的日常任务按"可验证度 × 重复度"打分,找出最值得交给 Agent 的那一个。
- 放弃指数:★☆☆☆☆
第二部分 原理篇:LLM 到底在干嘛(06-13)
06. Token:模型眼里的世界
要点:
- BPE 分词的原理;中文和英文的 token 消耗差异。
- 为什么模型数不清 strawberry 里有几个 r,也不擅长把字符串倒过来写。
- token 数同时决定了计费和上下文上限。
- 动手:在 Tiktokenizer 网站上对比同一段内容的中英文切分;用官方的 token counting API 算一算你常用的 prompt 有多少 token。
- 参考:Karpathy《Let's build the GPT Tokenizer》
- 放弃指数:★★☆☆☆
07. Next-token prediction:一个字一个字地猜
要点:
- 自回归生成,以及 logits 经过 softmax 变成概率的过程。
- 模型没有草稿纸,它输出的就是它的思考过程。所以"先推理后结论"和"先结论后解释"的效果完全不同。
- 动手:同一道多步算术题,分别要求模型"先给答案再解释"和"先推理再给答案",对比准确率。
- 放弃指数:★★☆☆☆
08. 采样:temperature、top-p 与"同题不同答"
要点:
- 贪心解码与随机采样的区别;temperature、top-p、top-k 各自控制什么。
- 为什么 temperature=0 也不保证每次输出完全一样:批处理和浮点运算会带来细微差异。
- 部分推理模型限制了采样参数。
- 动手:同一个问题在不同 temperature 下各跑 10 次,画出答案分布。
- 放弃指数:★★☆☆☆
09. Transformer 与 Attention:不推公式的直觉版
要点:
- embedding 把 token 变成向量。
- attention 让每个 token 都能"看"到其他 token。
- 多层堆叠逐步提炼语义;MLP 层被认为是存储知识的地方。
- 参考:3Blue1Brown 深度学习系列第 5 到 7 集
- 放弃指数:★★★☆☆(第一个劝退点,看不懂可以跳过,不影响后文)
10. Context Window:模型的内存条
要点:
- 上下文越长,成本越高。
- KV cache 的作用,以及 prompt caching 为什么能便宜很多:前缀保持稳定就能复用缓存。
- Lost in the middle:长上下文中间部分的信息最容易被忽略。
- 动手:做一个"大海捞针"小实验,把同一个事实分别放在长文档的开头、中间、结尾,测试召回率。
- 放弃指数:★★☆☆☆
11. 训练三阶段:能力是怎么被"装"进去的
要点:
- 预训练产出 base 模型,本质是一个互联网文档续写器,知识以有损压缩的形式存进参数。
- 指令微调(SFT)让它学会扮演助手。
- RLHF 和 RLAIF 让它对齐人类偏好。
- 动手:在 Hugging Face 上找同一模型的 base 版和 instruct 版,给相同输入,观察 base 版如何"续写"而不是"回答"。
- 参考:Karpathy《Deep Dive into LLMs like ChatGPT》
- 放弃指数:★★☆☆☆
12. 推理模型:让模型先想再答
要点:
- Test-time compute:在推理时多花算力换质量。
- 用可验证奖励做强化学习,在数学和代码这类有标准答案的领域效果最明显。
- thinking token 也要算钱:复杂任务值得开,简单任务开了反而又慢又贵。
- 动手:同一道题分别在开和不开 thinking 的情况下跑,记录耗时、质量和价格。
- 放弃指数:★★☆☆☆
13. 用原理解释怪行为:原理篇结业考
要点:六个现象逐个归因。
- 幻觉:有损压缩,加上模型被训练成"总要给出像样的回答"。
- 讨好:人类反馈本身偏爱被认同。
- 不知道新事:有知识截止日期。
- 同题不同答:采样的随机性。
- 数不清字母:token 粒度比字母粗。
- 越聊越笨:上下文被无关内容稀释。
- 动手:不看前文,用自己的话把这六个现象各解释一遍。
- 放弃指数:★☆☆☆☆
第三部分 上下文工程篇:模型只认识上下文(14-18)
14. 从 Prompt 工程到 Context 工程
要点:
- 上下文是模型唯一的世界,上下文之外的它一概不知道。
- 注意力是有限的预算,塞进去的东西越多,每样分到的越少。
- 上下文的五个组成部分:system prompt、工具定义、对话历史、检索内容、工具输出。
- 参考:Anthropic《Effective context engineering for AI agents》
- 放弃指数:★☆☆☆☆
15. System Prompt 写作:角色、约束与示例
要点:
- 一个示例胜过十个形容词。
- 用 XML 标签给内容分区。
- 解释"为什么"比全大写的 MUST 更有效。
- 输出格式要写清楚。
- 动手:为一个代码审查 Agent 写 system prompt,迭代三个版本并对比效果。
- 放弃指数:★★☆☆☆
16. Context Rot:为什么长对话越聊越笨
要点:
- 上下文越长性能越差,这在实验中有据可查。
- 应对手段:clear、compact、开新会话。
- 交接文档模式:会话结束前让 Agent 写一份
progress.md,下一个会话从它接手。
- 动手:在 Claude Code 里用
/context观察上下文的构成,以及它随会话变长的变化。 - 参考:Chroma《Context Rot》研究报告
- 放弃指数:★★☆☆☆
17. 项目记忆:CLAUDE.md 与 AGENTS.md
要点:
- 该写:构建和测试命令、项目约定、踩过的坑。
- 不该写:lint 能强制执行的规则、代码里一眼就能看出来的东西。
- 这类文件的层级与加载机制。
- 两种记忆系统设计的对比:文件式与向量式。
- 动手:为一个开源项目写一份 CLAUDE.md,用同一个任务对比有和没有这份文件时的效果。
- 放弃指数:★☆☆☆☆
18. 检索:RAG 还是 Agentic Search
要点:
- RAG 三件套:embedding、向量库、切块。
- Agentic search:让 Agent 自己用 grep 和 glob 按需查找。
- 为什么主流编码 Agent 更偏向后者;什么场景下仍然该用 RAG。
- 动手:对同一个代码库问同一个问题,分别用向量检索和 grep 两种方式,对比结果。
- 放弃指数:★★★☆☆
第四部分 协议篇:Function Calling 与 MCP(19-23)
19. Function Calling 协议拆解
要点:
- 用 JSON Schema 定义工具。
tool_use与tool_result两种消息块的结构。stop_reason字段的含义;并行工具调用。- 核心认知:模型只输出调用意图,从不真正执行。
- 动手:只用 curl 手动完成一次完整的工具调用往返。
- 放弃指数:★★☆☆☆
20. 工具设计:写给模型用的 API
要点:
- 命名、描述、参数设计的原则。
- 返回值要精简、可读,最好带上下一步的提示。
- 错误信息本身就是提示词,写得好能让模型自己纠错。
- 工具太多、功能重叠,都会让模型选错。
- 参考:Anthropic《Writing effective tools for agents》
- 放弃指数:★★☆☆☆
21. MCP 入门:工具界的 USB-C
要点:
- MCP 解决的是 N×M 问题:N 个 Agent 对接 M 个工具,不用再写 N×M 套适配。
- 三个角色:host、client、server。
- 三种能力:tools、resources、prompts。
- 底层是 JSON-RPC,传输方式有 stdio 和 Streamable HTTP 两种。
- 动手:给 Claude Code 接入一个现成的 MCP server,观察它的工具定义是怎么出现在上下文里的。
- 放弃指数:★★☆☆☆
22. 用 Go 手写一个 MCP Server
要点:
- 使用官方的
modelcontextprotocol/go-sdk。 - 实现一个个人书签管理工具,支持增、查、打标签。
- 用 MCP Inspector 调试。
- 使用官方的
- 动手:写完后接入 Claude Code 实际使用。
- 放弃指数:★★★☆☆
23. MCP 进阶与边界
要点:
- 远程 server 与 OAuth 授权。
- 每个工具定义都会吃掉上下文。
- 工具投毒与信任问题。
- 什么时候不需要 MCP:一个 CLI 工具加一段说明,往往就够了。
- 放弃指数:★★★☆☆
第五部分 手写 Agent 篇:用 Go 从零造一个(24-31)
本系列的核心部分。八篇写完,你手里会有一个能用的迷你 coding agent。
24. 手写 Agent ①:调通 API,跑起多轮对话
- 要点:项目结构;消息历史的数据结构;system prompt 的注入方式;一个最简单的 REPL。
- 参考:Thorsten Ball《How to Build an Agent》(同样用 Go 实现)
- 放弃指数:★★☆☆☆
25. 手写 Agent ②:第一个工具,read_file 与 list_files
- 要点:工具注册表的设计;调用分发;第一次看着模型自己决定先读哪个文件,那种"它活了"的瞬间。
- 放弃指数:★★☆☆☆
26. 手写 Agent ③:让它会改代码,edit_file
要点:
- 采用 str_replace 式编辑,并要求匹配必须唯一。
- 为什么不让模型整文件重写:费 token,而且容易悄悄改坏没打算改的地方。
- 新建文件的处理。
- 放弃指数:★★★☆☆
27. 手写 Agent ④:给它一个终端,run_bash 与权限
- 要点:人工确认机制;命令白名单;超时控制;限制工作目录;危险命令拦截。
- 踩坑预告:作者的
rm -rf惊魂记。 - 放弃指数:★★★☆☆
28. 手写 Agent ⑤:上下文管理
- 要点:工具输出截断;token 预算;自动压缩(把历史对话总结成摘要);最大迭代次数。
- 动手:先故意让 Agent
cat一个巨大的日志文件,看它怎么崩,再修好。 - 放弃指数:★★★★☆
29. 手写 Agent ⑥:流式输出、错误处理与重试
要点:
- SSE 流式解析。
- 遇到限流和服务过载时做指数退避重试。
- 工具报错时把错误信息回传给模型,让它自己修。
- 放弃指数:★★★☆☆
30. 手写 Agent ⑦:Subagent,给 Agent 加分身
要点:
- 实现一个
task工具,作用是开一个拥有全新上下文的子循环。 - 子循环只把摘要返回给主循环。
- 并行执行;多开分身的代价。
- 实现一个
- 放弃指数:★★★★☆
31. 手写 Agent ⑧:Skills 与 MCP 接入
要点:
- 渐进式披露:上下文里平时只放每个 skill 的名字和描述,用到时才读取完整的 SKILL.md。
- 把第 22 篇写的 MCP server 接入自己的 Agent。
- 里程碑:一个能用的迷你 coding agent 诞生。
- 放弃指数:★★★☆☆
第六部分 用好成品篇:拆解 Claude Code / Codex(32-34)
32. Claude Code 解剖:对照自己的实现
要点:
- 逐项对照:工具集、权限模式、plan mode、todo 管理、上下文压缩。
- Codex 在沙箱与权限上做了不同的取舍,两者对比着看。
- 看懂之后再回头看,那些"最佳实践"其实都是从设计里自然推出来的。
- 放弃指数:★★☆☆☆
33. 自动化:Hooks、自定义命令与 Headless 模式
要点:
- 用 hooks 在每次编辑后自动格式化、跑测试。
- 自定义斜杠命令。
- 用 headless 模式(
claude -p)接入脚本、CI 或 n8n 这类自动化平台。
- 放弃指数:★★☆☆☆
34. 多 Agent 并行与 Agent SDK
要点:
- 用 git worktree 让多个 Agent 并行干活。
- 编排者模式。
- 用 Claude Agent SDK 基于官方框架造 Agent。
- 多 Agent 的协调成本,很多时候比你想的高。
- 放弃指数:★★★★☆
第七部分 工程化篇:验证、评测、成本、安全(35-38)
35. 验证回路:测试是 Agent 的眼睛
要点:
- 和 Agent 一起做 TDD:先写测试 → 确认测试失败 → 再实现 → 直到测试通过。
- 用容器做沙箱;mock 外部依赖。
- 让 Agent 能自己跑通端到端流程。
- 动手:同一个需求,分别在有测试和没测试的情况下交给 Agent,对比返工次数。
- 放弃指数:★★☆☆☆
36. Evals:给 Agent 打分
要点:
- 建一个评测集。
- 代码类任务用可执行的方式判分。
- LLM-as-judge 的用法与校准。
- 回归评测:换模型或改 prompt 之前,先跑一遍。
- 参考:Chip Huyen《AI Engineering》;Hamel Husain 的 evals 系列文章
- 放弃指数:★★★★☆
37. 可观测性与成本:Agent 的账本
要点:
- 用 tracing 记录每一步,可以用 OpenTelemetry 或 Langfuse。
- 建一本 token 账本,知道钱花在了哪里。
- 用好 prompt caching。
- 模型路由:小模型打杂,大模型拍板。
- 放弃指数:★★★☆☆
38. 安全:Prompt Injection 与"致命三件套"
要点:
- 网页、文件、工具返回的内容里可能藏着指令。
- "致命三件套":私有数据、不可信内容、对外发送能力,三者同时具备时风险最高。
- 应对:最小权限;关键操作保留人在回路。
- 动手:在本地构造一个藏有注入指令的页面,测试自己写的 Agent 会不会中招,然后加防护。
- 放弃指数:★★★★☆
第八部分 放弃篇:天花板与结业(39-40)
39. Agent 的天花板:什么时候该放弃
要点:
- 复合错误率:每一步 95% 的成功率,连续 20 步之后只剩约 36%。
- 长程任务中的目标漂移;成本难以预测;结果不可验证的任务。
- 什么时候该回到确定性代码。
- 放弃指数:★★★★★(标题都写了)
40. 结业:造一个能用的,然后复盘
要点:用自己的 Agent 和 Claude Code 完成同一个真实任务,然后回答三个问题:
- 差距在哪里?
- 哪些差距来自模型,哪些来自 harness 的设计?
- 哪些问题靠上下文工程就能补上?
- 结语:所谓放弃,是放弃对魔法的幻想,开始把它当作一个可以理解、可以驾驭的工程系统。
- 放弃指数:☆☆☆☆☆(恭喜,你没有放弃)
附录
写作节奏建议
- 按每周 2 篇的节奏,约 20 周写完。
- 第五部分(手写 Agent)建议先把代码全部写完再动笔,避免写到一半推翻前面的设计。
- 原理篇可以和实战篇穿插发布,保持读者的新鲜感。
主资料清单
| 资料 | 对应篇目 |
|---|---|
| Karpathy《Deep Dive into LLMs like ChatGPT》 | 06-13 |
| Karpathy《Let's build the GPT Tokenizer》 | 06 |
| 3Blue1Brown 深度学习系列第 5-7 集 | 09 |
| Anthropic《Building Effective Agents》 | 04、34 |
| Anthropic《Effective context engineering for AI agents》 | 14-16 |
| Anthropic《Writing effective tools for agents》 | 20 |
| Anthropic《Claude Code: Best practices for agentic coding》 | 17、32 |
| Thorsten Ball《How to Build an Agent》 | 24-27 |
| Chroma《Context Rot》 | 16 |
| ReAct 论文(Yao et al., 2022) | 03 |
| MCP 官方文档与 go-sdk | 21-23 |
| Chip Huyen《AI Engineering》 | 36 |
| Simon Willison 关于 prompt injection 的系列文章 | 38 |
注意事项
Agent 领域的产品迭代极快,具体命令、参数和功能名称在写作时以官方文档为准。原理部分的内容相对稳定,可以写得笃定一些;产品操作部分建议在文中注明"截至写作时"。
评论
还没有评论,来说点什么吧。