最近,Claude Code 团队的成员 Thariq 发表了一篇深度总结,题为《Lessons from Building Claude Code: Seeing like an Agent》。这篇文章没有炫耀产品多强大,而是坦诚地分享了他们在过去一年中踩过的坑、走过的弯路以及最终沉淀下来的方法论,特别聚焦于一个核心问题:如何为AI智能体设计工具?
文章的核心论点非常犀利:构建智能体的最大挑战,往往不在于模型本身是否足够聪明,而在于如何设计它的“动作空间”。你提供的每一个工具,都会从根本上改变它的思考路径和失败模式。关键在于给它“能用好”的工具,并且当问题出现时,它能有机会自我纠正。
Thariq 将这套方法论提炼成一句话:学会像智能体一样观察世界。 这听起来抽象,但在工程上非常具体:不要在白板上凭空设计工具,而要去分析真实对话日志,观察模型在哪里卡住、为什么卡住,以及卡住之后你希望它如何自救。
下面,我们将结合原文中的三个关键案例进行展开,并在文末附上一套可落地的实践清单。
太长不看版(核心要点)
- 动作空间是核心产品:Agent 最难的不是“会做”,而是 动作空间的设计。每个工具都会引入新的决策分支和潜在失败点。
- 工具适配性优先:工具不是越强大越好,关键是模型是否能有效使用它。就像解题时,计算器、纸笔和电脑的优劣,取决于解题者能否驾驭。
- 结构化提问是突破点:让模型通过纯文本提问沟通效率低。创建专用的结构化提问工具能显著降低人机交互摩擦。
- 警惕早期工具的“副作用”:曾经有效的工具(如 Todo 列表)在模型能力提升或多智能体协作时,可能从“拐杖”变成限制思维的“枷锁”。
- 让智能体自建上下文:从 RAG(被动检索)到 Grep(主动搜索),再到技能的分层披露,趋势是让 Agent 按需获取信息,而非被动接受海量上下文。
- 不加工具也能扩展能力:通过子智能体、分层知识文件等方式扩展能力边界,本质上是扩大了动作空间,但没有增加主智能体的工具数量。
- 工具设计是迭代艺术:多实验、多读模型输出、做小改动。优先优化系统的可恢复性,而不仅仅是追求能力上限。
一、动作空间才是真正的产品
很多团队在构建智能体时,第一反应是堆砌能力:接入网页、数据库、浏览器,调用多个模型,再添加一堆花哨的工具。
但真正上线后,最先暴露的问题往往是:
- 模型困惑:在几十个工具入口前犹豫不决,错误尝试或误用。
- 调试困难:无法理解模型为何做出某个特定动作,出了问题难以复现和修复。
这就是 Thariq 强调的“动作空间”——模型“能做什么”的全部可能性集合。你赋予它的每个新工具,都像是给了一个新器官,同时也引入了一个新的风险面。
文章提到了一个实际的工程困境:在 Claude API 中,工具可以通过多种原语构建,比如 bash、skills 或代码执行。选项多了,抉择就来了:是提供一个“万能工具”(如 bash),还是提供几十个高度专用的工具?
这里有一个非常贴切的比喻:
你面前有一道复杂的数学题。你想要什么工具?
- 纸和笔:最基础,但速度慢。
- 计算器:更快,但你需要知道如何使用其高级功能。
- 计算机:功能最强大,但你需要会写代码、运行和调试。
将这个问题映射到智能体上:你应该给模型提供“它能用好的工具”,而不是你认为“最强大”的工具。
那么,如何知道它能用好什么工具呢?答案朴实但有效:仔细观察它的输出,反复进行测试。
我们可以将工具按风险和潜力大致分为三类,以便决策:
| 工具类型 |
典型例子 |
收益 |
代价与风险 |
| 低风险,低能力 |
只读检索、总结 |
失败可控,行为可预测 |
能力上限有限 |
| 中风险,可组合 |
结构化提问、任务管理 |
提升沟通带宽,使协作更稳定 |
需要设计清晰的使用契约 |
| 高风险,高上限 |
bash、代码执行、网络访问 |
真正“能干活”,潜力巨大 |
需全面管理权限、状态、副作用和可恢复性 |
二、让模型“会提问”——AskUserQuestion 为何是“甜蜜点”
几乎每个智能体产品都会遇到一个痛点:模型需要向用户澄清需求,但这个澄清过程本身非常低效。
纯文本提问的问题不在于“问不出来”,而在于“沟通带宽太低”。用户需要阅读一长串问题并逐一回答;模型可能还会追问、改变问法或补充条件,导致交互回合数爆炸。
Claude Code 团队的目标很明确:降低模型提问的摩擦,提高人机沟通的带宽。 他们为此进行了三次主要尝试。

