这道题其实是在问,怎么让[[Agent]]能安全高效地调用外部工具,同时又要方便扩展和维护。本质上是一个能力编排和治理的问题。
我先说注册机制。我会用动态注册加静态配置兜底。动态注册就是每个工具服务启动时,往注册中心比如etcd上报自己的名字、端点、健康状态,Agent通过服务发现拿到可用列表,这样新增工具不用重启。但核心工具比如代码执行、数据库查询,我还会内置在配置文件里,防止注册中心挂了这些工具用不了。
再说描述规范化,这是最关键的。LLM要靠自然语言理解工具是干嘛的,执行层要靠Schema做参数校验。所以我会用自然语言描述加JSON Schema参数;OpenAPI接口需要适配为具体工具协议,不能把两种格式直接混称。举个例子,一个查询酒店的工具,description写清楚支持城市和价格筛选,parameters根部用type:object,properties里定义city:string和max_price:number,required在该参数schema内声明city。执行层用这个结构校验;模型是否选对工具/填对语义仍需测试。这里有个坑,description写得太模糊,LLM就容易选错工具,所以我会要求每个工具描述都覆盖典型使用场景。
权限控制这块,我会分三层。工具级用RBAC,用户角色决定能调哪些工具。参数/资源级,用户、租户与资源归属需可信后端授权,不能相信模型传入的user_id;脱敏只能减少暴露,不能替代授权。执行级,代码执行工具要放到沙箱里,还要限制QPS和耗时。说白了,权限不是一刀切,得看工具的风险等级。
版本管理我用语义化版本,v1.2.3这种,主版本不兼容、次版本新增、修订版修复。注册时带上版本号,Agent可以指定query_hotel@1.x,这样向后兼容。灰度发布按流量比例切,异常自动回滚。版本兼容性没处理好,上线就是事故。
和Agent核心的集成,就是规划、执行、反思的闭环。规划模块拿工具描述,做[[ReAct]]推理。执行模块调注册中心拿Endpoint,调工具拿到结果。反思模块看执行日志,成功失败耗时,决定是继续、重试还是换工具。结果我会标准化封装,必须有成功码、数据和错误信息,Agent才好做决策。
实际落地时,描述规范化最容易出问题,比如参数描述和实际行为不一致,LLM就会[[幻觉]]调用。所以我会在工具上线前,用一批测试query跑一遍,检查LLM选工具和填参数的正确率。如果这个点不过,后面权限和版本管理做得再好也没用。
所以我的整体思路是,用动态注册保证扩展性,用描述与Schema辅助选择和校验,用后端分层授权控制访问,并按版本兼容约定和测试管理变更,最后通过标准化封装让Agent能自主决策。