做企业级Agent协同系统之前,我一直以为最难的会是模型选型和推理优化这类“硬核”问题,真正动手之后才发现,最扎心的是Agent之间怎么说话、出了问题到底该找谁。A2A协议(Agent2Agent Protocol)解决的是前半截,人机责任链解决的是后半截。这篇文章不聊空泛概念,直接讲我落地这类系统的完整思路,从A2A协议的Agent Card、消息对象、任务状态机,到怎么把人工审批嵌进Agent工作流里,再到注册中心、路由编排、超时熔断这些藏在真实业务里的细节。适合正在设计多Agent平台的架构师,也适合准备把Agent接进核心业务流程的技术负责人。
1. 企业级Agent协同:为什么协议层不能自己拍脑袋
1.1 多个Agent不等于协同系统
很多团队做多Agent,第一步就是各自定义一套通信方式,结果项目跑两三个月就会发现变成了“方言大会”。A调B用的是HTTP加自定义JSON,B调C走的是消息队列,C调D直接塞了个内部SDK,每个Agent之间都靠“人情文档”维系,改一个字段要拉一个会。
我见过一个真实案例,三个Agent组成的“协同系统”,联调整整花了一个季度。问题根本不是模型回答不好,而是A发给B的消息,B根本解析不出来,因为两边的字段名都叫orderId,但一个传字符串一个传对象。更麻烦的是,任务执行到一半,下游Agent挂了,上游Agent还在傻等,也没有状态概念,全靠互相ping。这种集成方式,本质上还停留在“把多个服务用脚本粘起来”的阶段,不是协同。
企业级协同的第一件事,就是把通信协议定死,让每个Agent都按照同一套规则声明自己会什么、怎么调用、任务执行到哪一步了。这就是A2A协议出现的意义。它解决的是Agent和Agent之间的“握手”问题,让不同团队、甚至不同厂商开发的Agent,能在同一个体系里互相发现、互相协作。
1.2 A2A协议为什么值得押注
A2A(Agent2Agent)是Google在2025年牵头推出的开放协议,目标就是给Agent之间通信定标准。它基于JSON-RPC 2.0,走HTTP传输,核心思路是“任务驱动”:一个Agent发起任务,另一个Agent处理任务,整个生命周期都有明确状态。这个设计思路和我们做企业集成的经验很对路,因为任务有状态、有结果、有失败重试,才能纳入运维体系。
可能有同学会说,我们自己定义一套协议不也挺好?短期看确实可以,但长期有三个问题绕不开:一是招人成本高,每个新人都要重新学你的“独有方言”;二是生态兼容性差,你没法直接接第三方Agent能力,也没法被别的平台集成;三是协议设计中的坑,比如幂等、状态迁移、消息格式定义,你都得自己踩一遍。A2A协议至少要帮你把这些通用问题兜住。
这里要专门说一句,A2A和MCP(Model Context Protocol)不是替代关系,而是互补关系。MCP解决的是Agent怎么调用工具、怎么访问数据,A2A解决的是Agent和Agent之间怎么协作。打个不精确的比方,MCP是给Agent装上手和眼睛,A2A是给Agent配上对讲机。两者在真实项目里往往同时出现,别把它们搞混。
版本上,A2A从0.3演进到1.0,最直观的变化是Agent Card这类元数据的规范更严格了,安全与授权方面的要求也更明确。对企业用户来说这是好事,因为协议越严谨,越适合用来承载真实的业务链路。
2. 把A2A协议掰开看:Agent Card、消息模型与任务状态机
2.1 一张Agent Card搞定能力发现
A2A协议里,每个Agent都要对外发布一张“身份证”,叫Agent Card。这是一份JSON文档,描述了Agent的基本信息、能力列表、调用地址和安全要求。其他Agent拿到这张卡,就知道“对方能干什么、该怎么调用”。
Agent Card里的关键字段,我按落地经验排个优先级:
name:Agent的名字,注册中心里做唯一标识,命名规范一定要早点定。description:用自然语言描述这个Agent擅长处理什么场景,比如“负责查询订单状态并处理售后申请”。别小看这段描述,其他Agent在做任务路由时,很可能就是靠它判断要不要把任务交给你。url:Agent服务的访问地址,注册中心和调用方都靠它找上门。capabilities:声明Agent支持的能力,比如是否支持流式输出、是否支持主动推送通知。这决定了调用方能不能用长连接模式做实时交互。skills:更细分的能力列表,每个skill可以有自己的描述和输入输出模式,适合做大能力拆解。authentication/authorization:说明调用这个Agent需要的身份认证方式,企业环境里几乎是必填项。
在企业内部落地时,Agent Card除了做注册,更实用的价值是充当“能力目录”。开发新Agent之前,先查一遍现有Agent Card,很多时候会发现你要的能力已经有了,直接调用就行,不用再重复造轮子。我看过很多团队内部有六七个Agent,功能互相重叠,就是因为大家压根不知道别人做了什么,而Agent Card能把这种重复建设成本压下来。
2.2 消息、任务、Part与Artifact:四个对象怎么协同
A2A协议的核心数据模型有四个对象,刚开始接触容易绕,我用一个订单查询场景把它们串起来。
首先是Task,也就是一次完整的工作单元。比如“查询订单OD20250618001的物流状态”,这条Task从客服Agent发给订单Agent,就开启了一段协作。
Task里装着Message,Message是Agent和Agent之间对话的基本单位,里面带role字段,标识是哪个Agent发的。每个Message又由若干Part组成,Part可以是TextPart(一段文本)、FilePart(文件引用)、DataPart(结构化JSON数据)。这一步的灵活度很关键,因为Agent之间既要传递自然语言,也要传递结构化数据。
订单Agent处理完Task之后,会生成Artifact,也就是任务的产出物,比如处理完的订单数据、生成的报表文件。Artifact和普通消息的区别在于,它代表任务执行的“完成品”,后续Agent可以直接拿去做下一步处理。
这四个对象的协作关系,简单说就是:发起方创建Task,Task里包含Message,Message由多个Part组成,执行方处理完后产出Artifact。设计得比较干净,没有引入复杂的概念,但覆盖了Agent协作的大部分场景。
2.3 任务状态机如何支撑人机协作
我之所以觉得A2A协议适合企业级场景,很大原因是它把任务状态定义得足够清晰。一个Task从创建到结束,会经历这几个状态:submitted(已提交)、working(执行中)、input-required(等待额外输入)、completed(已完成)、failed(失败)、canceled(已取消)。
这里面最有价值的是input-required状态。它表示Agent执行到一半,碰到需要外部输入才能继续的情况。放到企业场景里,这个状态就是天然的“人工介入点”。比如退款Agent计算出一笔退款金额,按照公司授权规则,超过5000元需要部门总监审批,这时Agent就可以把任务状态置为input-required,然后等待人类审批通过后再继续执行。
有了状态机,我们还可以做两件重要的事:一是任务状态持久化,每个状态变更都写入日志,审计可以随时回放某个Task从创建到结束的完整轨迹;二是异常处理,比如Task卡在working状态太久,可以触发超时机制,把任务标记为failed并发告警。
所以在我的架构里,A2A的状态机不只是协议的一部分,它还是整个责任链系统的地基。后面要讲的人工审批、超时升级、熔断,全是靠这套状态机支撑的。
3. 人机责任链:把“谁来负责”写进系统
3.1 为什么需要责任链:AI越强,责任越不能模糊
企业环境和个人玩Agent最大的不同,就是出了事必须有人负责。用户投诉了、财务损失了、监管问询了,系统不能一脸无辜地说“这是Agent干的”。Agent只是工具,但使用工具的过程和结果,必须映射到具体的人和流程上。
人机责任链这个概念,我理解为:把系统中每个Agent可执行的动作,都对应到明确的授权边界、审批节点、回退策略和审计日志上。简单说,就是给Agent画一个圈,圈内它可以自己跑,圈外必须有人点头。
我常跟团队打个比方:企业里的Agent,定位应该像个能力很强但还没转正的实习生。你交给它查资料、写草稿、算数据,它干得又快又好;但如果它要对外承诺客户、操作资金变动、删除生产数据,你就必须给它配一个“带教导师”,重要事项签字确认,全程留痕。责任链就是把“带教导师”这套机制数字化、流程化。
3.2 责任链的分层设计:操作层、审批层、审计层
我落地责任链时,习惯把整个体系分成三层来看。
第一层是操作层,对应Agent能自主执行的动作。这类动作的特点是影响范围可控、可回退、不涉及重大利益,比如查询信息、生成报告草稿、做数据统计分析。这层追求的是效率,目标是让Agent尽量少打扰人。
第二层是审批层,对应需要人类介入才能执行的动作。这类动作的特点是影响面大、不可轻易回退,比如对外发送正式报价单、执行退款、删除用户数据、发布生产配置。这层追求的是控制,Agent负责把方案准备好,人来拍板。
第三层是审计层,对应全流程的留痕。所有Agent动作、任务状态、审批记录、参数变更,都写入不可篡改的审计日志。这层追求的是可追溯,任何时间点我们都能回答“这个决定是谁在什么条件背景下做出的”。
举几个真实动作的分层示例:
| 业务动作 | 责任层级 | 说明 |
|---|---|---|
| 查询客户历史订单 | 操作层 | Agent自主执行 |
| 生成退款金额建议 | 操作层 | Agent产出建议,但不生效 |
| 执行退款(金额阈值内) | 审批层 | 按规则自动审批或转人工 |
| 执行退款(金额超阈值) | 审批层 + 审计层 | 必须人工审批并全量审计 |
| 批量删除用户数据 | 审批层 + 审计层 | 双人复核,全程留痕 |
这个表不是死的,每家企业要根据业务风险来定义哪些动作属于哪个层级。但整体的设计原则是一致的:能自动的尽量自动,不能自动的坚决人工,所有操作必须可审计。
3.3 用input-required状态嵌入人工审批
责任链怎么和A2A协议结合起来?答案是直接利用input-required状态。
当Agent流程运行到需要人类决策的节点时,责任链引擎会介入,做三件事:第一,把当前任务的状态置为input-required;第二,通过企业IM、邮件、审批系统等渠道通知对应的审批人,附上Agent准备好的上下文信息,比如退款金额、客户历史记录、风险提示;第三,等待审批结果。
审批人通过审批之后,引擎把人类的决策以Message的形式回传给原先的任务,任务状态恢复为working,Agent继续往下跑。如果审批人驳回,任务会转成failed状态,同时触发后续的异常处理流程,比如通知下游Agent不再执行、记录驳回原因。
这套机制我强烈建议配合两个策略一起用。一个是审批超时升级,比如二级审批两小时没响应,自动升级到一级审批人,避免单点阻塞。另一个是审批上下文聚合,不要让审批人只看到孤立的一条“请审批”,要把Agent决策的依据、候选人、相关业务数据一起打包给他,否则审批人不敢点同意,还是得去翻系统,效率一样低。
4. 企业级架构落地:注册中心、路由编排与系统拓扑
4.1 最小可行架构:Registry + Broker + 责任链引擎
聊完协议和理论,讲一讲我在企业里实际落地的架构。一套能用起来的多Agent协同系统,我建议至少要包含四个部分。
第一部分是入口网关,负责接收来自业务前台、用户对话、定时任务等各种来源的请求,做初步的身份认证和负载分发。
第二部分是Agent Registry(注册中心),用来管理所有Agent Card。Agent启动时把自己的Card注册上来,Registry做健康检查、能力索引和运行时路由查询。其他Agent要找人帮忙,先来Registry查卡,拿到对方的url和授权要求再发起调用。
第三部分是任务编排层,我习惯叫它Broker或者编排引擎。它负责按业务流程编排多个Agent的执行顺序,处理任务的路由、状态跟踪、重试和结果聚合。这一层相当于整个协同系统的中枢神经,业务规则写在这里,而不是散落在各个Agent里。
第四部分是责任链引擎,单独拆出来作为一个服务。它负责判断当前任务是否需要人工审批、需要哪个角色审批、超时之后怎么升级,同时把审批动作和审计日志打通。
这里要特别强调一个设计原则:不要在Agent内部写复杂的业务流程编排。Agent只负责自己领域内的专长,比如订单Agent只处理订单相关逻辑,流程怎么串是编排层的事。否则一旦业务链路调整,你得改好几个Agent并重新发布,排错成本极高。
4.2 技术选型与关键参数配置参考
技术选型上,如果团队没有太重的历史包袱,我建议直接采用主流做法:Agent服务用Python或Java都没问题,重点是Agent之间的通信统一走A2A协议。传输层用HTTP + JSON-RPC,需要实时流式交互的场景再加一道WebSocket。
下面给出一份我在项目中用过的参数配置参考,具体数值按业务量调整,但思路可以复用:
| 配置项 | 建议值 | 说明 |
|---|---|---|
| Agent调用超时 | 10s | 单次Agent调用超过10s就触发重试或降级 |
| Agent调用重试次数 | 3次 | 重试需要配合幂等键,防止重复执行副作用 |
| 任务整体超时 | 30min | 超过后视为异常任务,进入人工处理队列 |
| 人工审批超时 | 2h | 超过后触发升级流程 |
| 审批升级次数上限 | 2级 | 避免无限升级刷屏 |
| 消息体大小限制 | 1MB(内联Part) | 大文件用FilePart引用,不内联传输 |
| 并发任务上限 | 按Agent配置 | 防止单个Agent被打垮 |
配置里最容易被忽视的是幂等。A2A协议里,每个Task有唯一的taskId,调用方在重试时要带上这个ID,接收方要做去重。比如退款Agent收到一条Task,中途网络断了,重试时又发一条一模一样的Task,如果没有幂等判断,就会发生重复退款的事故。这块一定要在Agent端做扎实。
4.3 一个完整场景:工单处理链路的端到端实现
空讲架构不如跑一个真实场景。以“客户投诉工单自动处理”为例,完整链路走一遍。
业务流程是这样:客户提交一条投诉工单,内容包括“我上月买的订单还没收到货,我要退款”。系统需要联动客服Agent、订单Agent、财务Agent和人工审批。
第一步,客服Agent接到工单,先做意图识别,判断这是一个售后退款请求。然后它去Registry查一下,看哪个Agent能处理订单查询,发现订单Agent的Card描述匹配,就发起一条Task,任务内容是“查询订单号XXX的物流状态和退款资格”。
第二步,订单Agent接收Task,状态从submitted变成working。它执行完毕后,把订单状态、支付金额、物流轨迹封装成Artifact返回。客服Agent拿到结果,发现订单确实超过预计送达时间,符合退款条件。
第三步,客服Agent调用财务Agent,计算退款金额。财务Agent算完给出退款建议金额,比如298元。这时责任链引擎介入,根据规则判断:298元低于5000元的审批阈值,按正常授权应该可以自动放行。但这里我们设置了另一个条件——该客户近30天内有两次退款记录,属于高风险用户,所以退款必须人工审批。
于是任务状态从working变为input-required,责任链引擎生成一条审批通知,推送给客服主管。通知里包含工单上下文:退款金额、客户历史、风险标记、退款方案。主管审核后点通过,引擎把审批意见回传给财务Agent,任务恢复working,财务Agent执行退款,完成后任务进入completed状态,全程审计日志自动归档。
这个场景走完,你会发现A2A协议承担的是“通信+状态传输”,责任链引擎承担的是“决策控制+人工介入”,各司其职,不互相干扰。而最终的退款审批记录、Agent执行记录、状态变更记录,都能在审计系统里一键导出,满足合规要求。
5. 常见问题与排查技巧实录
5.1 高频问题速查表
多Agent系统跑起来之后,日常运维会碰到不少问题,我把高频问题整理成了速查表:
| 现象 | 可能原因 | 排查建议 |
|---|---|---|
| Registry里搜不到某个Agent | Agent服务未注册或健康检查失败 | 检查Agent的url是否能通、注册是否带对了Agent Card |
任务一直卡在working | 下游Agent超时或死锁 | 查看任务状态变更日志,定位阻塞Agent |
| 审批节点长时间无响应 | 审批人没收到通知或IM通知失败 | 检查通知渠道配置,设置超时自动升级 |
| 消息体过大导致超时 | 内联了过多文本/文件内容 | 改用FilePart的URI引用,减少内联传输 |
| 重试后产生重复执行 | 缺少幂等处理 | 确认Agent端是否用taskId做去重 |
| Agent之间误调 | Agent Card描述不精确,路由判断错误 | 细化description和skills,加上明确的触发条件 |
第一条是很多团队最容易踩的。Agent Card里的description字段,你别写得太抽象,比如“提供客户服务支持”这种,别的Agent根本判断不了什么场景该调用你。要写成“处理客户订单查询、物流跟踪、售后申请,输入参数为订单号,输出为订单状态与物流轨迹”,这样才能减少路由误判。
5.2 几条实战避坑经验
最后分享几条我从项目里踩出来的教训,希望你能绕开。
第一条,别让一个Agent承担太多职责。我最早把订单查询、物流跟踪、退款计算放在一个Agent里,想着省事儿,结果发现任务状态一复杂,排查问题就要翻它内部的长链路日志。后来拆成三个Agent,每个都只做一件事,不仅调试容易,责任边界也更清楚了。
第二条,人工审批节点一定要有超时和备选通道。我踩过一个坑,审批消息只发了企业IM,结果审批人出差没看到,整个工单链路卡了一整天。后来所有审批节点都加了超时升级机制,超过30分钟自动邮件+短信通知,超过2小时升级到上级审批人,再也没出现过任务卡死的投诉。
第三条,审计日志从第一天就要设计好,别等项目大了再补。A2A任务状态、Agent调用参数、审批人操作记录,这些都要带上时间戳和唯一流水号。别等出事再想着“能不能追溯”,那时数据早被覆盖了。审计日志也不建议只存在数据库里,定期归档到对象存储,保留至少一年是企业级的基本要求。
第四条,先小范围试跑,再横向铺开。不要一上来就规划十个Agent协同的宏大蓝图。我习惯先选一个真实业务链路,用两个Agent加一个审批节点跑通,验证A2A协议、责任链和审计流程都能正常运转,再逐步扩展。这样每次加新Agent,都是在验证过的骨架上加肌肉,出问题的概率小很多。
这套体系我实际落地过几次,最深的体会是:Agent协同系统的瓶颈,从来不在模型能力,而在组织能不能接受“让机器跑得快、让人管得住”这个分工。A2A协议给了技术上的共同语言,责任链给了业务上的安全感。如果你正准备做类似规划,我的建议是先别急着上十个Agent的大秀,老老实实把两个Agent通过A2A协议跑通,再塞一个审批节点进去,完整走一遍端到端流程。走到那个节点,你一定会对这套体系产生完全不一样的理解。