这不是一次简单的角色对调。当谷歌ADK首次作为主控方,通过A2A协议调用亚马逊Bedrock上的Worker智能体时,暴露了六个互操作性缺陷——其中五个,在本地开发环境的任何测试都无法捕捉。
此前两次基准测试都以Bedrock为主,ADK为从。这次反转的角色互换,理论上只是换个部署方向——核心域逻辑完全框架无关,比较算法原封不动。结果却撕开了六个缺陷,指向一个更深的结论:绝大多数A2A演示停在“HTTP 200返回了”这一步,那只是冒烟测试,根本算不上互操作性基准。
远程验证的成本,必须和工作成本分开
本次基准测试跑了三种模式,就是为了把远程校验开销从实际工作开销中剥离出来。汇率比较走算术逻辑,不用模型判断数值是否匹配——金额和汇率都用Decimal精确表达,模型根本没机会在两个数字之间摇摆。
这让基准框架本身足够干净。意味着如果调用失败,原因只能出在协议栈、传输层或信任链上,而不是模型幻觉或数值比较的模糊地带。
一个版本号差距,直接炸穿通信层
第一个缺陷在部署前就嗅到了,它决定了整个Worker侧的架构设计。
strands-agents的A2A实现锁死在a2a-sdk低于0.4版本,走的是A2A v0.3的message/send机制。而google-adk的A2A组件用到a2a-sdk 1.x版本,对应v1.0的SendMessage方法。v1.0客户端根本调不了v0.3服务端——Agent卡片本身不携带任何版本协商字段。
同一个版本分裂在上一轮测试中,曾迫使A2UI扩展从ADK智能体中剥离。这次从另一侧反方向再次出现,彻底暴露了A2A生态在版本一致性上的脆弱。
修复方式是:只用strands-agents负责智能体循环本身,A2A v1.0的服务端表层直接从a2a-sdk手写构建。Starlette的路由注册到create_agent_card_routes和create_jsonrpc_routes,完全绕过框架封装带来的隐藏依赖。同时,测试用例专门断言lockfile中a2a-sdk保持在1.x版本以上——任何一个依赖升级悄悄回退版本,都会被自动化测试当场拦截。
一个缺失的HTTP依赖,让容器启动即崩溃
第二个缺陷更隐蔽。Cloud Run容器构建一切顺利,所有本地测试绿灯通过,然后在生产启动时原地崩溃。
报错信息直截了当:ModuleNotFoundError——找不到sse_starlette模块。调用链追溯下来,ADK的to_a2a()方法内部引入了a2a.server.routes,而routes模块又依赖sse_starlette。这个依赖只随a2a-sdk的http-server额外选项安装。
无论是google-adk的a2a组件,还是裸装的a2a-sdk,默认都不拉取这个HTTP服务端依赖。代价是一次发布失败。现在主从两端的依赖声明都显式写入了a2a-sdk[http-server]——在多云环境中,隐式可选依赖就是定时炸弹。
联邦身份链路:不能靠本地密钥赌安全
协调器本身不持有任何AWS密钥,走的是联邦身份链路。Cloud Run的元数据服务器先发出Google OIDC令牌,再通过STS的AssumeRoleWithWebIdentity接口,交换成临时凭证,所有对Bedrock的请求都用SigV4签名。
这种设计意味着如果信任策略配置有偏差,或令牌交换的过期时间设得太短,远程调用就会沉默失败——本地开发时根本模拟不了这种身份链路。六个缺陷中,有五个恰好栽在这种跨云身份与网络边界上,本地模拟环境碰不到真实STS行为,也碰不到A2A协议栈的版本差异或HTTP依赖缺失。
当主从角色对调,所有沉淀在本地测试盲区中的假设都被推到了生产边界上。六个缺陷的出现不是意外,而是跨云智能体互操作进入真实部署阶段必须支付的学费。
热门跟贴