多 Agent 协作到底靠什么?从 Codex 内部机制到 A2A 企业服务

源码分析基于 OpenAI Codex 提交 d1e3f9dfe3d5f6105b7e4c3958b9bf2ac6c32818,不代表所有版本或某个桌面安装包。A2A 以本文核对的 1.0.0 规范为准。图中角色和任务均为通用示例;架构建议没有经过生产或互通测试。

给几个 Agent 分别起名"架构师""开发""测试",再让它们互相发消息,就能协作了吗?

真正需要回答的是:实例由谁创建?名字在哪里登记?消息发到哪里?等待期间程序在做什么?接收失败以后,谁知道任务没完成?

理解这些问题,也就能分清 Codex 的内部协作、A2A 协议和官方 SDK 各自负责什么。

1. 先分清:协议、SDK 与协作运行时

层次 主要职责 本文中的例子
通信协议 约定独立系统交换什么信息、如何交互 A2A
协议 SDK 用代码实现客户端、服务端和传输适配 A2A Java SDK
协作运行时 创建或调用 Agent,组织上下文、消息和执行 Codex 内部协作、各类编排框架

A2A 规定独立 Agent 系统之间的交互契约。Codex 的 collaboration 则是本文所分析的一套内部协作机制。"Codex 有具体实现"不等于"Codex 实现了 A2A"。 前面这条内部链路使用自身的注册与消息机制。A2A 规范、Codex 协作控制源码

类似地,A2A SDK 可以替应用处理协议通信,具体任务如何完成仍要由应用实现。它并不要求内部必须采用某一种 Agent 框架。

2. Agent 地址从哪里来?运行时维护路径与实例

角色配置与运行实例要分开看。"测试角色"描述职责和配置;一次真正创建出来的测试 Agent,还需要自己的运行上下文、标识和状态。配置一个角色,不等于已经启动了一个常驻服务。Codex 子 Agent 配置与编排

在本文的源码快照中,同一根任务树共享协作控制与注册信息。调用方指定子任务名,运行时结合父路径构造完整路径,并在创建过程中登记实例。

例如:

  • 当前调用方是 /root,子任务名为 testing,得到 /root/testing。
  • 当前调用方是 /root/architect,同名子任务得到 /root/architect/testing。

这些是运行时中的逻辑地址,不是文件夹,也不是 HTTP 地址。注册表维护路径、实例元数据及反向查询关系。路径构造、Agent 注册表

下面是据固定源码快照整理的简化逻辑图,展示创建操作涉及的对象,不展开内部执行顺序和错误分支:

所以,"架构师怎么知道测试 Agent 的地址"有具体的信息来源:创建工具的返回结果,以及查询已有实例的工具。并不是模型凭角色名称猜出一个地址。这一版本的 spawn 返回结果包含规范化后的 task_name。创建工具实现

3. target 负责路由,message 提供任务内容

下面是一次消息工具调用的参数示意,假设目标实例已经存在:

json 复制代码
{
  "target": "/root/testing",
  "message": "只读检查订单分页的边界行为,返回失败场景和依据;不要修改代码。"
}

target 让运行时找到接收者;message 是提供给接收 Agent 的内容。示例中的限制属于任务约定,实际文件和工具访问仍受运行环境约束。

消息投递成功,不代表测试已经执行。接收者需要结合上下文理解任务、请求工具执行,再根据真实结果作出判断。任务约定不能单独改变运行环境权限。

常用协作操作的区别可以这样理解:

操作 作用
spawn_agent 创建一个新的子 Agent
send_message 向已有实例投递消息
followup_task 继续分配任务,并可让空闲实例开始新的执行轮次
wait_agent 等待消息或状态变化,不等于指定任务必然成功

运行中的 Agent 会在合适的处理边界接收消息;不能把"已投递"理解为"立刻打断所有正在执行的工具"。消息工具实现

事件驱动,为什么源码里仍然能看到循环?

接收循环负责反复处理事件;是否轮询,要看没有事件时怎样等待。

在这条源码链路中,操作通过异步通道交给会话处理器,消息写入 mailbox 队列,再通过 watch 通知状态变化。等待端使用异步等待和超时机制。会话事件处理、邮箱与通知、等待工具

