Thariq推文【Lessons from Building Claude Code Seeing like an Agent】精读
像 Agent 一样看:从 Claude Code 的工具设计中学到什么
再次精读一篇Thariq关于 Claude Code 的文章,Lessons from Building Claude Code: Seeing like an Agent。它讨论的不是某一个具体功能怎么实现,而是一个更难也更本质的问题:我们该如何为 Agent 设计“动作空间”。
这篇文章最打动我的地方在于,它没有把工具设计讲成一套静态规范,而是提出了一种很工程化、也很现实的方法:先观察模型如何思考、如何犯错、如何使用工具,然后再反过来塑造工具。 这就是所谓的“像 Agent 一样看”。
如果要用一句话概括全文,我会这样说:
Agent 的工具不是越多越好,也不是越强越好,而是要和模型当前的能力、任务目标以及运行环境相匹配。
这篇文章主要讲了什么
文章围绕 Claude Code 的几个真实设计案例,讲清了一个核心命题:构建 Agent harness 最难的部分之一,不是把工具接进来,而是设计一个适合模型的动作空间。
Claude 可以通过 Tool Calling 使用各种能力,比如 Bash、Skills、代码执行等。问题在于,选项一多,设计就会变复杂:
- 是不是只给一个通用工具就够了?
- 还是应该为每类场景都提供一个专门工具?
- 一个工具到底应该做得多通用,还是多结构化?
- 模型能力变了以后,原来好用的工具会不会反过来限制它?
文章的回答很有意思:不要先站在工程师视角想“系统应该有什么”,而是要站在模型视角想“如果我是这个 Agent,我现在最适合用什么来完成任务”。
这也是“Seeing like an Agent”的真正含义。
从“给工具”到“按能力塑形”
作者用了一个很直观的比喻:如果让一个人解一道复杂数学题,你会给他什么工具?
- 一张纸,最低配,但很多计算要手工完成
- 一个计算器,更强,但前提是你会用复杂功能
- 一台电脑,能力最强,但你得知道怎么写代码、怎么执行程序
这个比喻背后的关键点是:同样一个任务,最适合的工具取决于使用者本身的能力。
Agent 也一样。一个模型并不是抽象意义上的“智能体”,它是一个具有当前能力边界、偏好和局限的具体系统。工具设计的目标,不是堆满可能性,而是让工具的形状和模型的能力结构尽可能对齐。
下面这张图可以概括文章的整体方法:
这也是全文最重要的工程思路:工具设计不是一次性规划,而是持续观察后的迭代塑形。
案例一:AskUserQuestion 工具是怎么长出来的
文章第一个案例讲的是 Claude Code 里的 AskUserQuestion 工具,也就是让 Agent 更高效地向用户提问。
一开始,Claude 当然可以直接在聊天里提问,但作者发现这种方式有明显摩擦:
- 用户回答成本高
- 提问结构不稳定
- 交互带宽低
- 很难保证问题总是清晰且有选项
于是他们做了几轮尝试。
第一次尝试:把问题塞进 ExitPlanTool
他们先尝试在 ExitPlanTool 里增加一个参数,让模型在提交计划时顺便给出一组问题。
这在实现上最简单,但语义上很混乱。因为模型一边要产出计划,一边又要对计划提问。如果用户回答和计划冲突,系统到底应该信哪边?模型是不是还得再调用一次工具?
也就是说,这种设计在工程上省事,但在 Agent 的行动语义上不够清晰。
第二次尝试:改输出格式
接着他们尝试让 Claude 用一种稍微结构化的 markdown 来输出问题,比如要求它输出项目符号、括号中的候选项等等,再由前端解析成 UI。
这个方案很通用,但不稳定。模型虽然“多数时候”能照做,但并不保证:
- 有时会多说几句
- 有时会漏选项
- 有时会自己换格式
这暴露了一个典型问题:让模型“模仿结构化输出”和让模型“真正调用结构化接口”,可靠性完全不是一个等级。
第三次尝试:单独做一个 AskUserQuestion 工具
最后他们做了一个专门工具,Claude 可以在任何需要的时候调用它,尤其是在 plan mode 里。工具触发后,UI 会弹出问题列表,并阻塞 Agent loop,直到用户回答。
这个设计的价值很明显:
- 输出结构稳定
- 可以强制包含选项
- 交互更顺滑
- 更容易在 SDK、skills 等场景里复用
更关键的是,Claude 喜欢调用它,而且调用得对。
这一点特别重要。因为一个工具是否成功,不只取决于它的功能完不完整,还取决于模型是否容易理解“什么时候该用、怎么用、用了之后会发生什么”。
案例二:Todo 不一定一直比 Task 更好
第二个案例更能说明“工具要跟着模型能力变化而变化”。
Claude Code 早期引入了 TodoWrite,让模型把任务写成 Todo list,并在执行过程中逐项勾选。这很好理解,因为早期模型确实容易跑偏,Todo 能起到“把模型拉回轨道”的作用。
但随着模型变强,这种工具开始出现副作用:
- 模型不再需要频繁提醒
- 固定 Todo 列表反而限制了灵活调整
- 子代理之间也难以共享和协同 Todo 状态
于是他们用 Task Tool 替代了 TodoWrite。Tasks 不只是“提醒模型别忘了做什么”,而更像 Agent 之间共享的任务载体:
- 可以有依赖关系
- 可以跨子代理同步更新
- 可以被修改、删除、重组
这里最值得记住的一点是:
一个工具曾经有用,并不意味着它会一直有用。随着模型能力提升,原本用于约束模型的结构,可能会逐渐变成束缚模型的结构。
这其实是做 AI 产品非常容易忽略的一件事。我们经常把某个设计当成固定最佳实践,但在 Agent 场景里,最佳实践往往是随模型能力迁移的。
案例三:搜索不是“喂上下文”,而是“让它自己找上下文”
文章第三个案例讲搜索接口设计,我觉得它非常重要,因为它直接关系到 Agent 如何构建自己的上下文。
Claude Code 早期也使用过 RAG 向量数据库来给模型提供上下文。这种方式快、强,但也有问题:
- 需要预先索引和维护
- 在不同环境里容易脆弱
- 更关键的是,这些上下文是“系统替它找好再喂进去的”
后来他们意识到,如果 Claude 可以上网搜索,那为什么不能自己搜索代码库?
于是他们给了 Claude 一个 Grep 工具,让它自己找文件、自己探索、自己建立上下文。
这意味着系统设计思路发生了变化:
- 过去是“替模型准备上下文”
- 后来变成“给模型探索上下文的能力”
这不是一个小改动,而是一个范式变化。因为更强的模型往往不只是更会回答问题,也越来越会主动构建完成任务所需的信息环境。
渐进披露:少加工具,也能增加能力
文章后半部分引出了一个特别值得借鉴的设计思想:progressive disclosure,渐进披露。
它的核心不是把所有能力一次性塞给模型,而是让模型在需要时,逐层发现和展开更多上下文或能力。
这套思路的好处在于,它能在不持续膨胀工具集的前提下,让 Agent 处理更复杂的问题。
文章举了一个具体例子:Claude Code 本身并不总是知道“如何使用 Claude Code”。比如用户问它怎么配置 MCP、slash command 是什么,它未必能答好。
如果把所有文档知识都塞进 system prompt,会带来两个问题:
- 上下文越来越臃肿
- 干扰它的主任务,也就是写代码
所以他们没有把文档硬塞进 prompt,而是先给 Claude 文档入口。后来又进一步做了一个 Claude Code Guide 子代理,在用户问“关于 Claude Code 自身的问题”时,由这个子代理专门去检索文档并返回答案。
这里很妙的一点是:他们增加了动作空间,但没有新增一个显眼的大工具。
这说明,给 Agent 增强能力,不一定等于新增 API;也可以通过分层信息、子代理和渐进披露来完成。
这篇文章真正想表达什么
表面上看,这篇文章在讲 AskUserQuestion、Task Tool、Grep、Guide Agent 等具体设计。但如果往下看,它真正想表达的是一个更通用的方法论:
Agent 设计不是先定义一套完美工具箱,再让模型去适应;而是先观察模型如何工作,再让工具逐步贴合模型。
这意味着几个非常重要的设计原则:
1. 工具设计要以模型可用性为中心
一个工具再强,如果模型不会稳定调用,价值就很有限。好的工具不是“理论上功能最多”的工具,而是“模型最容易理解并正确使用”的工具。
2. 不要把当前最优解误当成永久最优解
模型能力在变化,工具的最佳形态也会变化。过去帮助模型保持轨道的结构,将来可能变成限制模型探索的约束。
3. 上下文构建能力本身就是一种核心能力
未来更强的 Agent,不只是更会推理,还会更会“找资料、找线索、找上下文”。因此搜索接口、技能系统、渐进披露机制,都会越来越重要。
4. 新功能不一定对应新工具
如果每次遇到新需求都加一个工具,动作空间会越来越复杂。更成熟的方式,往往是通过文档入口、技能引用、子代理或渐进披露来扩展能力。
对我们自己做 Agent 有什么启发
如果把这篇文章翻译成更可执行的工程建议,我觉得至少有下面几条。
先观察模型,再设计工具
不要只从“人类工程师觉得工具应该长什么样”出发。先看模型在真实任务里是怎么失败的、怎么绕路的、怎么误用工具的。
用结构化接口替代脆弱的格式约定
如果一类交互需要高稳定性,不要过度依赖“让模型输出特定格式再解析”。优先考虑真正的结构化工具调用。
定期审视旧工具是否已过时
模型升级之后,要重新问一遍:
- 这个工具现在还在帮助模型吗?
- 还是已经开始限制它?
- 有没有更适合多代理协作的新抽象?
给模型探索环境的能力
很多时候,最有价值的不是多给它一段上下文,而是多给它一个自己找上下文的入口。
把动作空间控制在足够小但足够强的范围内
工具越多,决策复杂度越高。真正好的动作空间,往往不是最大化能力列表,而是最小化模型的选择负担,同时保证关键能力可达。
结语
这篇文章最后说了一句很值得记住的话:设计模型的工具,既是一门科学,也是一门艺术。
我很认同这一点。因为 Agent 系统不是纯静态软件,它面对的是一个会随着模型能力变化而不断迁移的交互对象。今天有效的设计,明天未必仍然最优。
所以,“像 Agent 一样看”并不是一句口号,而是一种工作方式:
- 多观察输出
- 多实验
- 多调整工具边界
- 多重新审视原来的假设
Agent 的工具设计,不该从“我们能接多少能力”开始,而应该从“模型真正能顺畅地用什么能力”开始。
这可能才是这篇文章最值得带走的结论。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)