首页 / 资讯中心 / 文章详情

Agent-Reach:为AI Agent打造的工具触达层,让模型真正长出能干活的手

Agent-Reach:为AI Agent打造的工具触达层,让模型真正长出能干活的手 ★ FEATURED ARTICLE
Agent-Reach这个名字我第一次看到的时候脑子里浮现的画面是一个聪明的大脑长出了一双真正能干活的手。如果你搞过Agent应用一定遇到过这种尴尬——模型推理能力越来越强但它永远只能给你输出一段文字没法自己去查天气、建工单、查数据库。你要么在代码里写一大堆if-else去匹配它说要调用哪个函数要么把几十个工具一股脑塞进Prompt里等着它选错。Agent-Reach要解决的就是这个问题它是一层介于模型与外部资源之间的“触达层”负责让Agent真正够到工具、API、知识库同时把鉴权、路由、回退、观测这些脏活累活全部收拢起来。这篇文章我会从设计思路、核心机制、最小可运行版本到实际踩坑实录完整拆一遍适合正在做Agent应用、研究Function Calling或者想给现有系统加一层“Agent入口”的开发者。1. 为什么Agent需要一个Reach层1.1 Agent的“手”为什么不够长先说一个最直观的类比。大语言模型就像一个知识渊博但不会做饭的顾问他能告诉你红烧肉该怎么做步骤倒背如流但他不会自己开火、下锅、翻勺。在纯对话场景里这没问题可一旦你想让他帮你完成一个真实任务——比如“帮我查一下这个订单的物流状态”或者“创建一张退款工单”——他就必须调用外部系统。这中间隔着的这堵墙就是Agent落地时最大的阻碍。早期方案很简单就是Function Calling把函数定义和参数Schema塞进Prompt模型根据用户意图输出一个结构化的调用请求代码拿到请求后执行函数再把结果回填给模型。这个思路本身没错但实际用起来问题一个接一个。首先是工具一多上下文就开始膨胀。一个精心写的函数描述少说几十个token工具数量上了20个每轮对话光工具描述就能吃掉上千token成本上去不说模型还会因为信息过载而选错工具。其次是每个工具的生命周期完全没人管鉴权怎么做超时怎么处理失败要不要重试并发时要不要限流这些逻辑如果不收敛在一个统一层里就会散落在业务代码的各个角落成为灾难。我见过很多团队的做法是在Agent代码里硬编码了一大串“if model_output get_weather”之类的分支再加十几个互相嵌套的try-except。项目能跑但加一个新工具要改代码、重发版本出了问题只能靠肉眼翻日志。这种状态持续不了多久你就会意识到需要一个独立的层把“模型意图”和“真实执行”彻底解耦。Agent-Reach就是干这个的。1.2 Reach层在Agent架构里的位置把Agent系统从上往下拆大致可以分成四层模型层、推理层、Reach层、资源层。模型层就是GPT、Claude、文心这些大模型负责理解和生成推理层负责拆解任务、决定下一步做什么比如ReAct循环、Plan-and-ExecuteReach层就是我们今天的主角它位于推理层之下、资源层之上专门负责把推理层的“行动意图”变成真实的“系统调用”资源层则是企业内部的数据库、HTTP API、知识库、工单系统等具体能力。Reach层不是什么神秘的东西你就把它理解成Agent的“标准总线”。它的核心职责有六个发现知道当前有哪些工具可用、路由决定某个请求该交给哪个工具、鉴权确认Agent有没有权限调用、执行真正发起请求、回退失败后怎么办、审计记录一切行为。这六个职责如果分散在各处系统会越来越难维护把它们全部收进Reach层上面的推理层和下面的资源层就能各自保持简单。用生活化的话来说推理层是“大脑”负责决策Reach层是“神经传导系统加肌肉控制中枢”负责把大脑的命令准确无误地传导到对应的“肢体”上。大脑不需要知道肌肉细胞怎么收缩它只需要说“抬手”剩下的交给神经系统。Agent也一样推理层只需要说“查一下物流”Reach层负责找到物流查询工具、带上凭证、执行调用、把结果整理好送回来。1.3 Agent-Reach设计的三个原则在我自己搭Reach层的过程中总结出三条核心设计原则可以说哪个都不能丢。第一条是“描述驱动一切”。工具能不能被正确调用取决于你给模型的描述有多清楚。工具的name、description、参数Schema、返回值格式这些不是给程序员看的文档而是给模型看的“操作手册”。描述写得好模型一次就能选中正确的工具并填对参数描述写得烂模型就会在十几个工具之间犹豫、乱试。描述驱动还意味着新增工具只需要改配置和描述不需要改Reach层的代码。第二条是“失败可控”。Agent调用外部系统的失败率一定比你想象得高服务超时、参数缺失、权限不足各种原因都有。Reach层必须预设好失败模式超时多久算失败、重试几次、有没有降级方案、失败信息怎么反馈给模型。如果模型拿到的是一堆莫名其妙的堆栈信息那它将无法自己修复但如果我们把失败格式化成“服务暂时不可用请稍后再试”这种结构化消息模型就知道该换策略还是该通知用户。第三条是“可观测即默认”。Agent系统最难调试的地方就是不确定性——你今天跑同样的输入明天可能得到不同的输出。如果没有完整的日志和追踪出问题之后你根本不知道是哪一环出了偏差。所以Reach层的每一步包括收到的原始请求、路由选择、执行结果、耗时、Token消耗、是否重试都应该默认记录下来。宁可日志多到告警也不能没有日志。2. 核心机制与关键设计2.1 工具描述协议是整个系统的地基Reach层的第一项核心工作是定义一种统一的工具描述协议。你可以参考OpenAI Function Calling的格式也可以借鉴MCP的Tool Schema但不管用什么核心字段基本一样。我这边常用的最小有效结构是五个字段name工具唯一标识、description面向模型的行为说明、parametersJSON Schema格式的参数定义、returns返回值结构说明、errors定义的错误码和含义。这里最值的讲的是description怎么写。大部分开发者容易犯的毛病是把description写成了给人看的文档比如“获取天气数据”。但模型是拿这段文字来理解“什么时候该用这个工具”的。更好的写法是“当用户查询任意城市的当前天气或未来天气预报时使用。支持城市名称模糊匹配。如果用户未提供城市请询问后再调用。”你看这里面包含了三个关键信息触发条件、能力边界、参数缺失时的指引。模型看到这段描述才能判断“我要不要用、用了之后缺参数怎么办”。Parameters的收敛同样重要。我见过一个内部分析工具定义了24个可选参数结果模型每次调用都会自动填一堆不必要的参数然后报错。后来我把可选参数砍到只剩5个必须填的只有3个调用准确率直接提升了一大截。原则是参数能少就少能自动推导的就不让模型填能枚举的坚决用enum而不是让模型自由发挥。以下是一个比较标准的工具描述示例我拿这个当模板用{ name: query_order_status, description: 根据订单号查询物流与配送状态。当用户询问订单到哪了发货了没什么时候送达时使用。若缺少订单号先向用户索要。, parameters: { type: object, properties: { order_id: { type: string, description: 完整的订单号通常为12位数字或字母组合 }, include_tracking: { type: boolean, description: 是否返回物流轨迹明细默认false, enum: [true, false] } }, required: [order_id] }, returns: { type: object, properties: { status: { type: string, enum: [pending, shipped, delivered] }, eta: { type: string, description: 预计送达时间 } } }, errors: { ORDER_NOT_FOUND: 订单不存在可能输入有误, SERVICE_UNAVAILABLE: 物流服务暂不可用可让用户稍后再试 } }这段描述如果直接交给模型它对于“什么时候调用、缺参怎么办、错误怎么处理”都一目了然调用出错的概率会显著下降。2.2 工具发现与动态路由工具描述协议定下来后下一个问题是Reach层怎么知道有哪些工具、怎么把请求分发给正确的工具。这就是工具发现与路由的范畴。最基本的方案是静态注册表做法是启动时把所有工具的描述加载进一个字典路由的时候逐个匹配。适合工具数量少10个以内且很少变的场景。它的优点是简单可靠缺点很明显加工具要改配置、重发版本做不到热更新。进阶方案是动态发现。工具不再事先注册而是由各业务系统在启动或定期上报自己的能力描述Reach层维护一个“能力目录”。模型拿到的是整个目录的摘要真正需要调用时再拉取指定工具的详细描述。这种做法在工具数量超过几十个的时候几乎是必须的——你不可能每轮对话都把50个工具的完整描述塞给模型但你可以只把每个工具的一句话摘要给它等模型决定要用了再展开。路由策略上我建议用“精确匹配优先、语义匹配兜底”的组合拳。精确匹配就是根据模型输出的工具名直接查注册表命中就执行没命中时把模型的原始意图描述和所有工具的摘要做一次向量相似度计算取Top-3作为候选再交给模型做一次选择。这个兜底逻辑非常管用因为模型经常会把工具名叫错比如实际工具叫“query_sales_report”模型却输出“get_sales_data”精确匹配必然落空语义匹配却能把它捞回来。路由还有一个容易被忽略的细节并发控制。同一个Agent实例在跑多轮任务时可能同时发出好几个工具调用请求。Reach层要给每个请求分配一个request_id并且用队列或信号量控制单工具的并发量防止一个工具被同时调用几十次把后端打爆。静态注册表时代大家都不care这个等工具多了这一步迟早要做。2.3 权限隔离与安全边界Agent一旦能真调用工具权限问题立刻变得尖锐。模型没有主动的安全意识它只会按照用户意图执行而用户意图可能是恶意构造的。所以Reach层必须在“Agent身份”“工具权限”“数据脱敏”三个维度上进行隔离。第一层是Agent身份。每个Agent实例应该有一个最小权限身份比如“客服Agent”只能读取订单和创建工单不能删除数据、不能改价。身份在启动时绑定Reach层根据身份过滤可用工具列表身份看不到的工具模型连描述都拿不到自然无法调用。这比把工具都暴露出来、靠后端校验要安全得多。第二层是工具级权限。有时同一工具对不同身份有不同参数权限比如普通客服Agent能查询订单但看不到客户手机号运营Agent才能看到完整信息。这个可以在工具描述里做数据字段级别的控制Reach层在拿到模型生成的参数后把权限不允许的字段直接剥离而不是要求模型自己遵守。模型说“帮我查一下这个客户的手机号”Reach层返回中把手机号设置为null再告诉模型“手机号字段对当前身份不可见”。第三层是敏感操作二次确认。对于删除、批量修改、发消息这类操作Reach层应该设置一个“确认门闩”第一次调用时返回“该操作需要用户二次确认请用户回复确认后重试”模型就会向用户展示确认文案。用户确认后参数带上确认标记Reach层才放行。这套机制我建议做成平台默认能力而不是让业务自己去判断。2.4 可观测性设计最后说可观测性。Agent系统出问题绝大多数时候不是“代码逻辑错误”而是“事态发展偏离预期”模型选了这个工具而不是那个、参数多填了、后端超时了、用户绕过Agent直接提了敏感请求。没有观测你只能靠猜。Reach层的观测设计至少要有三块日志、追踪、指标。日志方面每一条请求必须记录完整的请求-响应链路包括原始消息、模型输出、工具选择、执行结果、错误码、请求耗时。日志格式尽量统一为JSON方便接ES或Loki。追踪方面给每一个Agent任务分配一个trace_id向下透传给每个工具调用这样用户反馈“刚才那个任务结果不对”时你只要拿trace_id就能捞出一整条链路从头看到尾。指标方面需要采集的无外乎工具调用次数、成功率、平均耗时、Token消耗、路由命中率、回退次数。这三个指标集我建议直接埋点量大了再考虑抽样。其中路由命中率最值得单独盯。如果发现模型频繁输出一个并不存在的工具名说明工具描述里缺少某些触发词或者工具数量过多导致模型混淆。命中率骤降通常意味着最近的工具描述改动出了问题。这个指标比调用成功率更能提前预警问题。3. 实操从零搭一个Agent-Reach最小可运行版本3.1 整体流程与核心代码说了这么多设计下面直接进入实操环节。我用Python给你搭一个最小的Agent-Reach版本包含工具注册、路由分发、执行、回退几个核心模块。它的工作流程是外部输入一个“模型意图”结构体Reach层根据意图中的tool_name去注册表里查找找到就执行对应函数失败就走回退逻辑。先看入口模块的骨架# reach_core.py from typing import Dict, Callable, Any import time import uuid class ToolRegistry: def __init__(self): self._tools: Dict[str, Dict[str, Any]] {} def register(self, tool_def: Dict[str, Any], handler: Callable): 注册工具。tool_def包含name/description/parameters/returns/errors。 name tool_def[name] if name in self._tools: raise ValueError(f工具 {name} 已存在) self._tools[name] { definition: tool_def, handler: handler } def get(self, name: str): return self._tools.get(name) def list_descriptions(self) - str: 把工具描述压缩成给模型看的摘要文本。 summaries [] for name, item in self._tools.items(): d item[definition] summaries.append(f{name}: {d[description]}) return \n.join(summaries) class ReachEngine: def __init__(self, registry: ToolRegistry): self.registry registry self.timeout 8 # 默认超时8秒 self.max_retries 2 def execute(self, tool_name: str, args: Dict[str, Any], timeout: int None): 执行一次工具调用带超时和重试逻辑。 timeout timeout or self.timeout tool self.registry.get(tool_name) if not tool: return self._fail(f工具 {tool_name} 不存在, TOOL_NOT_FOUND) handler tool[handler] trace_id uuid.uuid4().hex[:12] start time.time() attempt 0 while attempt self.max_retries: if attempt 0: print(f[reach] trace{trace_id} tool{tool_name} 第{attempt}次重试) try: result handler(args) elapsed (time.time() - start) * 1000 print(f[reach] trace{trace_id} tool{tool_name} 成功 耗时{elapsed:.1f}ms) return {status: success, data: result, trace_id: trace_id} except TimeoutError: return self._fail(调用超时, TIMEOUT, trace_id) except Exception as e: last_error str(e) attempt 1 time.sleep(0.5 * attempt) return self._fail(f调用失败: {last_error}, UNKNOWN_ERROR, trace_id) def _fail(self, message: str, error_code: str, trace_id: str None): return { status: error, error_code: error_code, message: message, trace_id: trace_id or uuid.uuid4().hex[:12] }这里我把超时和重试逻辑统一放进了Execute方法目的是让handler只负责业务实现不用关心容错细节。核心执行器就这么点代码看起来简单但够用后面的路由策略是建立在这个基础之上的。3.2 工具注册与描述实战下面注册两个工具。第一个是模拟查询天气第二个是模拟创建工单。注意handler的入参是一个dict这样做的好处是参数校验可以与模型输出解耦future如果要接JSON Schema校验器也方便。# tools.py from reach_core import ToolRegistry def get_weather(args): city args.get(city) if not city: raise ValueError(缺少城市参数) # 这里省略真实的天气API调用用静态数据模拟 weather_map {北京: 晴22°C, 上海: 小雨18°C} return { city: city, weather: weather_map.get(city, 未知城市请检查后重试) } def create_ticket(args): title args.get(title) priority args.get(priority, low) if not title: raise ValueError(工单标题不能为空) # 生成一个假的工单号 return { ticket_id: TK- str(hash(title) 0xFFFFFF), status: created, priority: priority } def register_all(registry: ToolRegistry): weather_def { name: get_weather, description: 根据城市名查询当前天气。当用户问某地天气时使用。若城市名不全直接告诉用户提供城市。, parameters: { type: object, properties: { city: {type: string, description: 城市名如北京、上海} }, required: [city] } } ticket_def { name: create_ticket, description: 为用户创建一张售后或咨询工单。当用户要求投诉、保修、人工介入时使用。, parameters: { type: object, properties: { title: {type: string, description: 工单内容摘要}, priority: {type: string, enum: [low, medium, high], default: low} }, required: [title] } } registry.register(weather_def, get_weather) registry.register(ticket_def, create_ticket)这时候你可以自己模拟一个“模型输出”来测试# main.py from reach_core import ToolRegistry, ReachEngine from tools import register_all registry ToolRegistry() register_all(registry) engine ReachEngine(registry) # 模拟模型Agent输出的调用请求 decision {tool_name: get_weather, args: {city: 北京}} result engine.execute(decision[tool_name], decision[args]) print(result)跑出来的结果应该是成功返回天气信息并且带一个trace_id。这一步其实就是Agent-Reach最小闭环的核心模型负责出决策Reach层负责执行决策。看到这里你应该明白为什么一开始我就强调描述协议的重要——上面这个demo里handler是程序员写的但真实场景里tool_name和args都是模型从描述里推断出来的描述不准确一切白搭。3.3 路由策略的落地如果模型偶尔把工具名搞错你的Reach层需要一个兜底路由。最简单的兜底是关键词匹配进阶做法是用向量召回。我先把关键词匹配发出来这个零依赖、好懂、可在线调试# router.py import re class KeywordRouter: def __init__(self, registry: ToolRegistry): self.registry registry self.keywords_map { 天气: [get_weather, weather, 气温, 下雨], 工单: [create_ticket, ticket, 投诉, 报修, 售后], } def route(self, raw_intent: str): 根据原始用户意图返回候选工具名列表。 candidates [] for keyword, tool_names in self.keywords_map.items(): if keyword in raw_intent: for name in tool_names: if self.registry.get(name): candidates.append(name) return candidates or None # 用法在ReachEngine.execute之前加一道路由判断当模型的tool_name精确匹配失败时把原始用户意图传进来如果能匹配到候选工具就自动补一刀修正再执行候选工具。这种策略实现成本低、效果立竿见影我建议先做这个。再讲一下向量语义路由的思路不是为了炫技而是工具多了以后关键词实在覆盖不过来。做法是启动时用embedding模型把所有工具描述切成向量存进向量数据库请求来的时候把模型的原始意图或参数描述也embedding一下用余弦相似度取Top-K。代码层面只需要在ReachEngine里加一个_semantic_search(intent, top_k)方法背后接FAISS或Chroma都可以。需要注意的点是向量路由只能作为候选生成器最终让谁执行最好还是拉工具描述的完整版再让模型选一次确保不会在语义相近的工具之间误选。3.4 接入主流Agent框架这一节讲怎么把独立的Reach层接到你正在用的Agent框架里。如果你用的是OpenAI的Function Calling逻辑很简单在Reach层维护的工具描述列表里把字段格式转换成OpenAI的functions格式然后在代码里把模型返回的function_call.arguments解析出来传给ReachEngine.execute即可。MCPModel Context Protocol风格的接入也大同小异把MCP的ToolSchema转换成我们内部的tool_def再注册进ToolRegistry执行时通过MCP client调用远端工具Reach层的鉴权和路由逻辑完全复用。不夸张地说Reach层之所以值得做就是因为这一层天然是“格式翻译”的最佳位置。上面对话模型下面接各种异构工具格式转换只发生在这一个地方。别的地方改来改去最后一定有一堆屎山。下面给一个OpenAI风格的适配示例def to_openai_functions(registry: ToolRegistry): functions [] for name, item in registry._toolsitems(): d item[definition] functions.append({ type: function, function: { name: d[name], description: d[description], parameters: d[parameters] } }) return functions这样Reach层注册的工具直接就能给OpenAI的ChatCompletion传参不需要在Agent业务代码里额外写映射。3.5 回退与自愈让系统不容易崩Agent系统具备回退与自愈能力是“能用”和“好用”的分水岭。回退的目的不是让每次调用都成功而是保证失败的时候Agent能拿到一个“可以继续推理下去”的反馈而不是一个死板的异常。我建议在ReachEngine里增加一个execute_with_fallback方法它的逻辑是优先精确匹配工具名失败走语义路由召回候选工具再失败走更简单的“通用调用”。代码示例如下def execute_with_fallback(self, tool_name: str, args: dict, raw_intent: str None): # 第一层精确执行 result self.execute(tool_name, args) if result[status] success: return result # 第二层关键词路由修正 if raw_intent: candidates self.keyword_router.route(raw_intent) if candidates: for name in candidates: if name ! tool_name: result self.execute(name, args) if result[status] success: return result # 第三层告诉模型换一种方式 return { status: needs_clarification, message: f直接调用{tool_name}失败且未找到合适的替代工具。请根据以下信息调整策略{result[message]} }在这套机制里第三层返回的needs_clarification非常关键。模型收到这样的返回后可能会建议用户换一个查询条件也可能会换一个思路去调用其他工具。比如用户说“帮我查一下上海明天穿什么”模型先调了get_weather但缺少城市精确名拿到needs_clarification后模型就会去调一个“城市别名匹配”工具先把“上海”标准化再去查天气。这就是自愈的雏形本质就是给模型提供足够的反馈信息让它有机会纠错。4. 常见问题与排查技巧实录4.1 高频问题速查表实际用了这么久我把遇到过的典型问题整理成一个表格你可以直接对照排查。问题场景现象根因解决思路模型总选错工具十几个工具时经常调用A实际应该用B工具描述语义重叠、边界含糊重写描述加入“何时使用/何时不要使用”的明确句式参数频繁缺失模型调用工具时漏填必填参数参数描述不够具体或参数名有歧义给每个参数补充示例值必填参数标进description里工具调用超时外部API偶尔超过5秒Agent任务失败单次调用没有超时控制在ReachEngine里加默认超时和重试见前文代码上下文膨胀工具多后每轮Prompt token消耗剧增所有工具完整描述都塞给了模型改成动态发现先给摘要决定调用后再展开全文权限越界Agent调用了不该调的敏感工具工具列表没有按身份过滤用Agent身份过滤可感知工具拿不到描述就调不了失败信息晦涩模型拿到Exception后没法继续错误透传给了模型原生堆栈错误码用户友好消息的格式参考前文errors字段工具循环调用模型反复调用同一个工具参数不变回退逻辑死循环或模型得不到有效新信息增加调用幂等去重对相同参数在短时间内直接返回缓存结果日志缺失难复盘用户反馈结果不对无法定位哪一步出问题Reach层没有统一日志和trace_id所有请求记录trace_id链路日志统一JSON格式4.2 避坑心得工具数量与描述质量的平衡一个常被忽视的事实是Reach层的工具数量并不是越多越好。工具多了模型做选择的难度指数级上升。我的经验阈值是单次会话中能让模型感知到“摘要级描述”的工具数量控制在20个以内完整描述展开的数量控制在5个以内。超过这个范围就要考虑用分组、命名空间或子目录的方式让工具在大类上先分野。比如所有查询类工具都以query_开头所有写操作都以write_开头模型在粗匹配时成功率会高很多。描述质量方面一定要安排定期review。每两周过一遍工具描述看哪些工具从来没被模型调用过多半是描述写得让模型看不懂“什么时候用它”。另外新工具上线后不要立刻全量开放先在灰度Agent上放量跑一天看路由命中率和调用成功率再决定转正。这个习惯能避免很多线上事故。4.3 从日志里读懂Agent“想法”最后分享一个实战技巧通过日志反推Agent的决策过程。我通常会在Reach层的日志里加一个字段叫model_rationale让模型在决定调用工具之前先输出一句“为什么这么判断”然后再输出调用请求。这个字段对线上问题排查的价值是巨大的。有一次用户投诉说“我让Agent帮我改订单地址它却去调用取消订单接口了”。从日志里看模型的rationale写的是“用户要求修改订单但这个接口支持修改地址和取消订单我认为取消操作更符合用户意图于是调用了取消接口”。这不怪模型是工单描述里“修改”和“取消”这两个词的条件边界没有写清楚。修复方式就是更新这个工具的description加上“当用户要求取消时使用修改请使用另一个工具”。这类问题只有靠rationale才能快速定位到“模型的思路哪一步跑偏了”没有这个字段你只能对着工具调用的结果瞎猜。4.4 上线前必做的三轮演练Reach层上线前我建议做三轮演练每一轮的目标不同。第一轮是单工具跑通。每个工具独立调用三次验证正常路径、缺参路径、异常路径下的返回结构是否符合预期。第二轮是混合对话演练。模拟真实用户连续对话中间穿插了涉及多个工具需求的长对话看模型在上下文中是否还能准确选择工具以及工具切换之间的状态是否混乱。第三轮是故障演练。专门把外部服务搞挂看Reach层会不会陷入无限重试、Agent能不能主动告知用户“服务暂时不可用”而不是傻傻地反复请求。这三轮跑完你才敢说Reach层可以接真实流量。最后说两句大实话从我自己的体会来说Agent-Reach这类东西不是做一个“组件”就完事了它是一种把Agent从概念验证推向生产的组织方式。你越早把工具接入逻辑收拢到一个统一层后面加工具、加权限、做审计就越省力。我记得第一次给项目接入Reach层的时候最大的感觉不是代码写得多优雅而是终于不用在业务代码里到处找function dispatch了。踩过几次坑之后我也形成了几个固定的习惯工具描述上线后第二天必看路由命中率会话里工具数量一定压着20个以内每次线上事故复盘一定先拉trace_id链路。如果你想给现有Agent系统加上这层能力我个人的建议是从最小版本开始先注册5个工具把路由、回退、日志这三件事跑通再逐步把现有工具迁移进来不要试图一口气做完。最后再分享一个实用小技巧Reach层接入外部系统时一定要把所有请求都走公司的统一网关这样限流、熔断、鉴权都可以复用网关能力Reach层自己只需要做业务层权限和路由就够了省下来的精力足以让你把重心放到工具描述和路由策略的优化上。
阅读完成 · 觉得有帮助?
咨询建站