下面是据固定源码快照整理的简化逻辑图,展示消息与通知的关系,不表示真实线程拓扑:

队列保存消息,通知帮助等待者知道发生了变化,两者职责不同。没有消息时,等待端不持续主动检查队列,而是等待变化通知或超时等条件。

Java 开发者可以类比 BlockingQueue.take():队列为空时等待元素,而不是循环调用 isEmpty()。但它与 Rust 的异步任务等待并非同一种线程模型,也不能因此推断"每个 Agent 对应一个独占线程"。Java BlockingQueue

4. 接收失败与执行失败,需要分别处理

"在线程里 catch 住异常"只能说明异常得到了某种处理,还要继续确认任务状态是否正确、调用方是否获知结果。

发生的情况 应当确认什么
目标不存在或投递失败 调用方收到错误了吗,任务是否真的交出?
接收通道关闭 等待是否结束,实例是否仍可运行?
工具或业务执行失败 是否形成失败结果,下一步由谁决定?
提交中断或取消 执行是否已经停止,已有副作用是什么?

在本文快照中,可以看到投递错误的处理和终态通知路径;但不能据此宣称所有失败都会自动重试、所有实例都会自动重启。通知本身也不等于一套持久化、保证重投的消息系统。协作错误处理、完成通知

中断同样要看实际状态:发出了中断请求,不足以证明正在进行的操作已经全部停止。中断处理

5. 换成 A2A 后,通信边界发生了变化

假设一个 Java 服务负责需求分析,另一个 Python 服务负责代码检查。双方希望交换任务和结果,同时各自保留内部实现,就进入了 A2A 解决的问题域。

下面是根据协议整理的边界示意。两个服务可以部署在同一台机器,也可以独立部署:

A2A 的几个核心对象是:

对象 用途
Agent Card 描述能力、服务接口和认证要求
Message 一次交流,承载文本、文件引用或结构化数据等内容
Task 有标识、有状态、可跟踪的工作单元
Artifact 任务产生的报告、文件或结构化结果
contextId 关联一组相关交互,不等于双方共享模型上下文

发送消息后,服务端可以直接返回 Message,也可以返回 Task。对端内部用了几个 Agent、怎样选模型,属于对端的实现。A2A 核心概念、任务生命周期

A2A 有没有注册中心?

A2A 标准化 Agent Card。调用方可以通过已知地址、配置、目录服务,或约定路径 /.well-known/agent-card.json 获取卡片。目录服务可以集中管理卡片,但当前规范没有规定统一的目录 API。

这与 Codex 在创建实例时登记本地路径不同。A2A 调用方仍需先知道一个域名、卡片地址或可查询的目录。Agent 发现机制

A2A 是轮询还是事件驱动?

协议支持多种更新方式:查询任务状态;在服务支持时接收流式更新;或者配置支持的 Webhook 推送。JSON-RPC 和 HTTP+JSON 绑定的流式更新使用 SSE,gRPC 则使用服务端流式 RPC。异步与流式交互、gRPC 流式规范

这些方式都不规定服务内部必须使用什么线程池或队列。协议中的取消是请求取消,也不能直接推导出业务已回滚。取消语义

6. 放在一张表里,区别更清楚

维度 Codex 本文分析的内部协作 A2A
面向对象 同一根任务树中的实例 独立 Agent 系统
定位方式 任务路径及实例注册信息 Agent Card 中的服务接口
工作表达 协作工具参数、任务上下文 标准化消息、任务和产物
运行责任 Codex 的运行时与执行配置 各服务自行实现
更新机制 异步通道、邮箱、变化通知 查询、流式或推送
互通条件 遵守该运行时的内部机制 双方支持兼容的协议与能力

因此,不能给 Codex 套上一个 HTTP 接口,就认为它已经支持 A2A。若做适配,还需要处理消息转换、任务状态、结果与错误映射,以及身份和权限边界。这是集成设计要求,本文没有实现这样的适配器。

同时,内部协作使用本地机制,也不意味着 Codex 只能通过界面使用。它另有 SDK 和 App Server 等程序化集成入口。Codex SDK、App Server

