像 Agent 一样思考:Claude Code 团队的工具设计哲学
解读 Anthropic 工程师 Thariq 的 Agent 工具设计经验——从三次失败到渐进式披露,Claude Code 团队如何学会"像 Agent 一样看世界"
你要给它匹配其自身能力的工具。但你怎么知道它的能力是什么?你得认真观察,阅读它的输出,不断实验。你要学会像 Agent 一样去看世界。
Thariq 是 Anthropic 工程师,Claude Code 的核心构建者之一。2 月底他在 X 上发了一篇长文,分享了构建 Claude Code 过程中关于 agent 工具设计的五个真实案例——不是理论框架,而是一线踩坑经验。这篇文章获得了 351 万次观看、209 条回复、9,691 个点赞,引发了大量高质量讨论。
构建 Claude Code 的经验:像 Agent 一样思考
构建 agent 框架最难的部分之一,是设计它的行动空间。以下是我们在构建 Claude Code 过程中,通过认真观察 Claude 所总结出的一些经验。
为了引出全文的核心问题,Thariq 用了一个很好的类比:想象你面对一道数学难题,你需要什么工具?
纸笔是最低配置——但你会受限于手动计算。计算器更好——但你得知道怎么使用高级功能。电脑最强大——但你得会写代码。
工具的选择取决于使用者的能力。给一个不会编程的人一台电脑,不如给他一个计算器。给一个程序员一个计算器,反而限制了他的发挥。
对 agent 来说也是一样。问题不是"什么工具最强大",而是"什么工具最匹配模型当前的能力"。这篇文章分享的,就是 Claude Code 团队在寻找这个匹配点的过程中踩过的坑。
以下是我从原文和社区讨论中提炼出的四个递进主题。
少即是多——工具数量的反直觉
直觉告诉我们,工具越多,agent 能力越强。但 Claude Code 团队的经验恰恰相反。
Claude Code 目前只有约 20 个工具,而且团队不断审视自己是否真的需要所有这些工具。添加新工具的门槛很高,因为这意味着给模型多了一个需要考虑的选项——每多一个工具,模型在做决策时就多一份"认知负担"。
这个发现在社区中引起了强烈共鸣。leon.M 分享了自己的实践经历:
做了一年了还在学这个。给了我们的 agent 12 个工具,发现它其实只用了 3 个。现在我们从 1 个开始,等它自己要求时再加。
Apple 的 CodeAct 研究为这个观点提供了量化支撑:单一代码执行原语(code execution primitive)在复杂任务上的表现比庞杂的专用工具集高出最多 20%。少,确实可以是多。
AskUserQuestion 工具的三次迭代是这个原则最好的案例。Claude Code 团队想提升 Claude 向用户提问的能力——虽然 Claude 可以直接用纯文本提问,但回答这些问题感觉太耗时了。怎么降低摩擦?
第一次尝试:给 ExitPlanTool 加一个参数,让它在输出计划的同时附带一组问题。结果——Claude 被搞混了。同时要求它输出计划和关于计划的问题,如果用户的回答和计划冲突怎么办?
第二次尝试:修改输出指令,让 Claude 用特定的 markdown 格式来提问,然后前端解析格式化。结果——不稳定。Claude 会额外添加句子、省略选项,或者干脆用完全不同的格式。
第三次尝试:创建一个独立的 AskUserQuestion 工具。Claude 可以在任何时候调用它,调用后弹出弹窗显示问题,阻塞 agent 循环直到用户回答。成功了。
Thariq 在原文中写了一句很有意思的话:
Claude 似乎乐于调用这个工具,而且我们发现它的输出效果很好。即使是设计得再好的工具,如果 Claude 不理解怎么调用它,也不会起作用。
phuong 敏锐地追问:"'Claude 似乎乐于调用这个工具'是这里最有趣也最缺乏解释的一句话。你是怎么检测模型对工具的'好感度'的——通过阅读 transcript 还是内部调用频率指标?如果这个启发式方法能更具体,它会改变所有人设计 agent 工具的方式。"
这个问题没有得到回答,但它指向了一个重要的直觉:工具设计的成功标准不是"人觉得合理",而是"模型理解怎么用、愿意用"。
Emeka 从企业工具开发的角度补充了一个很直接的教训:"我曾为 agent 构建工具时试图控制每一个可能的输入和输出,结果模型就是……绕过它了。省点工程量吧,信任模型能处理模糊性。"
工具会过时——能力升级后的枷锁效应
如果说"少即是多"是关于空间维度的认知,那"工具会过时"就是时间维度的教训。
曾经帮助模型的工具,随着模型进步,可能反而成为限制。
Claude Code 最初发布时,团队意识到模型需要一个待办清单来保持方向——可以在开始时写入待办事项,然后在完成工作时逐一勾选。为此他们给 Claude 提供了 TodoWrite 工具。但即便如此,Claude 经常忘记自己该做什么。
团队的应对方式是每隔 5 轮对话插入一次系统提醒,提示 Claude 它的目标是什么。
但随着模型的进步,问题反转了:模型不仅不再需要被提醒待办清单,反而觉得这些提醒是一种限制。被反复提醒待办清单让 Claude 觉得必须严格遵循清单,而不是根据需要灵活调整。 与此同时,Opus 4.5 在使用子 agent 方面有了很大提升,但子 agent 之间该如何协调共享的待办清单?
于是团队用 Task Tool 取代了 TodoWrite。两者的区别是本质性的:Todos 的作用是让模型保持正轨——像一个老板盯着员工的任务清单;Tasks 则更侧重于帮助 agent 之间进行沟通——像一个团队的协作看板。Tasks 支持依赖关系,跨子 agent 共享更新,模型还可以修改和删除它们。
从 TodoWrite → 每 5 轮提醒 → Task Tool,这是三次重新设计。 不是因为之前的设计"错了",而是因为模型已经成长了。
modi 的评论精准总结了这个现象:
因为模型不断超越工具而重新设计三次工具系统,这是正确的发展轨迹。大多数 agent 框架是为今天的模型构建的。模型一改进,脚手架就变成了限制。
这也引出了一个有趣的争议。Danny Cosson 认为 AskUserQuestion "实际上是个糟糕的设计"——它把 Claude Code 非常优雅的文本输入/文本输出模型强行套进了一个特定的交互模式,而且几乎没有好处。
但 @Toong 的反驳很有说服力:AskUserQuestion 的价值在于两点——主动权(明确告诉模型它有权提问)和状态管理(清晰地将标准文本输出与"等待用户介入"的阻塞状态区分开来)。
同一个工具,两种截然不同的评价。这恰好证明了 Thariq 结尾说的那句话:工具设计是艺术而非科学。它取决于你使用的模型、agent 的目标,以及它所处的环境。
让 Agent 自己找答案——从"喂给"到"自主搜索"
这是全文中我认为最有实用价值的部分。
Claude Code 最初使用 RAG 向量数据库来为 Claude 查找上下文。RAG 功能强大且速度快,但有两个问题:一是需要索引和配置,在不同环境中可能很脆弱;二是更根本的——这种方式是把上下文提供给 Claude,而不是让它自己去找。
团队做了一个关键转变:既然 Claude 能在网上搜索,为什么不能搜索你的代码库?通过给 Claude 提供 Grep 工具,让它自己搜索文件、自己构建上下文。
Beacon 的评论一针见血:
“渐进式披露”是被低估的洞察。大多数人把所有东西都塞进系统提示里,然后好奇为什么 agent 会搞混。按需提供信息,而不是一次性全给。
在一年时间里,Claude 从几乎无法自主构建上下文,进化到能够跨多层文件进行嵌套搜索,精准找到所需的上下文。 这个进化的关键不是给 Claude 更多信息,而是给它更好的搜索能力。
当 Claude Code 引入 Agent Skills 时,团队正式提出了**渐进式披露(Progressive Disclosure)**的概念:允许 agent 通过探索来逐步发现相关上下文。
具体的实现很优雅:Claude 可以读取 skill 文件,而这些文件又可以引用其他文件,模型可以递归地读取它们。skill 的一个常见用途就是为 Claude 增加更多搜索能力——比如给它关于如何使用 API 或查询数据库的指令。
Brian Wagner 分享了他的三层实践,和 Claude Code 的思路完全一致:
SKILL.md 保持精简(约 100 行),重度上下文放在 Claude 需要时才发现的文件里。我管它叫第三层。你们叫它渐进式披露。本质一样。
PrimeLine 甚至构建了一个量化的三层系统:JSON 配置(约 500 token)> 模式摘要(约 300 token)> 完整 markdown(约 3K token)。一个上下文路由器根据任务关键词决定加载哪一层。
这种分层策略的核心逻辑是:上下文是有限资源,边际收益递减。把所有信息一次性塞给 agent,不仅浪费 token,还会稀释真正重要的信息。按需提供,让 agent 自己决定什么时候需要更深层的细节——这才是可扩展的方案。
Claude Code Guide 子 agent 是渐进式披露的另一个巧妙应用。团队注意到 Claude 对如何使用 Claude Code 本身了解不够——如果你问它怎么添加 MCP 或某个斜杠命令是做什么的,它无法回答。
他们本可以把所有信息塞进系统提示,但用户很少问这类问题,这样做会增加上下文腐蚀,干扰 Claude Code 的主要工作:写代码。
先尝试给 Claude 一个文档链接让它自己搜索——可行,但 Claude 会把大量结果加载到上下文中来寻找正确答案。最终解决方案是构建一个专门的子 agent:Claude Code Guide。这个子 agent 有详细的搜索指令,知道怎么高效搜索文档以及返回什么内容。不增加任何新工具,却扩展了 Claude 的行动空间。
Lance Martin 在他关于 agent 设计模式的文章中提出了一个互补的视角:与其给 agent 定义几十个工具,不如给它一台电脑,让它用代码来编排工具。 Claude Code 的核心抽象就是 CLI——agent 活在你的电脑上,通过 bash 和文件系统这些基础原语来完成复杂任务。少数几个原子级工具(如 bash 工具),比庞大的工具集更灵活、更省 token。
Agent 设计模式
编程 Agent 的核心抽象是 CLI——根植于 Agent 需要访问操作系统层这一事实。
模型同理心——像 Agent 一样思考
前面三个主题——少即是多、工具会过时、让 agent 自己找答案——背后有一个共同的元方法论。Thariq 在文章开头就点明了:像 agent 一样去看世界。
这不是一套规则,而是一种思维方式。David Zhang 给它起了个名字:
我管这种能力叫模型同理心。未来所有优秀的工程师都需要这种技能。
模型同理心——不是从人类的角度设计"合理"的工具,而是从模型的角度思考它实际看到了什么、会怎么理解、会怎么使用。
Terminally Drifting 用三步精炼了每个 agent 团队都会经历的同一个教训:
1)为人类设计工具 2)模型像一只有管理员权限的浣熊一样使用它们 3)为 token 经济和可预测的副作用重新设计
"像 agent 一样思考"就是那个关键突破。
Vish 分享了他的转折体验:"我们一直在构建对人类来说合理的工具接口,然后不明白为什么 agent 总做出奇怪的选择。一旦你翻转心智模型,思考模型在工具定义中实际看到的是什么,一切都变了。"
Emeka 从企业级工具开发的角度说了同样的事:"一切默认都是人类的心智模型——Schema、字段名、流程,全都为人类阅读而优化。但对 agent 来说,这是错误的框架。"
这种"翻转心智模型"说起来简单,做起来需要不断练习。你需要认真阅读 agent 的输出——不是看它做对了什么,而是看它为什么做出某些选择、在哪里犹豫、在哪里走了弯路。这些"异常行为"往往不是模型的 bug,而是工具设计的 bug。
社区讨论中还出现了几个值得思考的补充视角。
OAIR 提出了一个盲区:所有这些工具迭代都假设 agent 是无状态的——每次会话从零开始。如果最重要的"工具"不在行动空间中,而是在关于这个代码库如何运作的持久记忆中呢? Claude Code 后来通过 CLAUDE.md 文件和 memory 系统部分回应了这个问题,但持久状态管理仍然是 agent 设计的开放难题。
Clinker 提出了另一个设计原则:优化可恢复性(recoverability)而非原始能力——显式的工具前置条件、可观察的状态和低成本的重试,往往比快速添加更多工具更有效。 这和软件工程中"让系统容错而非无错"的理念一脉相承。
范式折叠的总结最为犀利:
Action space 设计本质上是权力设计——你给 AI 什么权限,它就成为什么角色。这跟管理团队一模一样:你以为瓶颈是人的能力,其实瓶颈是你画的权限边界。
写在最后
回到 Thariq 的结语:
多做实验,阅读你的输出,尝试新方法。像 agent 一样去观察。
作为 Claude Code 的重度用户,读完这篇文章最大的感受是:那些看似"自然"的功能,背后是无数次"这样不行,换一种"的迭代。 AskUserQuestion 试了三次,TodoWrite 重新设计了三次,RAG 被 Grep 替代了。每次改进不是因为想出了更聪明的方案,而是因为认真观察了模型的实际行为。
这篇文章的副标题是 "Seeing like an Agent"——像 agent 一样看世界。但换个角度想,这其实也是所有好的工程实践的本质:不是从自己的视角出发设计系统,而是从使用者的视角出发。 只不过这次,使用者是一个 AI 模型。
未来每个构建 agent 的开发者,可能都需要掌握 David Zhang 所说的"模型同理心"。这不是什么神秘的能力,核心就是三件事:观察模型的实际行为,阅读它的输出,然后根据你看到的调整设计。
像 agent 一样去观察。
延伸阅读:
Claude Code 团队如何设计 Agent 工具
对 Thariq 长文的详细拆解分析,包括 Apple CodeAct 研究及其对 agent 工具设计的启示。
Agent 设计模式
探讨编程 Agent 的核心抽象:CLI 访问和操作系统层原语优于预定义工具列表。