开场:处处都是熟面孔
写完 mini-agent 的那个周末,我重新打开了用了一年多的 Claude Code,想看看自己造的东西和成品差多远。
这一次的感觉完全不一样了,像是在看一台自己拆过一遍的机器。
以前我看它的工具列表,只觉得"哦,它能读文件、能改文件"。现在我看到它的编辑工具要求 old_string 在文件里唯一,会心一笑:第 26 篇那个唯一匹配。看到它改文件之前必须先读过,我想起了 checkFresh。看到它在上下文快满时自动压缩,我知道它背后多半有一份类似"任务目标、已完成、下一步"的摘要模板。看到它派出一个子 Agent 去调研,界面上缩进显示子 Agent 的工具调用,我想:这不就是 childUI 吗。
当然,也有很多我没做的东西:计划模式、待办清单、操作系统级的沙箱、更细的权限规则、IDE 集成……每一样,背后都是一个我在 mini-agent 里遇到过、却没来得及解决的问题。
这一篇,我们把 Claude Code 拆开,和 mini-agent 逐项对照;再看看 Codex 在沙箱和权限上做了哪些不同的取舍。最后你会发现,网上流传的那些"Claude Code 最佳实践",几乎都能从它的设计里自然地推出来。读完本篇,你应该能回答这几个问题:
- 一个成品 coding agent,和我们手写的 mini-agent,哪些地方一样,哪些地方不一样?
- 计划模式和待办清单是什么?它们为什么有用?
- Codex 和 Claude Code 在安全设计上有什么不同的取舍?
- 那些"最佳实践",背后的道理是什么?
说明:成品 Agent 迭代极快,下面讲到的具体工具名、命令、模式名称,都是截至写作时(2026 年 10 月)的情况,以官方文档为准。这一篇重点是设计思路,思路比名字稳定得多。
一、一张对照表
先看全景:
| 维度 | mini-agent | Claude Code | 对应篇目 |
|---|---|---|---|
| 核心循环 | Agent.Send | 同样的循环 | 02、24 |
| 读文件 | read_file:带行号、分段读 | 带行号、分段读,还能读图片、PDF 等 | 25 |
| 改文件 | edit_file:字符串替换、唯一匹配、改前必须读过 | 同样的思路,另有专门写新文件的工具 | 26 |
| 搜索 | 用 run_bash 跑 grep | 专门的搜索工具(按内容、按文件名) | 18 |
| 终端 | run_bash | Bash 工具,可以选择套一层系统沙箱 | 27 |
| 权限 | 三种模式、白名单、黑名单、人工确认 | 多种模式,加上可配置的允许 / 拒绝规则 | 27 |
| 计划 | 没有 | 计划模式:先只读调研、出方案,批准后再动手 | — |
| 待办 | 没有 | 待办清单工具 | — |
| 上下文 | 截断、预算、自动压缩、/compact、/reset | 自动压缩、手动压缩、清空、查看上下文构成 | 28 |
| 子 Agent | task:全新上下文、只读工具、可并行 | 子 Agent,可以自定义不同类型的子 Agent | 30 |
| 项目记忆 | 读工作目录下的 AGENTS.md | 分层的 CLAUDE.md,可以引用其他文件 | 17 |
| 扩展 | skills、MCP | skills、MCP、hooks、自定义命令、插件 | 31、33 |
| 自动化 | headless 模式 -p | headless 模式、SDK | 33、34 |
| 界面 | 终端 REPL | 终端、IDE、桌面端、网页 | 24 |
你会发现,表格上半部分几乎是一一对应的。这不是巧合:第 02 篇说过,所有 coding agent 剥到最里面,都是同一个循环;而循环里的那些零件,读、改、搜、跑、管上下文,面对的是同样的问题,自然会收敛到相似的答案。
差距主要在下半部分:计划、待办、沙箱、扩展机制、界面。下面挑几个最有意思的展开说。
二、工具集:为什么搜索要单独做成工具
mini-agent 搜代码,是让模型用 run_bash 跑 grep。Claude Code 则有专门的搜索工具:一个按内容搜(底层通常是 ripgrep),一个按文件名模式找文件。
为什么要单独做?这里面有好几层考虑:
- 权限更细:搜索是只读的,可以永远免确认;而
run_bash什么都能干,要按命令内容逐条判断。把搜索单独拎出来,权限系统就简单了。第 27 篇我们花了不少力气处理"grep是白名单,但grep ... > file不是"这种情况,专门的工具天然没有这个问题; - 输出可控:专门的工具可以按相关性排序、限制返回的条数、自动跳过
.gitignore里的文件,不会一次吐出几万行(第 28 篇); - 跨平台:不同系统上的
grep参数不完全一样,专门的工具行为是一致的; - 模型更不容易用错:参数是结构化的(搜什么、在哪个目录、什么文件类型),而不是让它自己拼一条命令。
这是第 20 篇"按任务切分工具"的一个例子。 搜索是编码 Agent 最高频的动作之一,值得一个专门的工具。
同样的道理,Claude Code 的工具描述里会明确告诉模型:读文件用读文件的工具,不要用 cat;改文件用编辑工具,不要用 sed。mini-agent 的 run_bash 描述里也有这句话(第 27 篇)。专门的工具有专门的保护,绕过它们,就绕过了保护。
三、权限:几种模式,加上规则
3.1 模式
第 27 篇我们给 mini-agent 做了三种权限模式:default、accept-edits、yolo。Claude Code 的思路几乎一样,只是档位更多一些。截至写作时,大致有这么几类:
只读,不许改"] --> D["默认
有副作用的要问"] D --> E["自动接受编辑
改文件不问,命令照问"] E --> B["跳过所有确认
只在沙箱里用"] style P fill:#e3f2fd,stroke:#1565c0 style B fill:#ffcdd2,stroke:#b71c1c
"计划模式"是 mini-agent 没有的那一档,下一节专门讲。
3.2 规则
除了模式,Claude Code 还能配置允许和拒绝的规则,比如"go test 开头的命令永远允许""任何对 .env 文件的读取都拒绝",规则可以写在项目的配置文件里,团队共享。
这相当于把 mini-agent 写死在代码里的白名单和黑名单(DefaultAllow、denyPatterns),变成了用户可以配置的东西。思路完全一样:常见的安全操作免确认,危险的操作永远拒绝,其余的问人。
四、计划模式:先想清楚,再动手
4.1 是什么
计划模式(plan mode)是这样工作的:
- 在这个模式下,Agent 只能用只读的工具:读文件、搜索、列目录,不能改文件、不能跑有副作用的命令;
- 它调研完之后,写出一份实施方案:要改哪些文件、每个文件改什么、按什么顺序、怎么验证;
- 方案交给你审。你可以修改、补充、否决;
- 你批准之后,它才退出计划模式,开始动手。
先改 model,再改 service,最后加测试 U->>A: 第二步不对,退款金额要在 service 层校验 A-->>U: 修改后的方案 U->>A: 批准 Note over A: 退出计划模式,开始改代码
4.2 为什么有用
把前面几篇的原理串起来,计划模式有用的原因很清楚:
- 第 07 篇:先推理后行动。 模型没有草稿纸,让它先把方案写出来,就是给了它一张草稿纸。直接动手的 Agent,往往是"边改边想",改到一半发现方向不对,又改回去;
- 第 04 篇:能写死的就写死。 一份批准过的方案,相当于把一个开放式的 Agent 任务,变成了一个接近 workflow 的东西:步骤已经定了,Agent 只需要按步骤执行;
- 人在最便宜的时候介入。 在方案阶段发现"方向错了",改一句话就行;在代码改了二十个文件之后才发现,代价就大得多了;
- 只读保证了安全。 调研阶段它什么都改不了,你可以放心地让它到处看。
4.3 mini-agent 能不能做
能,而且不难。思路是:
- 在
permission.Mode里加一种ModePlan:只有readOnlyTools和白名单里的只读命令放行,其他一律拒绝,拒绝理由写"当前是计划模式,只能调研,不能修改"; - 在 system prompt 里加一段:计划模式下,调研完要输出一份方案;
- 加一个
/plan命令进入、/go命令退出。
这是一个很好的练习,留给你。
五、待办清单:把计划外化
5.1 是什么
Claude Code 有一个"待办清单"工具。在处理一个多步骤的任务时,Agent 会先调用它,写下一个清单:
☐ 读 order/model.go,了解订单结构
☐ 在 Order 里加一个 RefundedAmount 字段
☐ 在 service 里实现 PartialRefund
☐ 加测试
☐ 跑 go test ./...每完成一步,它就再调用一次这个工具,把那一项勾掉,必要时增删条目。用户在界面上能实时看到进度。
5.2 为什么有用
这个工具"什么都不做":它不读文件,不改代码,只是把一个列表存下来,再原样显示出来。那它为什么有用?
答案在上下文里:
- 第 16 篇:长任务里,模型会忘记目标。 一个列表写在上下文里,模型每一圈都能看到"还剩哪几步";
- 第 10 篇:越靠近末尾的内容越容易被注意到。 每次更新清单,最新的版本就出现在消息历史的末尾附近,比十几圈之前用户说的那句话醒目得多;
- 第 39 篇会讲:长程任务的一大难题是目标漂移。 一份不断被刷新的清单,是对抗漂移最简单的办法;
- 对用户也有用:你能看到它打算做什么、做到哪了,跑偏的时候能第一时间发现。
它是把模型脑子里的计划,变成了上下文里的一段文字。 第 02 篇说过:Agent 里没有"规划模块",所谓计划,最终都要变成消息历史里的一段文本,才能被模型看见。待办清单就是这句话最直接的产品化。
mini-agent 也可以加一个:一个 todo 工具,参数是一个列表,Run 里什么都不用做,只要把列表格式化成文本返回,再在终端里显示出来。另一个练习。
六、上下文管理:和第 28 篇如出一辙
Claude Code 的上下文管理,和第 28 篇的思路几乎一样:
- 自动压缩:上下文接近上限时,自动把历史总结成摘要;
- 手动压缩:一个命令,还可以附带指引,比如"压缩时重点保留关于数据库迁移的讨论";
- 清空:开始一个新任务;
- 查看上下文的构成:system prompt、工具定义、记忆文件、MCP 工具、对话历史各占多少。第 14 篇的拆解实验,第 16 篇的动手作业,都是在用这个功能。
手动压缩时"附带指引"这个功能,mini-agent 没有,但加起来很容易:/compact 后面如果跟了一段文字,就把它拼进第 28 篇那段压缩 prompt 的末尾,比如"另外,务必保留关于数据库迁移的所有决定"。第 28 篇说过,自动压缩最大的问题是"你不知道它丢了什么";能附带指引,就等于让你提前告诉它"这个不能丢"。
还有一点值得一提:它的项目记忆文件 CLAUDE.md 是分层的(第 17 篇):用户级、项目级、子目录级,处理哪个目录就加载哪个目录的那一份。mini-agent 只读工作目录下的一份 AGENTS.md。
七、Codex:另一种安全取舍
7.1 沙箱优先
OpenAI 的 Codex 在很多方面和 Claude Code 很像:同样的循环、类似的工具、同样认 AGENTS.md。但在安全设计上,它走了一条有点不同的路:沙箱优先。
截至写作时(以官方文档为准),Codex 的命令默认运行在操作系统级的沙箱里:
- 沙箱限制了它能写的目录,通常只允许写工作目录;
- 沙箱默认可以禁止网络访问;
- 在这个沙箱里,很多操作可以不问用户,因为就算做错了,影响也被限制在沙箱之内;
- 需要越出沙箱的操作(比如访问网络、写工作目录以外的地方),才需要用户批准。
它把"安全"分成了两个维度来配置:沙箱的范围(只读 / 可以写工作目录 / 完全放开)和审批的策略(什么时候问用户)。
7.2 两种思路的对比
先问人"] --> A2["人批准了,
在真实环境里执行"] end subgraph B["沙箱优先"] B1["在受限的沙箱里
直接执行"] --> B2["要越出沙箱时
才问人"] end style A fill:#e3f2fd,stroke:#1565c0 style B fill:#e8f5e9,stroke:#2e7d32
| 问人优先 | 沙箱优先 | |
|---|---|---|
| 安全靠什么 | 人的判断 | 操作系统的隔离 |
| 打扰程度 | 高,经常要确认 | 低,大部分操作不用确认 |
| 人疲劳之后 | 容易无脑点"允许",形同虚设 | 不受影响 |
| 实现难度 | 低 | 高,要对接各个操作系统的沙箱机制 |
| 漏洞 | 人看走眼 | 沙箱本身有漏洞,或者配置得太宽 |
问人优先的最大问题是确认疲劳:一个任务要确认二十次,到第五次你就不看了,直接按 y。这时候"人在回路"就成了一句空话。沙箱优先的思路是:与其指望人每次都认真看,不如让大部分操作即使做错了也没关系。
这两种思路也在互相靠拢:Claude Code 也加入了给命令套一层系统沙箱的能力,Codex 也保留了审批策略。第 27 篇说过,mini-agent 没有做操作系统级的沙箱,它的答案是"放开权限时,在容器里跑",本质上是把沙箱这件事交给了你。
7.3 在 mini-agent 上也能"沙箱优先"
mini-agent 自己没有沙箱,但你可以从外面给它套一个。配套仓库里有一份 .devcontainer/ 配置,它本来是给 Codespaces 用的,让你在浏览器里就能跑起整个仓库。换个角度看,它也是一个现成的隔离环境:在容器里用 -mode yolo 启动 mini-agent,它能改的只有容器里的文件,删光了重建一个就是。
这其实就是 7.1 节"沙箱优先"的一个粗糙版本:隔离的边界由容器来画,而不是由每一次确认来画。 它粗糙在两个地方:一是容器默认能联网,第 38 篇说的"往外发数据"依然可能;二是你挂载进容器的目录,比如你的源代码,它照样能改。真正的沙箱优先,会把"能写哪些目录、能不能联网"都做成可以配置的东西。
八、最佳实践,其实是设计的推论
网上流传着很多"用好 Claude Code 的技巧"。现在回头看,几乎每一条都能从我们前面讲过的原理里推出来:
| 最佳实践 | 为什么有用 | 原理在哪篇 |
|---|---|---|
| 给它写测试,告诉它怎么验证 | 结果可验证,Agent 才能自己纠错 | 05、35 |
| 把构建命令、约定、坑写进记忆文件 | 上下文之外的,它一概不知道 | 14、17 |
| 复杂任务先让它出计划 | 模型没有草稿纸,先推理后行动 | 07 |
| 一个任务一个会话,做完就清空 | 长对话会腐烂 | 16 |
| 长任务写交接文档 | 自动压缩会丢东西,交接文档你能审 | 16、28 |
| 告诉它具体的文件路径 | 让它看到关键信息,比改措辞有用 | 14 |
| 大范围调研交给子 Agent | 隔离上下文,主对话保持干净 | 30 |
| 别在真实环境里跳过所有确认 | 黑名单永远不完整 | 27 |
| 小步提交,经常看 diff | 它可能改了你没打算改的地方 | 26 |
| 别只接一堆 MCP server | 每个工具定义都在吃上下文 | 23 |
| 它说"改好了",自己再跑一遍测试 | 它的自信和它的正确率无关 | 02、05 |
理解了设计,最佳实践就不用背了。 遇到一个新产品、一个新功能,你也能自己推出该怎么用它。
8.1 反过来:用原理认出过时的"技巧"
这张表还有一个反向的用法:认出那些已经过时、甚至有害的技巧。
网上很多"提示词秘籍"是在两三年前写的,那时的模型、那时的产品和今天很不一样。拿原理去对一对,很多就站不住了:
- "在 prompt 里用全大写的 MUST 和三个感叹号强调":第 15 篇说过,新模型对指令越来越敏感,用力过猛反而可能让它在不该过度执行的地方过度执行。把规则写具体、给出原因,比加感叹号有用;
- "每次都写'请一步一步思考'":第 12 篇说过,推理模型已经会自己想了,这句话往往只会让正式回答里多出一段重复的推理;
- "一次把整个代码库喂给它,让它全面了解":第 10、18 篇说过,窗口装得下不等于看得清,让它按需搜索往往效果更好;
- "它答错了就让它重新生成,总有一次对的":第 08 篇说过,随机性可以用来探索,但一个要反复重来才能碰对的任务,多半是上下文缺了东西。
技巧会过时,原理不会。 判断一条技巧还值不值得用,就问它背后的原理在今天的模型和产品上还成不成立。
九、动手:同一个任务,两个 Agent
这一篇在配套仓库里没有对应的代码。动手环节是对比体验:
mini-agent 要接真实模型:先 export DEEPSEEK_API_KEY=sk-...。实验 1:对照工具列表
在你常用的编码 Agent 里(Claude Code、Codex 或别的),找到查看它工具列表的方法(很多产品可以直接问它"你有哪些工具",或者在设置里看)。对照第一节的表格,标出:
- 哪些工具在 mini-agent 里有对应的?
- 哪些是 mini-agent 没有的?它们解决的是什么问题?
实验 2:同一个任务
找一个你自己项目里的小任务,比如修一个小 bug、加一个简单的函数,分别交给 mini-agent 和成品 Agent。记录:
| mini-agent | 成品 Agent | |
|---|---|---|
| 转了几圈 | ||
| 读了哪些文件 | ||
| 你确认了几次 | ||
| 结果对不对 | ||
| 花了多少钱 |
(mini-agent 的费用用 /cost 看;第 37 篇会细讲。)这是第 40 篇结业任务的预演。
实验 3:试试计划模式
如果你用的 Agent 有计划模式,拿一个需要改好几个文件的任务,先在计划模式下让它出方案,你修改一处,再批准执行。和直接让它动手对比一下:结果更好了吗?你在什么时候发现了问题?
实验 4:给 mini-agent 加上计划模式或待办清单
按 4.3 节或 5.2 节的思路,给 mini-agent 加上其中一个。改完之后跑一遍 go test ./agent/...,别把已有的东西改坏了。
十、踩坑记录:用成品时的五个误区
误区 1:觉得成品"有魔法"。
它的核心和你写的 mini-agent 是同一个循环。它更好用,是因为每个零件都打磨得更细,而不是因为有什么神秘的机制。理解了这一点,遇到它犯傻的时候,你就知道该去哪里找原因。
误区 2:把所有确认都关掉,"反正它挺靠谱的"。
它大部分时候确实靠谱。但第 27 篇的惊魂记告诉我们,出事往往就在那一次。放开权限,要么在沙箱里,要么在容器里。
误区 3:只用它写代码,不让它验证。
它能跑测试,但你得告诉它测试怎么跑、哪些测试要通过。没有验证的 Agent,和第 02 篇那个"不看结果的剧本模型"没有本质区别。
误区 4:跳过计划,直接让它干大活。
大的改动,先出方案。在方案阶段改一句话,比在代码阶段返工便宜得多。
误区 5:遇到问题就换模型。
很多问题出在上下文里:它没看到关键文件、记忆文件过时了、对话太长了。先看看它看到了什么,再考虑换模型(第 13 篇:管好上下文,加上验证)。
一句话总结
成品 coding agent 和我们手写的 mini-agent 是同一个循环,读、改、搜、跑、管上下文这些零件几乎一一对应;差距在计划模式、待办清单、沙箱、可配置的权限规则和更多的扩展机制;Codex 走的是沙箱优先的路,用隔离代替频繁的确认;而那些最佳实践,都是从设计里自然推出来的。
循环 + 工具 + 权限 + 上下文"] -->|"再加上"| P["计划模式、待办清单、
沙箱、规则、hooks、IDE……"] P --> C["成品 Agent"] style M fill:#e8f5e9,stroke:#2e7d32 style C fill:#fff3e0,stroke:#e65100
评论
还没有评论,来说点什么吧。