ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Agent-Reach:为多Agent系统打造的服务发现与路由通信底座

2026/10/6 17:27:20 拓冰建站 浏览量
Agent-Reach:为多Agent系统打造的服务发现与路由通信底座 Agent-Reach 这个名字乍一看挺像营销工具的但它实际上是我折腾了大半年的一个 AI Agent 互联协议项目。做 AI 应用的同学应该都有这种体会单机跑一个 agent 不难难的是当你手里有十几个来自不同框架、不同团队、不同运行环境里的 agent想让它们自动互相找到、按需调用能力的时候整个系统就迅速变成一团乱麻。Agent-Reach 解决的正是这个问题——它给分散部署的 agent 提供一套发现、路由、鉴权的通信底座让 agent 之间能像微服务一样互相寻址、建立会话、协同完成任务。项目适合正在做多 Agent 系统、 Agent 平台或智能工作流编排的团队参考也适合想搞懂 Agent 互联原理的开发者当成一份入门材料来读。1. 项目动机Agent 之间的连接层为什么值得单独做先聊点背景。过去一年圈子里涌现了大量单 Agent 应用写代码的、做数据分析的、管日程的、生成图文的单拎出来个个都能干活。可真到生产环境里你会发现这些 agent 其实是“孤岛”。每个 agent 内部把规划、工具调用、记忆都做得很完整但对外基本没有标准接口A agent 想请 B agent 帮个忙要么人肉搬运结果要么硬写一套私有 HTTP 调用然后陷入接口维护的泥潭。我把这个阶段称为“多 Agent 的蛮荒期”。大家拼的不是单点能力而是怎么把一堆能力组织成一个有机整体。市面上有 agent 编排框架、有工作流引擎它们解决的是“流程怎么走”的问题但始终有一个基础问题没人好好管agent 之间到底怎么发现彼此、怎么声明自己能干什么、怎么安全地把请求送到正确的实例上Agent-Reach 的定位非常明确它不做规划、不抢框架的活只做“连接层”。你可以把它理解成 Agent 世界的 DNS 加路由网关——每个 agent 启动后把自己的身份和能力注册上来其他 agent 只需要知道一个逻辑名字就能找到目标并发起调用。至于对方内部是用 LangChain、AutoGPT 还是自研框架完全不用关心。这个设计取舍我斟酌了很久。最初差点把任务调度、状态机、多轮协商都塞进来后来发现这是贪多嚼不烂。把连接层做薄、做稳让上层框架有足够的自由发挥空间反而更符合生态规律。一个协议如果什么都管最后一定什么都管不好。Agent-Reach 只承诺三件事能发现、能路由、能被信任其余全部留给调用方。2. 核心架构拆解四个关键模块怎么分工整个系统的核心可以拆成四块彼此独立、通过一套明确的消息协议协作。没有分布式大佬那种精巧到炫技的架构每一步都是被真实部署逼出来的。2.1 注册与发现RegistryRegistry 是所有 agent 的中枢登记处负责记录当前有哪些 agent 在线、在哪个地址、提供什么能力。每个 agent 启动后必须向 Registry 发送注册请求并携带自己的 agent_id、连接地址、能力清单。为了及时清理死掉的实例我设计了心跳机制agent 每 15 秒发一次心跳超过 45 秒没收到心跳Registry 就把该实例标记为不可用并从发现结果里摘掉。状态存储这块我采用了分层方案在线状态这类短时效数据放 Redis用 TTL 自然过期能力清单和 agent 元数据放 SQLite 或 PostgreSQL便于做版本回溯和审计。为什么不全放 Redis因为能力清单是相对稳定的配置数据一旦注册中心重启就全丢会引发灾难数据库落盘才能保证重启后快速恢复。2.2 能力声明Capability Manifest这是 Agent-Reach 最核心的数据模型。每个 agent 必须用一个 YAML 文件描述自己的能力格式固定包含能力名、描述、输入输出 JSON Schema、超时时间。JSON Schema 是灵魂——有了它调用方才能在做参数校验和结果解析时不再靠猜。我当时特意让 manifest 跟随代码仓库走而不是由注册中心动态改。能力是代码的公开契约既然是契约就应该走代码评审、版本管理不能让人在后台悄悄改一个字段就把线上行为变了。每次发布新版本agent 启动时带上 manifest 的版本号Registry 会记录当前生效版本并保留历史版本用于回溯。2.3 消息路由与会话管理注册只是第一步真正的难点在路由。Agent-Reach 采用了两层路由模型第一层按 agent_id 定位目标实例第二层按能力名定位具体动作。消息在协议层被表达成 Reach 地址格式类似reach://data-fetcher/query_metrics语义就是“找到>docker run -d --name reach-registry \ -p 8866:8866 \ -e REACH_STORE_DSNsqlite:///data/reach.db \ -v reach-data:/data \ reach-registry:1.4.2Registry 对外暴露两个端口8866 是 WebSocket 接入端口agent SDK 连这个8867 是管理端口用于查看在线状态和健康检查。首次启动后打开http://localhost:8867/health能看到服务状态和当前注册的 agent 数量就说明注册中心起来了。3.2 让 agent 注册并声明能力给 report-bot 写一份 manifest.yamlagent_id: report-bot display_name: 报表生成助手 version: 1.2.0 description: 生成周报月报的数据摘要 capabilities: - name: generate_report description: 根据周期生成报表摘要 input_schema: type: object properties: period: type: string description: 周期如 2025-03 required: - period output_schema: type: object properties: summary: type: string timeout_ms: 30000然后写接入代码。SDK 提供了 Python 版本核心就四行from agent_reach import AgentReachClient client AgentReachClient( registry_urlws://registry.internal:8866, agent_idreport-bot, private_key_path./keys/report-bot.pem, ) client.register_from_file(manifest.yaml) client.start()注册成功后在管理端页面能看到 report-bot 出现在在线列表里点进去还能看到它声明的能力。这里有个小细节我反复提醒自己manifest 里的能力名一经发布就不要随便改名否则所有调用方全部断链。真要大改宁可新起一个能力名、把旧的标记为 deprecated。3.3 跨 Agent 调用的最小样例现在 report-bot 要调用>result client.call( targetdata-fetcher, capabilityquery_metrics, payload{period: 2025-03}, timeout30, ) print(result.summary)SDK 内部替你完成了寻址、鉴权、建连、WebSocket 通信、超时控制这一整套流程。实际体验下来最容易被坑的是超时设置。如果被调能力内部还要再调其他 agent链路一深超时就要分层设置最外层给 30 秒内层每个环节只给 20 秒保证外层超时时内层早就死透了不会出现资源悬挂。3.4 跨网段部署的网关模式单机房部署没问题但真实场景里 agent 往往分散在不同 VPC、不同业务区网络层面未必能直连。Agent-Reach 额外提供了一个 reach-gateway 组件扮演协议层中继的角色。SDK 不直连 Registry而是先连就近的 gateway由 gateway 转发注册信息和消息。网关模式不是让你去绕网络限制而是解决业务网络里常见的“不能直接点对点”的问题。它只做协议转发不改变鉴权逻辑、不做内容解密所以安全边界还是保持原样。部署时建议每个网络区域各放一个避免单点故障影响全局。4. 实测踩坑常见问题与排查思路运行这半年我把最有代表性的几个坑整理在下面都是真实环境里会反复遇到的。4.1 注册了几秒就掉线现象agent 在管理端能正常注册但几秒后状态就变成离线再注册再掉无限循环。排查过程先看心跳日志发现 SDK 在发送心跳时抛出了 WebSocket 连接已关闭的异常。再看 Registry 的接入日志发现连接被服务端主动断开。最后定位到是 Nginx 代理层设置了空闲超时 60 秒而 agent 心跳周期是 15 秒看起来没问题但问题出在连接建立后 SDK 先注册再启动心跳中间有个空窗期超过了代理的判定阈值。解决方案是让 SDK 在注册前先发一条 ping 占位确保代理不会把连接当成空闲连接回收。4.2 消息乱序导致任务状态错乱长任务走异步模式后有段时间上层业务反馈报表内容对不上。查了半天才发现问题不在 Agent-Reach而在上层框架用了多个线程处理同一会话的事件处理顺序无法保证。Agent-Reach 在协议层保证了单连接内的消息有序但一旦业务侧开了多线程消费顺序就不可控了。解法是在事件消息里增加 session_seq 序号消费端按会话做内存重排。4.3 权限 scope 配得太宽测试环境出现过一次越权一个只该读数据的 agent由于 token 里写的是call:*:*竟然能触发另外一个 agent 的数据删除能力。这类问题在测试环境几乎发现不了因为权限越小越容易踩到缺失权限的报错大家为了跑通流程就顺手放开了。我的教训是上线前必须做一个权限最小化走查用脚本扫出所有通配 scope逐个确认存在的必要性。4.4 问题排查速查表现象可能原因优先排查手段注册后立即掉线中间代理空闲超时 / 心跳启动晚抓接入日志确认断开方向调用超时但目标 agent 正常链路层次多、超时配置冲突检查调用链各层 timeout_ms消息重复执行客户端重试机制叠加服务端重放检查消息去重字段 session_seq注册失败 401证书签发时间与服务器时区偏差校验本机时间重新签发 token管理端看不到新注册能力manifest 版本号未变化导致缓存未刷新强制递增 manifest 版本这种速查表我建议每个团队按自己的实际故障维护一份比看十篇文档都管用。5. 扩展方向和 MCP 生态的融合最后聊聊 Agent-Reach 未来可能的走向。最近 MCPModel Context Protocol热度很高它解决的是“agent 怎么调外部工具”的问题Agent-Reach 解决的是“agent 之间怎么互相调用”的问题两者天然互补。我最近在尝试做一层适配器把 Agent-Reach 注册的每个 agent 能力转换成 MCP 工具描述格式让任何兼容 MCP 的客户端都能像调用工具一样调用远端 agent。相当于给 Agent-Reach 套了一个 MCP 外壳既保留了 agent 互联的寻址能力又能接入庞大的 MCP 工具生态。目前原型已经能跑通效果比我预期好。另一个方向是多组织联邦注册。当两个公司或两个部门各自维护一套 Registry又要相互调用时联邦模式比全局统一注册更现实。每个 Registry 可以配置对等信任关系只同步对方公开的能力摘要具体调用请求仍然由各自内部路由处理。这样既隔离了管理边界又打通了业务协作。我在实际维护过程中最深的感触是互联协议这种东西前三个月拼的是功能后半年拼的全是细节。心跳、重试、超时、权限、审计每一项单看都不难但合在一起稳定性就是从这些枯燥的细节里长出来的。Agent-Reach 当前版本我还在持续迭代代码里那些注释和排查日志基本都是深夜真实事故留下的痕迹。如果你也在做多 Agent 系统建议先把连接层想清楚再谈上层智能否则业务跑起来之后再回头补底座的课代价会大得多。