尝试1:把“问题”塞进计划工具
最简单的想法是:在输出计划的那个工具里增加一个参数,让它同时生成一组需要澄清的问题。
结果模型困惑了:我到底是在“制定计划”,还是在“询问制定计划所需的信息”?如果用户的回答与初步计划冲突,模型该修改计划吗?需要再调用一次工具吗?工具的职责开始混淆不清。
教训:一个工具试图同时承担两件不同的事情,最终可能导致两件事都做不好。
尝试2:强制规定 Markdown 输出格式
第二个思路更“通用”:不创建新工具,而是要求模型输出一种改造过的 Markdown 格式(例如,每个问题带上方括号选项),然后由程序解析并渲染成用户界面。
在演示中效果不错,但上线后非常脆弱:模型只要多写一句解释、漏掉一个选项或改变一个标点,整个解析就可能失败。
教训:将系统的可靠性建立在“模型永远严格遵循特定文本格式输出”的假设上,是脆弱的,迟早会出问题。
尝试3:专用的 AskUserQuestion 工具
最终,他们创建了一个专用的提问工具。模型可以在任何需要的时候调用它,尤其是在“规划模式”下被鼓励使用。调用后,会弹出一个结构化的用户界面,并暂时阻塞智能体的执行循环,直到用户做出回答。
这个方案的价值不在于“更复杂”,而在于“更清晰”:
- 职责单一:工具只负责提问和收集答案。
- 结构固定:输出是结构化的数据,天然易于解析和渲染。
- 交互高效:用户回答从“写一段话”变为“选择一个选项”,沟通带宽提升,回合数减少。
- 可复用:该能力可以在 SDK、Skills 等其他场景中复用。

推文配图:AskUserQuestion 的“甜蜜点”在于平衡自由与刚性。太自由会混乱,太刚性则脆弱。

推文配图:AskUserQuestion 的结构化交互界面示例(支持点选和补充输入)。
落地建议:把“提问”当作接口设计,而非文案写作
如果你正在设计智能体产品,建议将用户问询设计成一种工程契约,至少包含以下四个要素:
- 问题要简短:每次只聚焦一个决策点,避免将一整份需求文档塞进一个问题。
- 选项要互斥:尽可能使用枚举选项,避免让用户陷入“既选A又选B”的模糊境地。
- 提供默认值:明确用户未做选择时的处理逻辑,不要让模型去猜测。
- 保留自由输入口:当枚举无法覆盖所有情况时,允许用户补充说明,但应将其放在单独的字段中。
这些要求本质上不是“写作技巧”,而是接口设计规范。模型也更倾向于调用一个契约清晰的工具,而不是在自然语言中反复试探和绕弯子。
三、模型变强后,Todo 从“拐杖”变成了“枷锁”
Claude Code 早期使用 Todo(待办事项)列表来防止模型跑偏:项目开始时先写一个待办列表,完成一项勾选一项。他们为此提供了 TodoWrite 工具来写入和更新待办事项。即便如此,模型还是经常忘记要做什么,于是他们又增加了“每5轮对话提醒一次”的系统提示。
在模型能力较弱的阶段,这种方法非常有效。
但随着模型训练的迭代和能力提升,副作用开始显现:
- 模型开始将 Todo 列表视为“不可违背的剧本”,不敢灵活调整执行路线。
- 系统的定期提醒反而强化了“死守列表”的倾向,模型不再主动思考并修改计划。
- 当引入多智能体协作时,共享的 Todo 列表成为了瓶颈——谁来修改?如何合并更新?如何表达任务间的依赖关系?
于是,他们将 TodoWrite 工具升级为了 Task(任务)工具。核心变化在于:从“个人记事本”升级为“团队协作协议”。

