课程大纲 › 领域 2:工具设计与 MCP
2.1 设计说明清晰、边界明确的有效工具接口
タスクステートメント2.1:明確な説明と境界を備えた効果的なツールインターフェースを設計する
官方大纲原文(日文):知识 4 条 · 技能 4 条
需要掌握的知识
- LLMがツール選択に用いる主要な仕組みとしてのツールの説明。最小限の説明では、類似したツール間での選択の信頼性が低下する
- ツールの説明に、入力形式、クエリの例、エッジケース、境界の説明を含めることの重要性
- 曖昧な、または重複するツールの説明が誤ったルーティングを引き起こす仕組み(例:ほぼ同一の説明を持つanalyze_contentとanalyze_document)
- システムプロンプトの文言がツール選択に与える影響:キーワードに敏感な指示が、意図しないツールの関連付けを生む可能性がある
需要能做到的事
- 各ツールの目的、想定される入力、出力、および類似の代替ツールではなくそのツールを使うべき場面を明確に区別するツールの説明を作成する
- 機能の重複をなくすために、ツールの名前を変更し説明を更新する(例:analyze_contentをextract_web_resultsに名前変更し、ウェブに特化した説明を付ける)
- 汎用的なツールを、入出力の契約が定義された目的別のツールに分割する(例:汎用的なanalyze_documentを、extract_data_points、summarize_content、verify_claim_against_sourceに分割する)
- 適切に書かれたツールの説明を上書きしてしまう可能性のある、キーワードに敏感な指示がないかシステムプロンプトをレビューする
课程讲解 · AI 草稿,未经人工审核 以官方文档为准
这一条考什么
考你能否设计出让模型"选得对"的工具接口。Claude 主要依据工具的名称、描述和参数 schema 来决定调用哪个工具,所以描述写得太短、两个工具描述几乎相同、或者系统提示里有对关键词敏感的指令,都会导致错误路由。题目常给出误选工具的现象,要你找出根因并选择修复方式:完善描述、重命名、把通用工具拆成职责单一的工具、审查系统提示。
核心概念
描述是工具选择的主要依据
模型看不到你的实现代码,它只能读到工具定义。描述只有一句"Analyzes dependency graph"时,模型无法判断它与自己熟悉的 Grep 相比有何优势,于是倾向于用熟悉的通用工具。类似地,"Extracts a function from code"没有说明它是否理解语法树、是否会更新调用点,模型就可能宁可用 sed 做文本替换。描述越简略,相似工具之间的选择就越不可靠。
好描述应包含什么
一份合格的工具描述通常覆盖:
- 做什么:具体能力与范围,而不是一个动词。
- 何时用 / 何时不用:与相似工具的区别,例如"需要查依赖关系时用本工具,而不是对 import 语句做 Grep"。
- 输入格式:每个参数的含义、格式、取值来源(如"order_id 必须来自 lookup_order 的返回结果,不得猜测")。
- 示例查询:一两个典型调用。
- 边界与边缘情况:不支持什么、空结果意味着什么、大输入如何处理。
- 输出:返回哪些字段,便于模型规划下一步。
{
"name": "get_dependency_graph",
"description": "基于 AST 构建指定模块的依赖图,返回直接 import、传递依赖和循环依赖。当问题涉及'谁依赖谁''改动影响范围''是否存在循环引用'时使用本工具,而不是用 Grep 搜索 import 文本(Grep 无法识别别名导入和动态导入)。输入 module 为点分路径,如 'app.billing.invoice';depth 默认 2,最大 5。模块不存在时返回 is_error。输出:{direct:[], transitive:[], cycles:[[...]]}。",
"input_schema": {
"type": "object",
"properties": {
"module": {"type": "string", "description": "点分模块路径,如 app.billing.invoice"},
"depth": {"type": "integer", "minimum": 1, "maximum": 5, "default": 2}
},
"required": ["module"]
}
}含糊或重叠的描述导致误路由
如果同时存在 analyze_content("分析内容并提取信息")和 analyze_document("分析文档并提取信息"),模型面对一个网页搜索结果时几乎是在抛硬币。修复方向是消除功能重叠:
- 重命名,让名字本身体现差异:
analyze_content→extract_web_results,描述限定为"解析网页搜索返回的结果列表"。 - 改写描述,明确各自的适用输入与不适用场景。
- 若两个工具本质上做同一件事,合并为一个工具并用参数区分(例如把
issue_credit与process_refund合并为带action参数的resolve_compensation)。
把通用工具拆成目的明确的工具
一个接受"文档 + 自由文本指令"的 analyze_document 看似灵活,实际上同时承担提取、摘要、核实三种截然不同的任务:要求"提取财务指标"时返回了叙述性摘要,要求"总结方法论"时又返回了原始数据表。拆分为:
extract_data_points:输入文档与要提取的字段列表,输出结构化数据点。summarize_content:输入文档与长度/关注点,输出摘要文本。verify_claim_against_source:输入一条论断与来源,输出支持/反驳/无法判断及证据片段。
每个工具都有明确的输入输出契约,各自的成功标准和错误处理也更清晰。相比之下,"保留单工具、加一个 analysis_type 枚举"只是把歧义从工具选择挪到参数选择,输出契约仍然混杂。
系统提示也会影响工具选择
系统提示中对关键词敏感的指令可能覆盖精心编写的工具描述。例如系统提示写着"凡是提到'文档'就使用 analyze_document",那么用户说"帮我把这篇网页文档的要点列出来"时,模型会被"文档"一词拉向错误的工具。审查要点:
- 找出"看到 X 词就用 Y 工具"之类的硬规则,改为描述意图而非关键词。
- 检查系统提示与工具描述是否存在冲突说法。
- 工具选择逻辑尽量写在工具描述中,让信息就近、一致。
正确做法与反模式
- 正确:在描述中写明用途、输入格式、示例、边界,以及与相似工具相比何时该用它。反模式:一句话描述,如"分析依赖图"。
- 正确:把重叠的工具重命名并改写描述,例如
analyze_content改为extract_web_results。反模式:保留两个几乎一样的描述,靠系统提示补救。 - 正确:把万能工具拆成输入输出契约明确的专用工具。反模式:一个工具 + 自由文本指令参数包打天下。
- 正确:审查系统提示,删除对关键词敏感的路由指令。反模式:在系统提示里继续堆"遇到某词用某工具"的规则。
- 正确:在参数描述中声明值的可信来源(如必须来自前一个工具的结果)。反模式:只声明类型,让模型自行"编"一个看似合理的值。
常见陷阱
- "在系统提示里加路由规则:依赖问题用 MCP 工具而不是 Grep"——治标不治本,且关键词规则可能引发新的误路由;最佳答案是充实工具描述。
- "把 Grep 从可用工具中移除以消除重叠"——损失了合法的文本搜索能力。
- "加一个请求分类器,在 Agent 处理前预先路由"——额外基础设施,绕开了模型本该依据的描述。
- "保留通用工具但增加 analysis_type 枚举"——歧义仍在,输出契约仍混杂,不如拆分。
- "换成 tool_choice: any 强制每轮都调用工具"——解决的是"是否调用",不是"选哪个、参数从哪来"。
- "接受现状,因为 sed 更可预测"——放弃了更合适的专用工具。
实操练习
目标:对比"简略描述"与"完整描述"下 Claude 的工具选择。
- 保存下面的
tool_desc_lab.py。 - 先用
WEAK版本运行 5 次,记录模型选了哪个工具;再换成STRONG版本运行 5 次。 - 比较两组结果。
import anthropic
client = anthropic.Anthropic()
Q = "billing.invoice 模块被哪些模块间接依赖?有没有循环引用?"
grep_tool = {
"name": "grep",
"description": "在代码库中按正则搜索文本,返回匹配行。",
"input_schema": {"type": "object", "properties": {"pattern": {"type": "string"}}, "required": ["pattern"]},
}
WEAK = {
"name": "dep_graph",
"description": "分析依赖图。",
"input_schema": {"type": "object", "properties": {"module": {"type": "string"}}, "required": ["module"]},
}
STRONG = {
"name": "dep_graph",
"description": ("基于 AST 构建模块依赖图,返回直接依赖、传递依赖与循环依赖。"
"涉及'影响范围''间接依赖''循环引用'的问题应使用本工具,"
"而不是用 grep 搜索 import 文本(grep 无法识别别名与动态导入)。"
"module 为点分路径,如 billing.invoice。"),
"input_schema": {"type": "object", "properties": {"module": {"type": "string"}}, "required": ["module"]},
}
for label, dep in [("WEAK", WEAK), ("STRONG", STRONG)]:
picks = []
for _ in range(5):
r = client.messages.create(
model="claude-sonnet-4-5", max_tokens=300,
tools=[grep_tool, dep], messages=[{"role": "user", "content": Q}],
)
picks += [b.name for b in r.content if b.type == "tool_use"][:1] or ["(无工具)"]
print(label, picks)检查结果:STRONG 版本应更稳定地选择 dep_graph。再试着在 system 中加入"凡是提到'模块'就用 grep 搜索",观察这条关键词指令如何把正确选择拉偏。
自测清单
- Claude 选择工具时主要依据哪些信息?为什么一句话描述不够?
- 一份完整的工具描述应包含哪些要素?
- 遇到
analyze_content与analyze_document这样重叠的工具,有哪几种修复方式? - 为什么把通用
analyze_document拆成三个工具,比加一个枚举参数更好? - 系统提示中的哪类措辞可能覆盖良好的工具描述?如何审查?
对应题目(7)
题目归类由 AI 判断,仅供参考。
练习这 7 道题