type
Post
status
Published
date
May 19, 2026
slug
agent44
summary
tags
Agent
category
icon
password
一、核心结论
在 Agent 系统里,工具描述不是写给人看的 API 文档,而是写给模型看的“决策边界”。
传统 API 文档强调“这个函数能做什么”,因为调用者是程序员,程序员会根据业务上下文自己判断是否调用。但 Agent 工具调用的调用者是 LLM,它需要从自然语言任务中判断:
现在需不需要调用工具?该调用哪个工具?应该传哪些参数?工具结果回来后,下一步继续调用工具还是结束?
因此,工具描述中最重要的不是“能做什么”,而是“什么时候该用、什么时候不该用、和哪些工具相比应该优先/避免使用”。
Anthropic 的 Claude 工具定义文档也明确要求工具描述说明工具做什么、何时使用和不使用、参数含义、限制与行为细节,并建议复杂工具至少写 3-4 句话;Claude API 会把这些工具定义构造成特殊 system prompt,让模型基于这些描述决定工具调用。(Claude Platform)
二、为什么“什么时候该用”比“能做什么”更重要?
1. Agent 面临的是“工具选择问题”,不是“函数调用问题”
OpenAI 的 function calling 流程本质上是:请求时给模型一组工具,模型判断是否需要工具并生成 tool call,应用侧执行工具,再把结果返回给模型继续生成最终答案。(OpenAI开发者)
也就是说,模型不是直接执行函数,而是在一堆候选工具中做选择。这个选择过程更像路由:
在这个流程里,“工具描述”影响的是 D、F、G 三个关键节点:是否调用、调用哪个、参数怎么填。
如果工具描述只写:
Search documents.
模型只能知道它“能搜索文档”,但不知道:
是搜索本地知识库,还是搜索网页?是适合精确文件名,还是适合语义问题?找不到时是否应该继续 web search?和grep_code、read_file、web_search的边界是什么?
这就是为什么很多 Agent 会出现“工具调用幻觉”:不是模型不会调用工具,而是工具边界没有被描述清楚。
2. “能做什么”往往高度重叠,“什么时候用”才提供区分度
在真实 Agent 系统里,工具经常有重叠能力。例如:
工具 | 都“能做什么” | 真正应该区分的“什么时候用” |
read_file | 读取内容 | 已知具体文件路径时用 |
grep_code | 查找内容 | 搜索类名、函数名、关键词时用 |
glob_files | 找文件 | 不知道路径但知道文件模式时用 |
rag_search | 搜索知识 | 查询内部文档、历史知识时用 |
web_search | 搜索知识 | 查询当前事件、外部实时信息时用 |
task_agent | 让子 Agent 工作 | 多步骤、开放式探索、需要并行调研时用 |
如果描述只写“读取文件”“搜索代码”“搜索知识”,模型很难知道该选哪个。Anthropic 在高级工具使用文章中提到,工具数量变多时,不仅会产生 token 成本,常见失败还包括工具选择错误和参数错误,尤其是工具名称相似时。(Anthropic)
成熟项目通常会把“什么时候不用”写得非常具体。OpenCode 的
Task 工具描述里不仅说它可以启动子 Agent 处理复杂多步骤任务,还明确写了不该用它的场景:如果只是读取具体文件路径,应使用 Read 或 Glob;如果搜索类定义,应使用 Grep;如果只在 2-3 个文件内找代码,应使用 Read。(GitHub)这类描述的核心价值不是解释功能,而是帮助模型减少误选。
3. 工具描述其实是 Agent 的“策略层”
MCP 规范中,工具被设计为 model-controlled:模型可以根据上下文和用户提示自动发现并调用工具;但出于安全考虑,应用应让用户看清暴露给 AI 的工具,并在操作时提供确认机制。(Model Context Protocol)
这意味着工具描述承担了三种角色:
第一,它是 capability spec:告诉模型工具能做什么。第二,它是 routing policy:告诉模型什么时候该选它。第三,它是 safety hint:告诉系统和用户这个工具是否只读、是否有副作用、是否需要确认。
OpenAI Apps SDK 对 MCP 工具要求标注
readOnlyHint、openWorldHint、destructiveHint 等注解,用来描述工具可能产生的影响,例如是否只读、是否可能写入外部世界、是否有破坏性副作用。(OpenAI开发者)所以,生产级 Agent 里工具描述不只是“注释”,而是“行为约束”。
三、从成熟项目看工具描述怎么写
1. Claude / Anthropic:工具描述要写成“新员工交接文档”
Anthropic 的工具设计文章提出,工具描述会进入 Agent 上下文,因此会共同影响工具调用行为;写工具描述时应像给团队新人解释工具一样,把专业查询格式、术语、资源关系、输入输出都显式化,并用严格数据模型减少歧义。(Anthropic)
它还强调工具实现和描述应该一起优化:
工具数量过多会增加误选风险;工具返回结果应只包含高信号信息;大结果应支持分页、过滤、截断;错误响应应告诉 Agent 如何修正参数,而不是只返回晦涩错误码。(Anthropic)
这背后的思想是:工具不是越原子越好,而是要让模型“容易选、容易传参、容易从结果继续推理”。
2. OpenCode:在工具描述里直接写 When to use / When NOT to use
OpenCode 的
TodoWrite 工具描述是一个很典型的例子。它不是只说“创建任务列表”,而是明确规定:当任务需要 3 个以上不同步骤、工作非平凡且需要规划、用户提供多个任务、或新指令到来时应主动使用;当任务是单个简单任务、纯信息问答、或任务跟踪没有组织价值时跳过。(GitHub)这说明成熟 Agent 工具描述会把调用条件写成可判定规则,例如:
3+ distinct stepsnon-trivial workmultiple taskspurely informationaltracking adds no value
这类规则对 LLM 非常友好,因为模型可以把用户请求映射到这些自然语言条件上。
OpenCode 的
websearch 工具描述也明确写了使用场景:用于访问知识截止日期之后的信息、当前事件和近期数据,并要求搜索最新信息时使用当前年份。(GitHub)这就是“何时使用”的典型设计:它不仅说明“能搜索网页”,还告诉模型“什么时候必须从静态知识切换到动态检索”。
3. OpenClaw:先区分 tool、skill、plugin,再控制模型能看到什么
OpenClaw 文档把工具、技能和插件分得很清楚:tool 是模型可调用的 typed function,用于读取数据、改文件、发消息、调用 provider 或操作外部系统;skill 是加载进 prompt 的指令包,用于提供可复用工作流或约束;plugin 则用于给运行时增加新能力、凭证、生命周期 hooks 或安装包。(OpenClaw)
这对工具描述设计很重要。很多团队会把“工作流说明”也塞进工具描述,导致工具描述越来越长。更合理的做法是:
工具描述负责“能力边界与调用条件”;Skill 负责“流程、规范、风格、检查清单”;Plugin 负责“新增能力、凭证、运行时生命周期”。
OpenClaw 还说明,模型只能看到通过 active profile、allow/deny policy、provider restrictions、sandbox state、channel permissions 和 plugin availability 过滤后的工具。(OpenClaw)
也就是说,工具描述不是唯一控制层,还应配合权限策略、沙箱和可见性控制。
四、坏工具描述与好工具描述对比
反例:只写“能做什么”
这个描述的问题是:
没有说明搜索范围:本地知识库、项目文件、网页还是数据库?没有说明什么时候该用:事实查询、语义检索、精确路径、代码搜索是否都用它?没有说明什么时候不用:已知文件路径时是否应该直接 read?没有说明参数策略:query 应该是自然语言、关键词、文件名,还是 SQL-like 表达式?没有说明结果为空怎么办:换关键词、扩大范围,还是直接告诉用户找不到?
正例:写清“路由边界”
这段描述真正有价值的不是第一句,而是后面的使用条件、排除条件、替代工具和失败恢复策略。
五、工具描述设计的 10 条关键原则
原则 1:先写“用户意图触发器”,再写功能
推荐格式:
当用户想要……时使用当任务需要……时使用当信息来源属于……时使用
例如:
Useweb_searchwhen the answer depends on current or recently changed public information.
比下面这种更有用:
Search the web.
因为前者告诉模型“何时需要外部实时信息”。
原则 2:必须写 “When NOT to use”
“什么时候不用”比“什么时候用”更能降低误调用。
推荐写法:
Do NOT use this tool when the user provides an exact file path; useread_file.Do NOT use this tool for current events; useweb_search.Do NOT use this tool for destructive operations unless the user explicitly asks and approval is granted.
OpenCode 的
Task 工具就是这种模式:它明确列出不该用 Task 的场景,并指出替代工具 Read、Glob、Grep。(GitHub)原则 3:写清和相邻工具的边界
工具描述不能孤立写,要按“工具族”设计。
例如在代码 Agent 里,
read_file、glob_files、grep_code、task_agent 的边界可以这样设计:工具 | 使用条件 |
read_file | 已知具体文件路径 |
glob_files | 不知道具体路径,但知道文件模式 |
grep_code | 搜索类名、函数名、字符串、符号 |
task_agent | 多步骤、开放式、需要自主探索 |
如果不写这种边界,模型会倾向于调用“看起来最强”的工具,比如总是开子 Agent 或总是 web search,导致成本、延迟和错误率上升。
原则 4:参数描述要写“语义”,不是只写类型
坏参数描述:
好参数描述:
原则 5:写清数据范围、时效性和可信边界
RAG / 搜索类工具尤其要写清:
数据源是什么是否包含最新数据是否包含用户私有数据是否可能不完整结果是否需要引用来源什么时候应切换到 web search
例如:
这可以避免模型把静态知识库当作实时数据库使用。
原则 6:把副作用和权限写进描述,但不要只依赖描述
对于会写文件、发消息、删数据、付款、改配置的工具,要写清:
是否只读是否会修改外部系统是否不可逆是否需要用户确认是否可以批量操作是否允许自动重试
OpenAI Apps SDK 要求 MCP 工具提供 impact annotations,例如
readOnlyHint、openWorldHint、destructiveHint,用于描述工具影响范围。(OpenAI开发者)但要注意:描述和 annotation 只是提示,真正的安全必须由执行层强制。OpenCode 的
write 工具在执行写文件前会走 permission ask,并在写入后触发 LSP diagnostics,把错误信息返回给模型继续修复。(GitHub)原则 7:工具返回结果也要服务下一步决策
工具描述不能只管调用前,还要约束调用后结果。
Anthropic 建议工具返回高信号信息,避免把大量低层字段塞回上下文;对于大结果,应支持分页、范围选择、过滤、截断,并在截断或错误时给出可操作提示。(Anthropic)
例如搜索工具返回:
比返回一大段无结构文本更利于 Agent 继续规划。
原则 8:为复杂工具提供 examples,但不要用 examples 替代描述
Anthropic 文档明确说,清晰描述最重要;复杂输入、嵌套对象、格式敏感参数可以补充
input_examples。(Claude Platform)适合加 examples 的场景:
参数很多有嵌套对象有日期、金额、时区、过滤表达式有 mutually exclusive 参数有复杂枚举组合
但 examples 不能替代规则。模型需要知道为什么这个例子适用,而不是只模仿形状。
原则 9:工具越多,越需要命名空间和动态发现
当工具数量很多时,把所有工具定义一次性塞进上下文会带来 token 成本和选择混乱。Anthropic 的 Tool Search Tool 就是为这个问题设计的:不是预加载所有工具,而是让 Claude 按需搜索工具;其文章提到大规模 MCP 工具定义可能消耗数万到十几万 tokens,而动态工具搜索可以只加载当前任务需要的工具。(Anthropic)
这意味着工具描述还要适合“被搜索”。工具名和描述里要包含可检索关键词:
比下面这种更容易被 Tool Search 命中:
原则 10:用评测驱动工具描述迭代
工具描述不是一次写完的。应把工具调用日志纳入评测:
评测维度 | 观察问题 |
工具选择准确率 | 模型是否选错工具 |
参数有效率 | 参数是否缺失、格式错误、语义错误 |
过度调用率 | 明明可直接回答却调用工具 |
漏调用率 | 需要工具却直接编答案 |
多步成功率 | 工具结果回来后是否能继续正确行动 |
安全拦截率 | 高风险工具是否正确请求确认 |
成本/延迟 | 是否调用过大、过多、过慢工具 |
一篇 2026 年关于 MCP 工具描述质量的研究指出,MCP Agent 依赖自然语言工具描述来选择工具和传参;如果描述缺陷、过短或误导,模型可能选错工具、传错参数或产生不必要步骤。该研究还发现,在 856 个 MCP 工具描述中,97.1% 至少存在一种“description smell”,常见问题包括缺少使用指南、未说明限制、参数不透明等;增强描述后任务成功率有统计显著提升,但也带来 token 成本权衡。(arXiv)
六、推荐的工具描述模板
生产环境可以把每个工具描述统一成下面结构:
七、一个更完整的工具描述示例:RAG 搜索工具
这个描述覆盖了:
什么时候用:内部文档、PDF、历史决策、会议纪要什么时候不用:实时信息、精确文件路径、代码符号检索替代工具:web_search、read_file、grep_code参数策略:自然语言查询,包含实体和日期失败恢复:弱结果时改写 query 再试一次安全属性:只读可信边界:索引可能过期或不完整
这才是 Agent 真正需要的工具描述。
八、落地建议:把工具描述当成“可测试的 Prompt 接口”
最后可以用一句话总结:
API 文档告诉人“这个函数怎么用”;工具描述告诉模型“什么时候应该选择这个动作”。
在生产级 Agent / RAG / MCP 系统中,工具描述应该像 Prompt 一样被设计、评测、迭代,而不是像普通注释一样随手写。一个成熟工具描述至少要回答:
这个工具解决什么任务?用户说什么时应该调用?什么情况下绝对不要调用?如果不用它,应该用哪个工具?参数如何从用户意图映射出来?它是否只读、是否有副作用、是否需要确认?返回结果如何支持下一步推理?出错、为空、超时时 Agent 应该怎么恢复?
当这些问题被写清楚后,Agent 的工具调用会从“看起来会用工具”变成“稳定、可控、可评测地调用工具”。这也是 Claude Code、OpenCode、OpenClaw 这类成熟 Agent 系统给我们的核心启发:工具描述不是功能介绍,而是 Agent 行为边界的第一层设计。
分享