推文配图:从 Todos 到 Tasks 的转变,背后是模型能力提升与多智能体协作需求的驱动。
Todos 与 Tasks 的本质区别
用工程语言来翻译:
- Todos 更像是线性的检查列表,适合单线程执行和防止思路跑偏。
- Tasks 更像是有向无环图,适合表达依赖关系、多线程协作和状态同步。
当智能体演变为一个团队时,任务管理的目标不再是“提醒自己”,而是“对齐彼此”:
- 依赖表达:如何声明“任务C依赖于任务A和B的完成”?
- 状态同步:谁做了什么?进度如何?
- 产物归档:每个任务的输出物保存在哪里?
- 失败回滚:某个任务失败后,其影响范围是什么?如何恢复?
这也是原文中最值得划线的一点:工具会“过期”。当模型能力升级或工作方式发生变化后,你需要有勇气回过头来,重新审视并重构已有的工具设计。

四、让智能体自己“寻找上下文”——渐进式披露优于硬塞文档
第三个案例探讨的是上下文构建的问题。
Claude Code 早期使用 RAG向量检索来提供上下文。RAG 强大且快速,但存在两个硬伤:
- 需要预先构建和维护索引,环境复杂时可能变得脆弱。
- 更关键的是,上下文是“你喂给它的”,而不是“它自己找到的”。
后来,他们提供了类似 Grep 的工具,让 Claude 能够在代码库中主动搜索文件,自己构建所需的上下文。
再往后,他们将这种按需探索的能力正式化为“Skills”,并强调一个核心理念:渐进式披露。
理解起来很直观:不要把所有的信息都塞进系统提示词里,而是给模型提供一个入口,让它能够像我们查阅资料一样,按需、分层地读取信息。没有人会先把一整本书背下来再开始解题。
文章还补充了一个很产品化的细节:Claude Code 目前只有大约20个工具,他们一直在自我审视“是否真的需要更多”。因为每增加一个工具,模型就多一个需要考虑的选项,其决策空间会变得更复杂。
所以他们为“添加新工具”设置了很高的门槛。更多时候,他们优先通过“渐进式披露”来扩展能力——这同样能让模型获得所需信息,但无需在主界面上增加一个新的工具入口。
更进一步,他们还创建了一个名为“Guide”的子智能体,专门用于回答“Claude Code 自身如何使用”这类问题。逻辑很现实:把所有操作文档塞进系统提示词,当没人提问时它们就只是噪音,会导致上下文质量下降;如果只给文档链接,模型又可能一次性加载大量搜索结果,结果仍然是噪音。
Guide 子智能体的策略是:将“如何查找、查到什么程度、返回什么格式”写成专门的指令,只有当用户询问关于 MCP、斜杠命令等特定问题时才触发它。这样,无需增加新的主工具,就扩展了智能体的能力边界。
一种可直接应用的知识分层方案
如果你需要将一套团队知识库交给智能体使用,采用“分层文件”结构通常比编写“万字提示词”更稳健。一个常用的三层结构是:
- 第0层:索引(200–500字)
只回答核心问题:我们有哪些能力?入口在哪里?在什么场景下使用哪个?
- 第1层:模式卡片(500–1500字)
使用清单、正面示例和反面示例,清晰地说明“如何操作”以及“如何验收”。
- 第2层:完整手册(2000字以上)
仅在需要深入细节时加载,避免长期占用宝贵的上下文窗口。
这与原文评论区提到的“三层系统”不谋而合,但这里特别强调 第1层必须可执行——它不应该只是说明,而应该是可以直接套用的操作清单。
这样做的好处显而易见:不触发就不占用 token;触发时能提供足够完成任务的信息;结构天然易于维护,修改某一层不会污染整体。

