Agent 注册了很多工具,如何告诉模型?
从工具定义到按需发现,说明注册表、模型可见工具与执行权限的区别,以及工具检索如何影响上下文和缓存。
一个研发助手接上代码仓库、工单和日志服务后,工具数量很容易从几个变成几百个。把全部定义放进每次请求,模型还没处理业务问题,上下文里已经有大量本轮用不到的参数说明。
比如,用户只想检查登录服务的错误日志,这一轮通常用不到创建工单或修改仓库的全部参数。工具仍然可以保存在服务器上,但模型先看到哪些定义,需要由应用决定。沿着这次日志查询,下面逐步说明工具如何被发现、送进模型请求,再交给程序执行。
注册、暴露和执行是三个步骤
假设日志工具已经注册。此时服务器知道如何调用它,但模型还未必见过它的名称和参数。应用把定义放进请求后,模型才有条件提出调用;真正发出日志查询,则是接下来的执行步骤。
| 位置 | 保存什么 | 负责什么 |
|---|---|---|
| 工具注册表 | 名称、描述、参数结构、版本、执行函数和权限信息 | 记录系统具备哪些能力 |
| 模型请求 | 当前可见工具的定义,或可调用的发现入口 | 让模型选择操作并生成参数 |
| 执行运行时 | 参数校验、权限校验、调用记录、超时与结果 | 把工具调用落实为外部操作 |
这里的运行时也常被称为 Agent Harness:围绕模型组织工具、会话和执行过程的程序。模型输出调用请求;实际执行由 Harness 或服务端承担。模型读到了某项能力的描述,并不意味着它已经获得执行权限。
MCP 2025-06-18 工具规范提供 tools/list、tools/call,以及名称、描述和 inputSchema 等字段;列表支持分页,服务端可以通知工具列表发生变化。客户端拿到列表后,仍需决定如何把工具提供给模型。MCP 没有替应用规定必须全量注入,也没有自动替它完成相关性检索。
一份工具定义需要说明什么
名称帮助识别操作,描述帮助判断适用场景,JSON Schema 约束参数结构。返回格式与错误语义也应有说明,否则模型即使调用正确,也可能误读结果。
下面是自定义工具注册表的示例,字段不是任何一家模型 API 的完整请求格式。接入时需要转换成所用 API 的工具定义。
{
"name": "search_error_logs",
"description": "按服务名和 UTC 时间范围查找错误日志。只读;返回匹配记录及下一页游标。",
"inputSchema": {
"type": "object",
"properties": {
"service": { "type": "string" },
"start": { "type": "string", "format": "date-time" },
"end": { "type": "string", "format": "date-time" }
},
"required": ["service", "start", "end"],
"additionalProperties": false
}
}
“查询数据”很难与其他工具区分。“按服务名和时间查错误日志”则能对应用户意图。参数结构能检查字段类型,时间先后、服务访问权限等业务约束仍需要运行时校验。Schema 校验通过,也不代表操作一定合理。
工具多时,先发现再加载
如果只有几个工具,每次把完整定义交给模型通常最省事。数量增加以后,就要决定由程序先选,还是让模型自己搜索。三种做法的取舍如下。
| 方案 | 过程 | 适用场景与代价 |
|---|---|---|
| 全量定义 | 请求直接携带全部工具 | 工具少且经常使用;实现简单,定义随规模增长 |
| Harness 预选 | 程序按任务或工作流选择工具子集 | 业务边界明确;预选遗漏时需要补充发现入口 |
| 模型主动发现 | 模型调用搜索工具,再读取匹配定义 | 能力多且任务开放;增加发现步骤,需验证检索质量 |
以“检查登录服务最近一次发布后的错误”为例,模型先看到“可访问仓库、部署记录和日志”的能力摘要,并调用 search_tools 查找相关操作。发现服务返回候选工具;Harness 或模型平台加载它们的完整定义,再让模型生成调用。
搜索可以先用名称、描述和关键词,必要时再加入语义检索与排序。候选列表应说明工具用途和适用条件,避免只返回一个相似度分数。找不到工具时允许换关键词、扩大范围或明确报告缺少能力,不应让模型猜测不存在的函数。
“搜索结果里有定义”与“下一轮可发起结构化调用”之间,还需要一条明确的连接路径:
- 平台支持延迟加载:按平台协议返回工具引用,由平台展开定义。
- 应用管理工具集合:Harness 将已选工具放入下一轮 API 的工具字段,并保持相关调用历史完整。
- 固定调用网关:模型调用
invoke_tool(name, arguments);网关查找定义并执行。参数装在通用对象中,具体约束主要由网关校验,不能假定模型平台会按被选工具的 Schema 约束它。
例如,Claude 工具搜索文档中的 tool_search_tool_regex_20251119 / tool_search_tool_bm25_20251119 支持用 defer_loading: true 延迟加载,由搜索返回工具引用(核对于 2026-10-27)。延迟的是进入模型上下文的时机:请求的 tools 数组仍要携带完整定义,供服务端搜索和展开;这是平台协议的一部分,不能把字段原样套到其他 API。还要区分工具发现和程序化调用:前者减少预先加载的定义,后者用代码编排调用、过滤中间结果,解决的是不同成本。
按需加载与缓存要一起考虑
工具定义占据上下文,也可能属于可缓存的请求前缀。每轮重新筛选、重排或改写工具定义,可能减少可复用前缀。缓存命中也不会让定义从上下文窗口消失,模型仍然受到上下文容量限制。
Claude 提示词缓存文档中,缓存层次按 tools、system、messages 组织;修改工具定义会影响后续缓存。支持延迟加载或中途添加定义的平台可能有专门的兼容机制,不能把“多了一个工具”一概解释为“所有缓存必然失效”。
对自建 Harness,可以保持常用工具定义和系统指令稳定,把发现结果与当前任务状态放到后续内容中;只有在 API 确实支持的路径上加载新工具。工具集合改变时,用实际请求记录核对缓存读取量、总输入量和任务结果。更少的定义、更多的缓存命中与更高的完成率,需要一起衡量。
缓存机制的推理背景可参阅前缀缓存与 TTFT。那篇解释推理阶段的复用,本篇讨论应用如何组织模型输入,两者的层次不同。
执行边界与验证方法
工具发现应先过滤当前账号不可使用的能力;具体调用时再检查权限、版本和参数。权限变更、服务断连或定义更新,都可能发生在发现与执行之间。工具说明及返回内容应作为资料处理,不应允许其中的文本改写 Harness 的权限规则。
从少量常用工具加一个搜索入口开始即可。暂时没有检索质量问题时,不必先建复杂的向量索引。需要扩展时,用固定任务集比较全量与按需方案,并保留相同的模型配置和任务完成标准。
| 验证项 | 需要观察的结果 |
|---|---|
| 发现质量 | 应用层标注的必需工具是否进入候选,遗漏后能否恢复 |
| 调用质量 | 是否选对工具,参数与业务约束是否通过 |
| 效率 | 包含发现步骤的总耗时、输入 token、缓存读取量和总成本 |
| 完成质量 | 是否取得正确结果,是否有证据支持完成声明 |
| 变化处理 | 工具撤销、版本更新、空结果与同名操作是否被正确处理 |
是否引入工具搜索,应由这组结果决定:若定义很长但预选已经稳定,优先保持简单的预选;若任务开放且漏选频繁,再补主动发现。只比较输入 token,会漏掉检索失败和额外往返的代价。参数通过校验后的边界见工具契约,跨回合保存发现结果见 Agent 的 /goal 如何实现。