构建 Claude Code 的经验教训:像智能体一样观察

发布于:2026-4-1|最后更新: 2026-4-2|
Created time
Apr 2, 2026 05:11 PM
category
library
date
Apr 1, 2026
status
Published
icon
password
slug
for-building-claude-code-less-is-more
summary
构建智能体框架时,设计动作空间与工具匹配至关重要,需通过观察和实验不断优化智能体的能力与工具使用。
tags
Claude
工程实践
type
post

Image
构建智能体框架,最难的部分之一就是设计它的动作空间
Claude 通过工具调用(Tool Calling)来执行操作。在 Claude API 中,可以使用 bash、技能(Skills)以及近期推出的代码执行(Code Execution)等原语来构建工具(更多关于程序化工具调用的内容,可参阅 @RLanceMartin 的文章)。
为了理解模型的"思维方式",我喜欢用一个类比:想象你正在解一道数学难题,你会希望有什么工具?这取决于你自己的能力水平——
  • 纸笔是最低配置,但手动计算会拖慢你。
  • 计算器会更好,但你需要知道怎么用高级功能。
  • 电脑是最快、最强大的选择,但前提是你得会写代码、会执行代码。
这是一个很实用的智能体设计框架:给它与其能力相匹配的工具。但你怎么知道它的能力边界在哪里?你需要保持关注,仔细阅读它的输出,不断做实验——学会像智能体一样去观察
以下是我们在构建 Claude Code 的过程中,通过观察 Claude 总结出的一些经验教训。

改进启发式引导与 AskUserQuestion 工具

Image
在构建 AskUserQuestion 工具时,我们的目标是提升 Claude 的提问能力(通常称为"启发式引导",Elicitation)。
Claude 当然可以直接用纯文本提问,但我们发现回答这类问题往往很费时间。如何降低用户的回答成本、提高沟通效率?我们前后尝试了三种方案。
尝试 #1 — 修改 ExitPlanTool
第一种方法是在 ExitPlanTool 中新增一个参数,让它在输出计划的同时附带一组问题。这实现起来最简单,但结果是让 Claude 陷入了困惑——它需要同时处理"计划"和"关于计划的问题"两件事。如果用户的回答与计划冲突了怎么办?Claude 是否需要调用两次 ExitPlanTool?这条路走不通,我们需要换思路。
关于我们为什么要做 ExitPlanTool,可以在提示词缓存那篇博文中了解更多背景。
尝试 #2 — 修改输出格式
接下来,我们尝试调整 Claude 的输出指令,要求它用一种特定的 Markdown 格式来提问——比如输出一个带括号备选项的要点列表,然后我们解析这些内容并在 UI 中呈现给用户。
这是适用性最广的调整方式,Claude 看起来也能处理,但效果并不稳定:它时常会附加多余的句子、漏掉选项,或者干脆用一种完全不同的格式输出。
尝试 #3 — AskUserQuestion 工具
Image
最终,我们决定将这个能力封装成一个专属工具,让 Claude 可以随时调用,并在规划模式下特别引导它使用。工具触发时,会弹出一个模态框展示问题,同时暂停智能体循环,等待用户回答。
这个工具的好处是多方面的:
  • 可以引导 Claude 输出结构化内容,并确保它为用户提供多个备选项;
  • 用户可以组合使用,比如在 Agent SDK 中调用它,或在技能中引用它;
  • 最关键的是,Claude 很喜欢调用它,输出效果也很好。再好的工具,如果模型不知道怎么用,也是白搭。
当然,这是否就是 Claude Code 启发式引导的终态?我们也说不准。正如下一个例子所示,对一个模型有效的方案,对另一个模型来说未必是最优解。

随能力提升而更新:任务与待办事项

Image
Claude Code 最初发布时,我们意识到模型需要一个待办事项列表来持续追踪进度。为此,我们提供了 TodoWrite 工具,让 Claude 在开始时写下任务清单,并在执行过程中逐项勾选。
但即便如此,Claude 还是经常"忘事"。为了解决这个问题,我们每 5 轮对话就插入一次系统提醒,告知它当前的目标。
随着模型能力的不断提升,以前必要的工具,现在可能反而成了束缚。持续重新审视"到底需要哪些工具"这个假设,至关重要。这也是为什么最好只支持一小批能力相近的模型——变量太多,就很难判断工具设计的优劣。

设计搜索界面

对 Claude 而言,用于构建上下文的搜索工具是一套特别重要的能力。
Claude Code 刚发布时,我们用 RAG 向量数据库来检索上下文。RAG 功能强大且速度快,但它需要索引和配置,在不同环境下稳定性也参差不齐。更关键的是,上下文是"喂"给 Claude 的,而不是它主动去找的。
但如果 Claude 可以搜索网页,为什么不能搜索你的代码库?于是,我们为它提供了 Grep 工具,让它可以自主搜索文件、自己构建上下文。
我们观察到一个清晰的规律:Claude 越聪明,只要工具合适,它构建自身上下文的能力就越强。
在引入 Agent Skills 时,我们将这种思路正式化为"渐进式披露"(Progressive Disclosure)——让智能体通过主动探索,逐步发现所需的上下文。Claude 可以读取技能文件,而这些文件又可以递归引用其他文件。事实上,"教 Claude 如何搜索"本身就成了一种常见的技能用法,比如教它如何调用 API 或查询数据库。
一年时间里,Claude 从几乎无法自主构建上下文,进化到了能跨多层文件进行嵌套搜索、精准定位所需信息。渐进式披露,如今已成为我们在不增加新工具的前提下扩展智能体能力的常用手段。

渐进式呈现:Claude Code 指南智能体

Claude Code 目前拥有约 20 个工具,我们一直在反思:真的需要这么多吗?每增加一个工具,都会给模型带来额外的认知负担,因此添加新工具的门槛必须足够高。
有一个问题我们注意到了:Claude 对 Claude Code 自身的使用方法了解不足。如果你问它如何添加 MCP、或某个命令的作用,它答不上来。
我们本可以把这些信息直接塞进系统提示词——但大多数用户很少问这类问题,这样做只会制造上下文噪音,干扰 Claude Code 的核心任务:写代码。
于是我们再次选择了渐进式披露。第一步,给 Claude 一个文档链接,让它按需加载搜索——虽然有效,但 Claude 经常为了找一个答案而加载大量无关内容。
最终方案是构建一个 Claude Code 指南子代理(Subagent)。当你询问关于 Claude Code 自身的问题时,主智能体会被引导调用这个子代理;子代理拥有完整的搜索指令和文档定位逻辑,能够精准返回所需内容。
虽然还不完美(Claude 被问及自我配置时偶尔仍会困惑),但已经比之前好得多——我们在不新增工具的情况下,扩展了智能体的操作空间

这是一门艺术,而非科学

如果你期待一套放之四海皆准的规则,恐怕要让你失望了。为模型设计工具,既是科学,也是艺术。 它取决于你使用的模型、智能体的目标,以及它所运行的环境。
多做实验,多看输出,多尝试新思路。学会像智能体一样去观察。
构建 Claude Code 的经验教训:我们如何使用"技能"(Skills)构建 Claude Code 的经验教训:提示词缓存(Prompt Caching)