7. 官方 Java SDK 能用于企业服务吗?

可以。官方 A2A Java SDK 已提供客户端和服务端支持,包含 JSON-RPC、gRPC、REST 传输,要求 Java 17+,采用 Apache-2.0 许可。协议规范版本与 SDK 发布版本需要分别核对。A2A Java SDK

一个初期企业 Agent 服务可以采用下面的建议架构。它不是 SDK 内部类图,也不表示图中能力安装依赖后就自动就绪:

SDK 负责协议接入。应用负责定义能力、执行业务和产生结果;生产运行还需要结合已有设施解决:

  • 身份与资源权限:认证调用者,并校验其对具体任务、数据和动作的权限。
  • 任务状态与恢复:保存必要状态,明确服务重启、执行超时和多实例之间如何协调。
  • 执行与重试边界:限制并发和等待时间;有写入副作用的业务必须考虑幂等,避免重试造成重复操作。
  • 运行证据:关联任务标识、业务请求和追踪信息,能够区分"请求已收到""任务已执行""结果已确认"。

这些是企业接入职责,不是 A2A 单独替应用完成的功能。官方企业指南也强调与既有身份、授权、网关和可观测性体系结合。A2A 企业接入指南

例如,一个"文档分析 Agent"可以先由普通 Java 代码接收任务、读取调用者有权访问的文档、调用模型并返回报告。只有内部步骤和角色变复杂时,才需要进一步评估编排框架。

8. 还有哪些开源实现值得看?

以下是不同侧重点的源码入口,不是性能或成熟度排名:

项目 适合观察的实现 许可
Deep Agents 子 Agent 委派、上下文隔离、文件和工具能力组合 MIT
Google ADK Java Java Agent 层级与执行编排,可接入 A2A;与协议层的 A2A Java SDK 是不同项目 Apache-2.0
LangGraph 有状态执行图、检查点、持久化与人工介入 MIT
CrewAI 角色、任务、协作团队与事件流程 MIT
Microsoft Agent Framework 顺序、并发、任务移交和群组编排 MIT

这些是可复用的实现,但没有义务采用 Codex 相同的注册表或邮箱模型。Microsoft 官方把 Agent Framework 定位为 AutoGen 与 Semantic Kernel 的直接继任者,阅读旧教程时应注意项目演进。官方定位

另两个常见协议也需要放对位置:MCP 主要连接 AI 应用与工具、资源;Agent Client Protocol 主要连接客户端或编辑器与编码 Agent。MCP 服务能力、Agent Client Protocol

对 Java 开发者,一条便于理解的阅读路线是:先通过 ADK Java 看任务如何在服务内部执行,再通过 A2A Java SDK 看这些能力如何对外提供。若重点研究子 Agent 的上下文隔离与委派,可以补看 Deep Agents。

建设系统时也可以采用同样的分层:先确定任务如何可靠完成,再确定哪些能力需要跨服务互通。内部编排与对外协议各自清楚,后续更换模型、框架或部署方式时,边界才容易保持稳定。

相关推荐
SL_staff42 分钟前
四维穿透式齐套判断:JVS-APS在制造计划系统中的技术实现
java·spring boot·python
Csvn42 分钟前
第 24 章 参数体系与调优
人工智能·aigc·agent
dong_junshuai43 分钟前
每天一个开源项目#108 36K星Claude金融Agent模板库
开源·github·agent
后端小肥肠43 分钟前
我做了个 Skill,一句话生成小程序原型,需求文档都帮你写好了
人工智能·aigc·agent
武子康43 分钟前
Ray 的 remote 调用之后:任务怎样衔接,状态留在哪里?
人工智能·llm·agent
程序员cxuan43 分钟前
WorkBuddy + ima 搭建本地知识库
人工智能·后端·程序员
AI深栈43 分钟前
第 17 章 · 编排 AI 流程:StateGraph 节点、条件边与意图路由
java·人工智能
知几蜗牛44 分钟前
vLLM为了新GPU拆掉旧抽象,为什么还要再造一套可移植层
人工智能
知几蜗牛44 分钟前
百万行PR也能顺滑滚动,GitHub靠的不是再加一层虚拟列表
人工智能