这篇文章结合 Claude Code 的真实迭代案例,讲清了 Agent 工具设计为什么不是“多加功能”而是“匹配模型能力边界”的持续工程。核心问题与设计视角文章把工具设计问题归结为 action space 设计:给得太少,模型做不成事;给得太多,模型决策负担上升。作者用“解数学题要配什么工具”的比喻说明:工具选择必…
转载说明:本文翻译自 Lessons from Building Claude Code: Seeing like an Agent,作者为 Thariq(源推文:2027463795355095314)。原文发布时间:2026-02-27。从构建 Claude Code 得到的经验:像 Agent 一样思考 封面图 构建一个 Agent harness 最难的部分之一,就是如何设计它的动作空间(action space)。 Claude 通过 Tool Calling 执行动作,但在 Claude API 里你可以用很多不同原语来构造工具,例如 bash、skills,以及最近加入的代码执行能力(关于在 Claude API 中进行程序化 tool calling,可以看 @RLanceMartin 的新文章)。 在这些选项都存在的情况下,你该如何给 Agent 设计工具?你是否只需要一个工具,比如 code execution 或 bash?如果你给它准备了 50 个工具,每个都对应一种潜在场景,又会怎样? 为了把自己放在模型的视角里,我会想象它面对一道很难的数学题。你会希望手里有什么工具来解题?答案取决于你自身的能力。 纸笔是最基础的配置,但你会受限于手算能力。计算器更好,但你得会用它的高级功能。最快、最强的选项是计算机,但前提是你知道如何写代码并执行代码。 这个框架对 Agent 设计很有用。你要给 Agent 提供与其能力形状匹配的工具。那你怎么知道它到底擅长什么?去观察、读它的输出、做实验。你要学会“像 Agent 一样看问题”。 下面是我们在构建 Claude Code 的过程中,通过持续观察 Claude 总结出的一些经验。提升 Elicitation 能力与 AskUserQuestion 工具 配图 在设计 AskUserQuestion 工具时,我们的目标是提升 Claude 的提问能力(通常称为 elicitation,即需求澄清/信息引导)。 Claude 当然可以直接用纯文本提问,但我们发现用户回答这些问题往往会花掉不必要的时间。我们能不能降低这部分摩擦,让用户和 Claude 之间的沟通带宽更高?尝试 #1 - 改造 ExitPlanTool 我们第一个尝试是在 ExitPlanTool 里新增参数,把问题数组和计划一起输出。这是实现成本最低的方案,但它让 Claude 困惑了,因为我们在同一次调用里同时要求“给计划”和“给关于计划的问题”。如果用户的回答和计划冲突怎么办?Claude 需要再调用一次 ExitPlanTool 吗?我们需要别的方案。 (关于我们为什么做 ExitPlanTool,可以看这篇 prompt caching 文章)尝试 #2 - 调整输出格式 接着我们尝试改写 Claude 的输出指令,让它输出一种稍作修改的 markdown 格式来提问。比如,让它输出一组带备选项(括号中)的要点式问题。这样我们可以再把这些问题解析并渲染成 UI 给用户。 这个方案是我们当时能做的最通用改动,而且 Claude 看起来也能比较好地按要求输出,但它不稳定。Claude 可能会追加多余句子、漏掉选项,或者直接换一种格式。尝试 #3 - AskUserQuestion 工具 配图 最终我们落地了一个可在任意时刻调用的工具,并在 plan mode 中特别鼓励 Claude 使用它。工具触发后,我们会展示一个弹窗来承载问题,并阻塞 agent loop,直到用户回答。 这个工具让我们能够稳定地要求 Claude 产生结构化输出,也帮助我们确保 Claude 会给用户多个选项。它还让用户能做更多组合式用法,比如在 Agent SDK 里调用,或者在 skills 里引用。 最重要的是,Claude 似乎“愿意”调用这个工具,而且输出质量也很不错。再好的工具设计,如果 Claude 不理解怎么调用,也不会真正发挥作用。 这就是 Claude Code 中 elicitation 的最终形态吗?我们并不确定。正如下一部分会看到的:对一个模型有效的方法,不一定对另一个模型同样最佳。随能力演进而更新:Tasks 与 Todos 配图 Claude Code 刚发布时,我们意识到模型需要一个 Todo 列表来保持执行轨道。可以在开始时写好 Todo,然后在执行过程中逐项勾选。为此我们提供了 TodoWrite 工具,让 Claude 能写入或更新 Todo,并展示给用户。 但即便如此,我们仍经常看到 Claude 忘记自己要做什么。为了解决这个问题,我们每 5 轮插入一次系统提醒,提示 Claude 当前目标。 随着模型能力提高,它不仅不再需要这种 Todo 提醒,反而可能被它束缚。持续收到 Todo…