让智能体选对工具的描述设计方法
文章围绕工具名称、描述和输入结构,讲解如何明确工具用途、适用条件、限制及错误恢复方式。结合自行构造的租车案例,讨论工具职责重叠、隐含调用顺序和描述自动检查。
AI 深度解读
Agent 调错工具,不一定是模型能力不够,也可能是工具根本没把使用条件交代清楚。原文用一个虚构的自行车租赁服务说明:工具描述是模型做决策的输入,名称、参数约束、调用顺序和错误提示,都应该按接口契约来设计。
最值得借鉴的是两件事:把容易误用的条件写进工具定义,再通过实际暴露给客户端的工具列表做自动检查。不过,提供的原文代码中途截断,测试结果也有待核对,不能把它直接当成可运行教程。
模型选工具时,看不到你的实现
在原文讨论的 MCP 工具选择流程里,宿主先获取 tools/list,模型根据工具定义选择工具、填写参数,宿主执行后再把结果交回来。模型不会通过这份定义看到背后的业务代码。
作者引用的 MCP 规范版本是 2026-07-28。工具定义包含唯一标识 name、面向人的展示名称 title、description、参数 JSON Schema inputSchema,以及可选的 outputSchema 和行为提示 annotations。其中,模型主要依赖名称、描述和参数 Schema,包括每个参数的说明。
所以,book 配上一句 Books a bike.,留下的空白远比看起来多:id 从哪里来,日期能不能写「下周一」,是否需要用户确认,失败后重试会不会重复预订?模型只能猜。
工具描述是模型执行任务时的输入,应该按接口契约维护。
原文转述 Anthropic 的建议:每个工具至少写三到四句话,并提到描述的小幅修改曾改善基准表现。但原文没有提供具体分数、模型和对照条件,我们能接受它的设计方向,不能据此推算收益。
好的定义,要把调用顺序和重试规则写出来
租车示例有两个站点 ostbahnhof、hafen,车型是 city、ebike、cargo。作者把模糊的 book 改成 rental_book_bike,让名称同时表达领域、动作和对象,也减少多个 MCP server 同时加载时的重名问题。
按文中引用的规范,名称允许 1 到 128 个字符,可使用字母、数字、下划线、连字符和点;Claude API 不允许点,因此作者推荐 snake_case。
下面的定义解决了最关键的几项歧义:预订上限、用户确认、ID 来源,以及重复请求的行为。
// Excerpt from src/server.ts: the booking tool
server.registerTool(
'rental_book_bike',
{
title: 'Book rental bike',
description:
'Books an available rental bike for a period of up to 14 days. ' +
'Use it only after the user has explicitly confirmed the bike and the period. ' +
'The bikeId always comes from rental_search_bikes, never make one up. ' +
'The same requestKey returns the same booking, so a retry never books twice.',
inputSchema: z.object({
bikeId: z.string().describe('ID from rental_search_bikes, e.g. "bike-hafen-01"'),
from: isoDate.describe('First rental day, YYYY-MM-DD'),
to: isoDate.describe('Last rental day, YYYY-MM-DD, same as or after "from"'),
requestKey: z.string().min(8).describe('Unique key per booking request, e.g. a UUID'),
}),
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
},
async ({ bikeId, from, to, requestKey }) => {
// ... see step 3
},
);
重点看 bikeId 的来源说明和 requestKey 的重试约定。前者告诉模型必须先调用 rental_search_bikes;后者约定同一个请求键返回同一笔预订,也就是幂等性。
但文字约定需要实现支撑。.min(8) 只检查字符串长度,不会验证 UUID,也不能保证请求键唯一。to 的描述要求不早于 from,这段字段定义本身也没有实现跨字段校验。
能由机器检查的约束,应继续放进 Schema:日期用 z.iso.date(),车型用 z.enum(),结果数量用整数及范围限制。搜索工具的 limit 是 1 到 20,默认 5;responseFormat 支持 concise 和 detailed,默认返回简短结果。
这种设计同时减少选择成本和上下文消耗。相比给每条 API 路由都包一个工具,作者建议合并常见工作流,避免 list_bikes、find_bikes、search_available_bikes 之间边界不清。原文引用的简短响应案例约用了详细响应三分之一的 token,但那不是这个租车服务的实测数据。
自动检查能挡住敷衍定义,挡不住业务错误
错误结果也是工具接口的一部分。原文区分两类错误:未知工具等协议错误通过 JSON-RPC 返回;输入或业务规则导致的执行错误,通过普通结果携带 isError: true,让模型获得纠正机会。
作者用这个辅助函数构造后一类结果:
// Errors the model can learn from: what is wrong, and how to do it right?
function toolError(message: string) {
return { content: [{ type: 'text' as const, text: message }], isError: true };
}
关键是 isError: true,而具体消息还要说明下一步。示例遇到未知站点时,会列出 ostbahnhof、hafen,要求向用户确认,不让模型继续猜。没有可用车辆则返回正常的空结果说明,建议换日期或站点。
配套检查通过 InMemoryTransport.createLinkedPair() 在内存中连接服务端和客户端,再用 client.listTools() 读取工具定义。这比只检查源码字符串更贴近宿主实际接收到的内容。
检查规则包括名称格式、rental_ 前缀、描述至少三句、出现 use 或 nutze,以及每个顶层参数都有描述。有问题就设置 process.exitCode = 1,适合放进 CI。
作者称示例测试环境为 Node.js 22 或更新版本、TypeScript SDK v2,具体使用 @modelcontextprotocol/server 和 @modelcontextprotocol/client 2.4.0、Zod 4.6、TypeScript 7.0。配置文件进一步写到 Zod ^4.6.7、TypeScript ^7.0.2、tsx ^4.23.15、@types/node ^26.6.5。安装命令使用的是 zod@4,这些版本信息也应区分看待。
验证入口是 npx tsc --noEmit、npm test、npm run check:tools。作者预期四项测试通过,检查输出 2 tools checked, no findings.。
不过,检查器只能守住形式底线:出现 use 不代表使用条件写对,名称正则也不能理解哪个词是动作。原文测试还有一个具体疑点:简短定义的断言写了 5 项发现,但按所示句子拆分表达式,句点后的空字符串也可能被计入,相关逻辑需要核对。
我的判断
我赞成把描述、Schema 和错误反馈一起设计。单独润色一段介绍,解决不了参数非法、调用顺序错误和重复写入。相较于只在系统提示词里解释业务规则,把规则放到相应工具旁边,更方便维护和审查。
但这篇提供的是设计经验和示例测试,没有给出完整的 Agent 任务成功率对照。三到四句话是写作建议,不是稳定性的保证;工具合并到什么程度,也要看任务边界,不能只追求数量少。
annotations 同样不能承担安全保证。readOnlyHint、destructiveHint、idempotentHint、openWorldHint 都是提示。写上 idempotentHint: true,不会自动获得幂等实现;要求用户确认,也不等于服务端已经强制验证授权。
提供的原文在预订处理函数中途截断,结尾关于测试发现错误的叙述也未完成。因此,14 天限制、完整时段冲突检查等逻辑无法核实。可见的存储实现使用内存 Map,搜索也只检查某一天,尚不足以支撑生产环境的并发预订。
它适合拿来审视工具契约,完整可运行性仍需自行验证。
能拿来做什么
- 给现有 Node MCP 工具做一次定义审查,逐个补齐用途、使用条件、限制和参数来源,优先处理写入类工具。
- 用 Zod 固化日期、枚举和数量范围,再给参数补上示例;跨字段关系与业务规则另外验证,避免文字承诺超过实际约束。
- 在 CI 中读取真实工具列表检查基础质量,同时为错误恢复和重复请求保留行为测试,别把句数达标当成验收完成。
- 调查 AI 编程中的误调用时,先看模型收到的工具定义和错误结果,确认它是否获得了正确 ID、调用前提与修复路径。