递归读取需克制,设置天花板
很多人看到“递归读取文件”会很兴奋,恨不得让智能体串联起整个知识图谱。
建议从一开始就关注两个关键指标:
- 搜索深度:智能体翻了多少层链接才找到目标信息?
- 回报率:每多深入一层,最终答案的质量提升有多大?
当“深度持续增加,但答案质量未见显著改善”时,就应该停止递归。更常见的做法是在第一层就放置“足够使用的结论性信息”,避免智能体为一个小问题陷入无限深挖的循环。
五、工具设计的迭代循环(7个步骤)
将原文的三个案例与工程实践相结合,可以总结出一套可复用的迭代节奏:
- 从真实输出中寻找摩擦点:不要猜测,去查看对话日志,分析模型在哪里卡住、在哪里出错。
- 优先选择最小杠杆:能用优化提示词解决的,就不要急于创建新工具;能用一个工具解决的,就不要堆砌多个。
- 将工具接口做“窄”:一个工具最好只承担一个清晰、单一的职责。
- 将结构化任务交给机器:关键数据不要隐藏在自然语言中,应通过数据模式、枚举值和默认值来规范。
- 将失败设计为可恢复的:允许重试、撤销和回滚,让模型在出错后有机会自我纠正。
- 确保交付物可落地、可验收:任务结果不应只停留在聊天气泡里,而应输出为可被人工审查的文件或成果。
- 定期复盘工具的适用性:模型能力进化后,曾经的“拐杖”可能成为“枷锁”,需要及时调整或更换。
当你准备“再增加一个工具”时,不妨先问自己:这个工具是否能让系统的失败模式变得更可控、更易恢复? 如果答案是否定的,那么这个工具很可能只是增加了系统的复杂性和噪音。
六、何时该“添加工具”?——一张决策参考表
很多团队的工具列表越来越长,常见的原因是:每当遇到一个问题,就下意识地“增加一个按钮或功能”。
建议在采取行动前,先用下面的表格审视一下,将解决方案收敛到最小可行的控制面:
| 遇到的问题 |
优先解决方案 |
原因分析 |
| 输出措辞不稳定,格式偶尔出错 |
优化提示词 + 补充少量示例 |
成本最低,不改变动作空间的复杂度 |
| 需要稳定、结构化的输出(用于解析、渲染或验证) |
引入专用工具(定义数据模式、枚举值、默认值) |
让结构由机器保障,减少对模型自由发挥的依赖 |
| 知识量大但不常用,仅在特定场景需要细节 |
采用文件分层 + 渐进式披露 |
避免不常用信息长期污染主上下文 |
| 需要按特定模式查询资料、文档或代码 |
创建具有明确搜索策略的子智能体 |
扩展能力边界,但不会增加主智能体的工具数量 |
你会发现,“添加新工具”并非默认选项,它更像是在确实需要一个结构化控制面时才采取的最终手段。
七、反模式检查清单
- 让一个工具同时负责计划、提问和执行:最容易让模型困惑,也最难进行调试。
- 依赖模型严格输出某种特定的自由文本格式:设计越“通用”,在生产环境中往往越脆弱。
- 把 Todo 当作不可更改的“剧本”而非动态的“状态”:这会导致模型不敢调整计划,在多智能体协作中尤为困难。
- 将整套文档全部塞进系统提示词:短期内可能有效,长期会导致上下文质量下降,维护成本越来越高。
- 只追求能力上限,忽视失败的可恢复性:能做更多事情,并不等同于你能放心地让它去做这些事情。
八、这是一门艺术,而非精确科学
工具设计没有放之四海而皆准的黄金法则,它高度依赖于你所使用的模型、你的产品目标以及智能体运行的具体环境。
更可靠的做法是将其视为一个持续迭代的循环:多进行实验,多阅读模型的原始输出,勇于尝试新的工具形态。正如我们在技术文档中常做的那样,从实践中总结规律。
最后,回归到文章开篇的核心:像智能体一样去观察。 观察它的行为,理解它的困境,然后迭代改进。这不正是人类学习、进步和解决问题的方式吗?在云栈社区,我们鼓励开发者分享这样的实战复盘,共同推进AI Agent技术的工程化落地。
落地清单:构建智能体框架前建议补齐的12项能力
- 提供结构化提问入口:实现类似
AskUserQuestion 的功能,优先级应设为最高。
- 将提问设计为UI契约:问题简短、选项互斥、包含默认值、支持自由补充。
- 用动态Tasks替代静态Todos:尤其是在涉及子智能体或并行执行的场景中。
- 任务需支持依赖与状态管理:能够表达有向无环图依赖,支持状态同步和产物关联。
- 赋予智能体自建上下文的能力:提供类似代码库内
Grep 的搜索工具,通常比单纯的RAG更稳健。
- 采用分层文件组织知识:建立索引层、模式层、手册层,实现按需加载。
- 坚持渐进式披露原则:不常用的信息绝不常驻在主上下文中。
- 克制工具数量:每一个新增工具都意味着一个新的决策分叉点和潜在的失败点。
- 确保关键动作可回放:日志、调用链追踪和工具参数都必须能够完整复现。
- 优先优化系统的可恢复性:实现低成本的重试机制,明确的前置条件检查,以及可观测的状态。
- 将交付物输出为实体文件:让工作成果走出聊天窗口,变得可审查、可版本化管理。
- 每次模型升级后复盘工具集:旧工具可能已经限制了新模型能力的发挥,切勿恋旧。
来源