专栏第 5 篇解决工具接入“越写越乱、越改越痛”的工程问题。一、问题描述为什么很多 Agent 项目会死在工具层当项目从 Demo 进入实战工具层很容易出现这几类问题每个工具入参/出参都不一样调用方不断写适配错误格式不统一排错靠猜工具数量一多分发逻辑散落在业务代码里新增一个工具要改多处回归风险高。本质原因缺少统一协议 缺少注册中心。二、先给结论工具层要做成“平台”不是“函数集合”一个可持续扩展的工具层最少需要三件事统一调用协议Input/Output/Error集中注册与发现Registry统一执行护栏超时/重试/熔断/权限做到这三点后Agent Core 才能保持稳定工具可以独立演进。三、统一协议设计建议标准3.1 请求协议{tool_name:search_docs,request_id:req_20260323_001,step_id:step_2,params:{query:single agent state machine},timeout_ms:8000,metadata:{user_id:u_001}}3.2 响应协议{ok:true,data:{items:[]},error:null,latency_ms:236,trace_id:trace_xxx}3.3 错误协议{ok:false,data:null,error:{code:TOOL_TIMEOUT,message:search_docs timeout after 8000ms,retryable:true},latency_ms:8001,trace_id:trace_xxx}重点所有工具都必须返回同一壳子结构这样调用方才不会写分支地狱。四、注册中心设计从“硬编码 if/else”走向“可插拔”4.1 为什么要 Registry没有注册中心时常见代码是iftool_namesearch:returnsearch_tool.run(params)eliftool_namedb:returndb_tool.run(params)...问题新增工具就改核心分发逻辑违反开闭原则。4.2 Registry 最小接口classTool(Protocol):name:strtimeout_ms:intdefrun(self,params:dict,ctx:dict)-dict:...classToolRegistry:def__init__(self):self._tools{}defregister(self,tool:Tool):iftool.nameinself._tools:raiseValueError(fduplicate tool:{tool.name})self._tools[tool.name]tooldefget(self,name:str)-Tool:ifnamenotinself._tools:raiseKeyError(ftool not found:{name})returnself._tools[name]deflist(self):returnlist(self._tools.keys())这样新增工具只需要新建工具类注册一次不改 Agent Core。五、执行护栏统一包裹工具调用5.1 包裹器目标无论哪个工具执行前后都走同一层 wrapper统一处理超时重试熔断日志指标权限5.2 执行伪代码defexecute_tool(req,registry,breaker,logger):toolregistry.get(req[tool_name])ifnotbreaker.allow(tool.name):returnfail(TOOL_CIRCUIT_OPEN,retryableTrue)startnow_ms()try:resultwith_timeout(lambda:tool.run(req[params],{request_id:req[request_id]}),req.get(timeout_ms)ortool.timeout_ms)latencynow_ms()-start logger.info(tool_ok,tooltool.name,latency_mslatency)breaker.on_success(tool.name)returnok(result,latency)exceptTimeoutError:breaker.on_failure(tool.name)returnfail(TOOL_TIMEOUT,retryableTrue)exceptExceptionase:breaker.on_failure(tool.name)returnfail(TOOL_EXEC_ERROR,messagestr(e),retryableFalse)六、权限与边界别让工具层成为安全短板建议最少做三层控制工具级白名单只允许注册后工具被调用参数级校验每个工具有独立 schema上下文级限制按用户/会话控制可用工具集合。例如普通用户可用search/read管理员才可用write/delete。七、推荐目录结构与前文衔接app/tools/ ├─ base.py # Tool 协议定义 ├─ registry.py # 注册与发现 ├─ executor.py # 统一执行包裹器 ├─ errors.py # 错误码定义 ├─ policies.py # 权限与策略 ├─ search_tool.py ├─ db_tool.py └─ http_tool.py八、验证清单怎么确认工具层“真可扩展”新增工具只改 tools 目录不改 agent core所有工具都返回统一响应结构超时/异常可映射到标准错误码工具执行日志可按 request_id 检索禁用工具时系统有明确错误返回而非崩溃九、常见报错与排查报错tool not found原因未注册或注册名不一致处理启动时打印 registry.list()做健康检查现象调用成功但上层解析失败原因工具返回结构不符合统一协议处理在 executor 层做 response schema 校验现象偶发高延迟原因个别工具无 timeout 或重试过度处理全工具强制 timeout 上限 统一重试策略现象权限绕过原因仅在前端限制后端未校验处理工具执行前做服务端策略校验十、本篇总结统一协议解决“能不能调”注册中心解决“好不好扩”执行护栏解决“稳不稳定”。一句话工具层标准化之后Agent Core 才能长期保持简洁。