跳到正文
北京时间
原文
Anthropic:Claude.dev 开发者博客· Thariq Shihipar·· 2026-04-10精选AI 评分64

Anthropic 工程师解析 Claude Code 工具设计方法:像智能体一样思考

Seeing like an agent: how we design tools in Claude Code

AI 导读

Anthropic Claude Code 团队成员 Thariq Shihipar 撰文讲解如何为智能体设计工具,核心方法是观察模型能力来匹配工具形态。

推荐理由

作者以 Claude Code 团队一线实践复盘工具设计取舍,给出失败尝试与渐进式披露等可迁移方法。

正文 · AI 翻译

构建 agent harness 最困难的部分之一就是构造它的工具。

Claude 完全通过 tool calling 来行动,但在 Claude API 中,可以用 bash、skills 和 code execution 等原语以多种方式构造工具。(你可以在 @RLanceMartin 的新文章中了解更多关于 Claude API 上程序化工具调用的内容)。

那么,你该如何设计你的 agent 的工具呢?是给它一个像 bash 或 code execution 这样的通用工具?还是给它五十个专用工具,每个用例一个?

要设身处地站在模型的角度思考,想象你被给了一道困难的数学题。为了解出它,你会想要哪些工具?这取决于你自己的技能水平!

纸是最低限度的,但你会受限于手动计算。计算器会更好,但你需要知道如何操作那些更高级的功能。最快、最强大的选择是计算机,但你必须知道如何使用它来编写和执行代码。

这是一个设计你的 agent 的有用框架。你想给它一些与它自身能力相匹配的工具。但你怎么知道那些能力是什么呢?你去观察、阅读它的输出、做实验。你学会像 agent 一样去看。

如果你在构建一个 agent,你会面临和我们一样的问题:何时添加一个工具,何时移除一个工具,以及如何区分两者。以下是我们构建 Claude Code 时回答这些问题的方式,包括我们最初在哪里做错了。

用 ASKUSERQUESTION 工具改进引导

Diagram titled "Finding the sweet spot": a spectrum from "no structure" to "too rigid". Modified markdown output sits near "no structure" (free but messy, hard to format). An ExitPlanTool parameter sits near "too rigid" (the plan is already formed, so the questions come too late). The AskUserQuestion tool is highlighted in the middle (structured, composable, with a clear UI surface).

在构建 AskUserQuestion 工具时,我们的目标是提升 Claude 提问的能力(通常称为引导)。

虽然 Claude 可以直接用纯文本提问,但我们发现回答这些问题感觉要花费不必要的时间。我们怎样才能降低这种摩擦,提高用户与 Claude 之间的沟通带宽呢?

尝试 1:编辑 ExitPlanTool

我们尝试的第一种方法是给 ExitPlanTool 添加一个参数,让它在计划旁边带上一组问题。这是最容易实现的修复,但它让 Claude 感到困惑,因为我们同时要求一个计划和一组关于该计划的问题。如果用户的回答与计划内容相冲突怎么办?Claude 是否需要调用 ExitPlanTool 两次?我们知道这个策略行不通,于是又回到了起点。(你可以在我们关于 prompt caching 的文章中了解更多关于我们为什么做 ExitPlanTool 的内容)

尝试 2:更改输出格式

接下来,我们尝试更新 Claude 的输出指令,让它输出一种稍作修改的 markdown 格式,用来提问。例如,我们可以让它输出一组项目符号问题,选项放在方括号里。然后我们可以解析并把这个问题格式化为给用户的 UI。

Claude 通常能生成这种格式,但并不可靠。它会附加多余的句子、丢掉选项,或者完全放弃这个结构。于是进入下一种方法。

尝试 3:AskUserQuestion 工具

The AskUserQuestion tool in the Claude Code terminal: tabs for Paradigm, Theme, Snacks, Indentation and Submit, the question "Which programming paradigm do you prefer for this project?", and numbered options: Functional, Object-Oriented, Procedural, Mixed, Type something, and Chat about this.

最后,我们决定创建一个 Claude 可以在任何时候调用的工具,但特别提示它在 plan mode 期间调用。当该工具触发时,我们会显示一个模态框来展示问题,并阻塞 agent 的循环,直到用户回答。

这个工具让我们能够提示 Claude 生成结构化输出,并帮助我们确保 Claude 给用户提供多个选项。它还为使用者提供了组合这一功能的方式,例如在 Agent SDK 中调用它,或在 skills 中引用它。

最重要的是,Claude 似乎很喜欢调用这个工具,而且我们发现它的输出效果很好。毕竟,即使设计得再好的工具,如果 Claude 不知道如何调用它,也是没用的。

这是 Claude Code 中 elicitation 的最终形态吗?我们对此表示怀疑。随着 Claude 能力越来越强,为它服务的工具也必须不断演进。下一节将展示一个案例:曾经有帮助的工具开始成为阻碍。

