你的工具描述是提示词,而非 API 文档
工具描述不是文档。它是模型在每一轮对话中都会读取的 prompt,用于决定该工具是否触发以及如何触发。你不是在为对接该工具的开发者编写内容——开发者已经在 PR 中看到了 schema、类型和示例。你是在为一个从未见过这个代码库的随机读者编写内容,它在同一个上下文窗口中还拿着另外二十个工具描述,并且必须在下一次前向传播中选出一个。
大多数团队并没有意识到这一点。他们把 OpenAPI 摘要粘贴到 description 字段中,把 JSON Schema 贴在下面,然后就发布了。结果,agent 调用工具的次数过少,或者自信地调用了错误的邻近工具,又或者用了任何读过 schema 的人类都会觉得“显而易见”是错误的参数来调用正确的工具。团队责备模型,但模型读取的正是一字不差的你写的内容。
最近一项对 103 个生产环境 MCP 服务器中的 856 个工具进行的审计发现,97.1% 的工具描述至少包含一种质量异味(quality smell),56% 的工具未能清晰说明其用途。这不只是某一个代码库中的小众问题,而是 2026 年工具界面的默认状态。当研究人员在受控条件下对描述进行变异测试, 修复了准确性和功能性的“异味”后,仅单次更改就使工具选择的结果波动了 8-12 个百分点。在多个服务器暴露功能等效工具的竞争环境中,符合标准的描述达到了 72% 的选择概率,而基准概率仅为 20%——这 3.6 倍的差距完全是由文案决定的。
文档型描述的三大症状
在修复任何问题之前,你必须识别出生产环境追踪记录(traces)中“文档型描述”的样子。失败模式主要分为三类,它们都指向描述本身,而非模型。
调用不足(Undercalling) 是最隐蔽的失败。工具就在那里,情况也需要它,但 agent 却没有调用。相反,agent 会根据其参数化知识即兴创作答案、幻觉出一个结果,或者向用户询问一个本来该由工具解决的澄清问题。追踪记录中的特征是:推理 token 提到了工具的一般主题领域(“用户想要天气”),但没有指名工具或尝试调用。当描述只是一个名词短语——如“天气服务集成”——而不是模型可以与用户意图进行模式匹配的触发条件时,就会发生这种情况。
自信的误用(Confident misuse) 表现得更明显,代价也更高。Agent 调用了工具,但参数是任何读过文档的人类都绝不会给出的。格式错误的日期范围、工具期望 IANA 时区标识符时给出的城市名称、包含模型为了满足未明确定义的 string 类型而自创的内部转义序列的查询字符串。这是“仅有 schema 的描述”的典型症状:模型看到 type: "string",然后填充了一个看起来最合理的数值。Schema 约束了结构,而非语义,而描述在确定语义方面毫无作为。
错误工具选择(Wrong-tool selection) 是最令人尴尬的失败,因为它看起来像是模型不该犯的阅读理解错误。存在两个相邻的工具——如 get_user 和 get_user_profile,或 search_issues 和 list_issues——而模型选错了。函数调用排行榜的基准测试工作显示,这种模式分布并不均匀;较小的模型和处于上下文压力下的模型会进行激进的关键词匹配。在测试的八个模型中,有五个只要 prompt 中出现“天气”一词就会调用 get_weather,即使被明确告知不要检查天气也是如此。具有重叠动词和对象的相邻工具是纯 API 文档无法拆解的地雷,因为文档是孤立地描述工具的。而模型是把它们放在一起读的。
将工具描述视为 Prompt:四个招式
将工具描述视为 prompt 意味着借鉴你已经应用于系统提示词(system prompt)的四种技术,并将它们应用于每一个工具规范。
招式 1:以触发条件而非功能开头。 API 文档的读者想知道端点的作用。模型则想知道何时调用它。将“从履行数据库中检索订单状态”替换为“当用户询问特定订单的当前状态、发货进度或查询信息时,请使用此工具。需要订单 ID(格式:ORD-XXXXXX)。”第一个版本描述了工具。第二个版本描述了模型即将做出的决策。该决策正是描述的用途所在。
招式 2:包含具体的调用示例。 提供输入示例是提高工 具描述质量最有效的手段,特别是对于具有嵌套参数、可选字段或格式敏感输入的工具。不是 schema,而是示例。{"order_id": "ORD-847291", "include_items": true} 对有效参数范围的引导作用比三段文字描述还要大。Anthropic 关于为 agent 编写工具的指南明确指出了这一点:具体的例子有助于处理 schema 无法表达的边界情况,例如可选参数通常应该包含还是省略。
招式 3:编写反面示例和同类工具区分。 这是 API 文档停止而 prompt 开始的地方。如果你的描述只说明工具的作用,模型就无法知道什么时候不使用它。添加一个明确的“不要将此用于 X”部分,指向处理 X 的同类工具。list_issues 的结尾应该是这样的:“不要用于通过 ID 获取单个 issue——请使用 get_issue;不要用于搜索 issue 内容——请使用支持全文查询的 search_issues。”对于一个大脑中同时装着这三个规范的人类读者来说,这感觉很冗余。但对于以有限的注意力串行读取描述的模型来说,每一次区分都大有裨益。
招式 4:在描述中说明输出形状,而不只是在 schema 中。 Agent 的下一个工具调用取决于当前调用的返回结果。如果模型无法从描述中预测输出形状,它就会过度获取信息、调用第二个工具来重新获取已经拥有的信息,或者因为无法判断响应将包含什么而截断推理。一行简短的“返回一个包含 status (enum: shipped, pending, delivered)、estimated_delivery (ISO 日期或 null) 和 tracking_url (字符串或 null) 的对象” 抵得上几十次失败的工具循环。
你真正需要的评估框架
只有当你像迭代提示词(Prompt)一样迭代描述时,将描述视为提示词的做法才会有回报——你需要一个足够紧密的评估循环,以便在几分钟内就能让描述的更改产生可衡量的增量。大多数团队都没有这种机制。他们有针对工具逻辑的单元测试,以及几个手动运行的演示场景。这种设置可以捕捉到损坏的 Schema,但无法捕捉到在 12% 的相关查询中会让 Agent 陷入错误工具“兔子洞”的描述。
这个框架有三层,你需要全部三层才能自信地进行迭代。
第一层是针对描述的评估集。对于每个工具,你需要收集 20–50 个本应触发该工具的用户查询,再加上 20–50 个本应触发相邻工具或根本不触发任何工具的查询。这些不是你产品演示中的理想路径场景。它们是那些凌乱、描述不充分、关键词相近的查询,正是这些查询暴露了工具选择的失败。你需要从三个维度对每次运行进行打分——是否触发了正确的工具、是否触发了错误的工具、模型是否在未触发任何工具的情况下捏造了答案——并分别追踪这些数字。将它们合并成一个单一的准确率分数会掩盖最需要暴露的失败模式。
第二层是竞争上下文评估。真实的 Agent 在其系统提示词中持有数十个工具。一个孤立来看非常出色的描述,可能会在竞争中败给旁边一个触发词略微更强的描述。在运行评估时,你应该加载完整的工具目录,而不仅仅是被测试的工具。关于 MCP 服务器在竞争环境下的研究表明,随着目录的增长,描述得好的工具与描述得差的工具之间的差距会拉大——描述不仅是在与用户的意图竞争,还在与上下文中的每一个其他描述 竞争。
第三层是生产环境追踪采样器。对实际的 Agent 运行进行采样,按选定的工具分组,并标记出模型推理与所调用工具不匹配的运行记录。这是发现你未曾预料到的失败模式的唯一方法。你在这里发现的模式将成为下一轮评估的查询,你在这里完善的描述将成为系统的下一个版本。生产环境是你的评估框架永远在追逐的语料库。
预算与 Token 的权衡
将工具描述像提示词一样编写,最直接的反对理由是成本。更长的描述在每一轮都会消耗更多的输入 Token,而现代 Agent 会在上下文中加载数十到数百个工具。从表面上看,这笔账看起来很糟糕:40 个工具每个 50 Token 的描述是 2,000 Token;而每个 200 Token 的描述则是 8,000 Token,并且在多轮对话的每次前向传播中都会重复。
一旦你考虑到失败的成本,计算方式就会改变。一次触发重试的错误工具调用会烧掉整整一次工具调用的 Token,加上模型为了修复错误而进行的任何推理。一个用户必须纠正的幻觉答案既消耗了对话轮次,又消耗了用户信任。关于增强 MCP 工具描述的研究发现,更好的描述将任务成功率的中位数提高了 5.85 个百分点,部分目标完成率提高了 15.12%——但在某些任务上也增加了 67% 的执行步骤,所以这种权衡是真实存在的,且取决于方向。正确的做法不是“让每个描述都变长”,而是“让那些关乎最高风险决策的描述变得详细,让那些简单、明确的工具描述保持简洁”。你的评估框架会告诉你哪个是哪个。
Prompt 缓存(Prompt caching)是这个方程的另一半。如果你的工具描述位于一个稳定的前缀中,该前缀可以跨轮次和跨用户缓存,那么长描述的单次请求成本将趋近于零,而质量收益却能持续存在。那些尚未将工具目录移动到缓存前缀中的团队,在每次请求中都在支付全额代价,并且对经济效益有着扭曲的看法。将工具列表移动到缓存友好的位置,通常比缩短单个描述是更高杠杆的干预手段。
组织架构的转变
更深层的变化是将工具描述视为自有的资产,而不是样板代码。当一个工具被构建时,API 团队编写端点和 OpenAPI 规范。而调用该端点的模型的提示词,应该由负责 Agent 体验的人拥有——这通常是不同的团队,有着不同的审核标准。今天,大多数组织要么让 API 团队的文档字符串(Doc string)渗入到工具描述中,要么让 Agent 团队在不告知 API 团队的情况下重写描述,随着时间的推移,由于端点的更改,这会导致描述发生偏离。
应该将工具描述与提示词一起进行版本管理,而不是与端点一起。像审查提示词更改一样审查描述更改——通过评估运行,而不是关注语法的代码审查。当端点更改时,强制进行描述审查;当描述更改时,强制进行提示词回归运行。评估框架是强制函数;没有它,描述会发生偏离,直到发生生产事故才会有人注意到。
这个简单的重新构思就是整个核心论点:你的工具描述是模型读取的提示词的一部分,你应用在系统提示词上的每一项提示词工程规范——清晰度、具体的例子、反例、消歧、针对评估的迭代——都适用于它们。内化了这一点 的团队交付的 Agent 能够更频繁地以正确的参数调用正确的工具。而那些继续编写 OpenAPI 摘要的团队交付的 Agent,在演示中看起来不错,但在追踪记录中却表现糟糕。
- https://www.anthropic.com/engineering/writing-tools-for-agents
- https://arxiv.org/html/2602.14878v2
- https://arxiv.org/html/2602.18914
- https://apxml.com/courses/building-advanced-llm-agent-tools/chapter-1-llm-agent-tooling-foundations/tool-specifications-descriptions
- https://huggingface.co/blog/kelseye/general-fc
- https://arxiv.org/html/2411.13547v2
- https://gorilla.cs.berkeley.edu/leaderboard.html
- https://blog.quotientai.co/evaluating-tool-calling-capabilities-in-large-language-models-a-literature-review/
- https://www.llamaindex.ai/blog/building-better-tools-for-llm-agents-f8c5a6714f11
- https://community.openai.com/t/prompting-best-practices-for-tool-use-function-calling/1123036
