如何实现动态工具发现和注册?
难度:高级 分类:Tool Use
简短回答
动态工具发现是指 Agent 在运行时(而非编译时)发现和使用新工具的能力。这解决了静态工具加载的两大问题:上下文窗口浪费(50+ 工具定义可消耗 55k+ tokens)和选择准确率下降(工具越多,模型选错的概率越高)。主流实现方式包括:MCP 动态发现(通过 tools/list 端点和 list_changed 通知实时更新工具列表)、语义检索(用 Embedding + FAISS 按用户意图检索最相关工具)、上下文感知过滤(根据认证状态、权限、会话阶段动态暴露不同工具集)、Instruction-Tool Retrieval (ITR)(每步只检索最小必要工具子集,减少 95% 上下文开销)。
详细解析
为什么需要动态工具发现?
静态工具加载的问题随规模暴露:
代码块
Plain Text
静态方式(所有工具塞进 System Prompt):
┌────────────────────────────────────┐
│ System Prompt │
│ 工具 1 定义 (500 tokens) │
│ 工具 2 定义 (500 tokens) │
│ ... │
│ 工具 50 定义 (500 tokens) │
│ ────────────────── │
│ 总计: 25,000+ tokens 仅用于工具定义 │
└────────────────────────────────────┘
动态方式(按需加载相关工具):
┌────────────────────────────────────┐
│ System Prompt │
│ 工具 A 定义 (500 tokens) ← 相关 │
│ 工具 B 定义 (500 tokens) ← 相关 │
│ 工具 C 定义 (500 tokens) ← 可能相关│
│ ────────────────── │
│ 总计: 1,500 tokens │
└────────────────────────────────────┘
Anthropic 内部测试显示 58 个工具可消耗约 55k tokens。工具数量增加不仅浪费成本,还会降低工具选择准确率。
方式 1:MCP 动态发现
MCP 协议原生支持工具的动态发现和热更新:
代码块
Python
# MCP Server 端:工具列表变化时通知客户端
class DynamicMCPServer:
def __init__(self):
self.tools = {}
async def register_tool(self, tool):
"""运行时注册新工具"""
self.tools[tool.name] = tool
动态发现 = 通知 + 拉取:Server 一注册/注销就广播 list_changed,Client 重新 tools/list 刷新 Agent 的工具清单。
典型场景: 用户登录后,Server 根据权限暴露不同工具;Session 从"浏览"阶段进入"购买"阶段时,新增支付相关工具。
方式 2:语义检索(Tool RAG)
当工具数量超过 50 个时,用 Embedding 检索最相关的工具子集:
代码块
Python
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
class ToolRegistry:
def __init__(self, tools: list[dict]):
self.model = SentenceTransformer("all-MiniLM-L6-v2")
self.tools = tools
方式 3:上下文感知过滤
根据运行时上下文动态调整可用工具:
代码块
Python
class ContextAwareToolFilter:
def __init__(self, all_tools):
self.all_tools = all_tools
def get_available_tools(self, context: dict) -> list:
available = []
for tool in self.all_tools:
# 权限检查
if not self.user_has_permission(context["user"], tool):
continue
方式 4:Instruction-Tool Retrieval (ITR)
最新研究方法——每一步只检索最小必要的系统指令片段和工具子集:
代码块
Python
class InstructionToolRetriever:
"""每步检索最小必要的指令和工具"""
方式 5:集中式工具注册中心
生产环境的规模化方案:
代码块
Python
class CentralToolRegistry:
"""集中式工具注册中心"""
各方式对比
常见误区 / 面试追问
误区:"把所有工具都放进 System Prompt 最简单可靠" — 工具超过 20 个后,选择准确率明显下降,上下文窗口被大量占用。动态发现是规模化的必要手段。
误区:"动态发现只是性能优化" — 它也是安全机制。通过动态过滤,可以根据用户权限、认证状态实时调整可用工具,实现最小权限原则。
追问:"语义检索选错了工具怎么办?" — 两层保护:(1) 检索时取 top-k(如 5-8 个)而非 top-1,给 LLM 更多选项;(2) LLM 仍然做最终选择——检索只是缩小范围,不是替代 LLM 的判断。
追问:"动态工具发现和 Agent 编排有什么关系?" — 动态发现影响 Agent 的能力边界——Agent 能做什么取决于它能发现哪些工具。在多 Agent 系统中,不同 Agent 可能连接不同的 MCP Server,拥有不同的工具发现范围。