随能力更新:tasks 与 todos

Diagram titled "From todos to tasks": on the left, a single agent with a checklist (set up project, write tests, implement feature, deploy). An arrow labeled "models improve" points to the right, where Agent A and Agent B share tasks with dependencies: Tasks 1 and 2 are done and feed Task 3, which is in progress, followed by Task 4.

当我们首次推出 Claude Code 时,我们意识到模型需要一个 todo list 来保持正轨。Todos 可以在开始时写好,并在模型完成工作时勾选。为此,我们给 Claude 提供了 TodoWrite 工具,它可以写入或更新 Todos 并展示给用户。

但即便如此,我们仍经常看到 Claude 忘记它该做什么。为了适应这一点,我们每 5 轮插入一次系统提醒,提醒 Claude 它的目标。

随着模型改进,它们发现 To-do 列表具有局限性。收到 todo 列表的提醒会让 Claude 认为它必须坚持这个列表,而不是在意识到需要改变方向时修改它。我们还看到 Opus 4.5 在使用 subagents 方面也变得好得多,但 subagents 如何在共享的 todo 列表上协调呢?

有鉴于此,我们用 the Task tool 替换了 TodoWrite 功能。Todos 侧重于让模型保持正轨,而 tasks 则帮助 agents 相互沟通。Tasks 可以包含依赖关系、在 subagents 之间共享更新,模型也可以修改和删除它们。

随着模型能力提升,你的模型曾经需要的工具现在可能正在限制它们。不断重新审视关于需要哪些工具的先前假设非常重要。这也是为什么坚持支持一小组能力特征相当相似的模型很有用。

设计搜索界面

我们构建的最具影响力的工具,是那些让 Claude 找到自己上下文的工具。

当 Claude Code 首次在内部发布时,我们使用了 RAG:向量数据库会预先索引代码库,harness 会检索相关片段,并在每次响应前交给 Claude。虽然 RAG 强大且快速,但它需要索引和设置,并且在各种不同环境中可能很脆弱。最重要的是,Claude 是被给予这些上下文,而不是自己找到上下文。

但如果 Claude 能在网上搜索,为什么它不能也搜索你的代码库呢?通过给 Claude 一个 Grep 工具,我们可以让它自己搜索文件并构建上下文。

随着 Claude 变得更聪明,在获得合适工具的情况下,它越来越擅长构建自己的上下文。

当我们引入 Agent Skills 时,我们将渐进式披露的理念正式化,这允许 agents 通过探索逐步发现相关上下文。

Claude 现在可以读取 skill 文件,而这些文件又可以引用模型可以递归读取的其他文件。事实上,skills 的一个常见用途是为 Claude 增加更多搜索能力,比如给它关于如何使用 API 或查询数据库的说明。

在一年的时间里,Claude 从几乎无法构建自己的上下文,发展到能够跨多层文件进行嵌套搜索,以找到它所需的确切上下文。

渐进式披露现在是我们常用的一种技术,用于在不增加工具的情况下添加新功能。在下一节中,我们将解释原因。

渐进式披露:CLAUDE CODE 指南代理

Claude Code 目前有约 20 个工具,我们团队经常重新审视是否需要所有这些工具才能让 Claude 发挥最大效能。添加新工具的门槛很高,因为这会给模型多一个需要考虑的选项。

例如,我们注意到 Claude 对如何使用 Claude Code 了解得不够。如果你问它如何添加 MCP 或某个斜杠命令是做什么的,它无法回答。

我们本可以把所有这些信息都放进系统提示中,但考虑到用户很少问这些问题,这会增加上下文腐化,并干扰 Claude Code 的主要工作:编写代码。

于是,我们尝试了渐进式披露:我们给 Claude 一个指向其文档的链接,它可以在需要时加载并搜索。这确实有效,但 Claude 会把大段文档拉入上下文,只为找到一个用户本可以用一句话得到的答案。

因此,我们构建了 Claude Code 指南——一个每当用户询问 Claude Code 本身时 Claude 就会调用的子代理。该子代理在自己的上下文中进行文档搜索,遵循关于如何搜索和提取什么的详细指令,并且只交回答案。主代理的上下文保持干净。

虽然这不是一个完美的解决方案(当你问 Claude 如何设置自己时,它仍然可能会感到困惑),但我们能够在不添加新工具的情况下向 Claude 的行动空间添加内容。

像代理一样观察是一门艺术,而非科学

为你的模型设计工具既是科学,也是艺术。这在很大程度上取决于你使用的模型、代理的目标以及它所运行的环境。

我们最好的建议?经常实验,阅读你的输出,尝试新事物。最重要的是,试着像代理一样观察。

立即开始使用 Claude Code。

关于作者: Thariq Shihipar 是 Anthropic 的技术人员,从事 Claude Code 相关工作。

来源:Anthropic:Claude.dev 开发者博客 · claude.dev