A2A(Agent-to-Agent)协议集成实践

1,486 阅读10分钟

多智能体(Multi-Agent)系统正在成为 AI 应用的新趋势。Google 提出的 Agent-to-Agent (A2A) 协议为不同 AI 代理间的协作提供了标准化通信方案。A2A 协议通过定义统一的任务(Task)对象、消息(Message)和能力发现机制,使得各类智能体可以跨平台、跨厂商互通,共同完成复杂任务。本文将详细介绍 A2A 协议的核心原理,并通过 Spring Boot 实例演示如何借助 Kafka 实现多智能体协作流水线。

A2A 协议核心概念与架构

Agent Card (agent.json)

每个 A2A 代理都需要公开一个 Agent Card,通常放在 /.well-known/agent.json,以 JSON 格式描述该代理的身份、能力、技能列表、服务端点、以及认证信息。其它代理通过发现 Agent Card,就能知道对方能做什么,并与之通信(相当于微服务中的接口发现)。

Task 对象

A2A 中的工作单位是 Task,代表一个具体的智能体任务请求。Task 包括任务 ID、请求方、目标代理、输入参数等信息,并拥有生命周期和状态。任务可以是短期的,也可以是需要长时间执行的「漫长研究」。代理间通过传输 Task,达成任务委派。任务执行过程中双方可以通过状态更新(如 IN_PROGRESS、COMPLETED 等)保持同步,最终产生输出结果(称为 Artifact)。

消息(Message)与消息部分(Message Part)

A2A 使用 JSON-RPC2.0 作为传输格式。每个 Task 可以携带若干 Message Part,支持文本(TextPart)、文件(FilePart)、结构化数据(DataPart)等多种类型。通过这类组合,代理可以交换自然语言描述、图像、文档或机器可读数据,实现多模态协作。

传输协议

A2A 协议基于常见标准构建,使用 HTTPS 进行传输,并兼容 Server-Sent Events (SSE) 等技术。也就是说,A2A 在底层其实就是给代理通信加了契约,只要各代理遵循 JSON-RPC,便可在现有架构中无缝接入。

客户代理(Client Agent)向远端代理(Remote Agent)发送一个 Task,整个流程示意如下: image.png

A2A 的优势

更强的解耦性

传统微服务需要事先知道对方的接口地址、API 格式等,增加了系统耦合度。A2A 采用能力发现机制,代理通过 Agent Card 广播自己的技能,使用时只需发送任务,不必关心对方实现细节。这种模式类似于为智能体提供一个 “DNS + 消息层”,让它们不用直接知道彼此,就能协作。

丰富的任务状态管理

A2A 定义了任务的生命周期和状态,可以处理长时间运行的任务。各代理间可以同步任务执行进度,客户端还可通过轮询或 SSE 实时获取状态更新。这种机制天然支持异步多步工作流,而传统 API 调用通常是一步到位、无状态的返回,难以跟踪复杂任务的进度。

面向自然语言和多模态

A2A 协议鼓励使用自然语言或其它丰富的交互方式触发任务。由于消息支持文本、音视频等多种格式,客户端可以直接将用户的需求以自然语言描述放进 Task 中,让服务端代理解析执行。相比之下,传统 REST 接口往往只能接受结构化参数,灵活性较低。

灵活拓展和协同

随着智能体数量增多,传统点对点集成模式会面临指数级连接问题(“N 个服务需要 N(N-1)/2 条连接”)。A2A 协议本身为异步消息通信打下了基础,使得代理网络更像一个动态协同的生态系统。各代理可以动态加入或移除,只要遵循协议即可交互。

pring Boot + Kafka + A2A 实战

Kafka 在 A2A 架构中的作用

尽管 A2A 解决了协议层面的互通,实际部署时仍面临代理间点对点调用的扩展问题。结合 Kafka 等事件驱动中间件可以进一步解耦智能体通信。Kafka 可作为一个“共享骨干”,让代理发布事件到主题(Topic),订阅感兴趣的事件,消除一对一调用的需要。在这种模式下,任何产生洞见的代理都只需 publish 一条消息,无需知道谁会消费;而感兴趣的代理只需 subscribe 相应主题即可获得任务。

使用 Kafka 带来的好处包括:

  • 松耦合: 代理不需要记录彼此的地址,只需关注消息主题。例如,orders 主题可用来分发所有新订单任务,而 payments 主题处理支付任务。若新增某个服务处理新类型任务,只要订阅对应主题即可,无需修改其他代理配置。
  • 可观测性: Kafka 会持久化消息日志,方便审计与回溯。消息在中间件持久化存储,可与监控链路结合,全面追踪系统行为。
  • 可扩展性: Kafka 支持水平扩展,多实例并发消费,能满足企业级的高吞吐和高可用需求。

传统 A2A 点对点通信在大型系统中难以扩展和监控,需要一个“共享的异步骨干”,Kafka 提供了天然的事件总线来解耦发布者和订阅者。

image.png

核心思路

以 Spring Boot 为例,搭建一个简单的 Kafka-A2A 桥接系统,包括三个 A2A 服务:OrderServicePaymentServiceAlertService,以及一个负责接收 Kafka 消息并生成 A2A 任务的桥接代理。Kafka Producer 发消息到不同主题,桥接代理监听消息并调用本地 A2A 客户端创建任务,各服务根据任务执行相应逻辑并返回结果。

构建 A2A 服务

首先定义三个业务服务,每个类都用 @Agent 注解标记为 A2A 代理,并为可执行方法添加 @Action 注解:

@Service
@Agent(groupName = "order support", groupDescription = "处理订单相关的操作")
public class OrderService {
    private A2AActionCallBack callBack;

    @Action(description = "处理新订单")
    public String processNewOrder(String orderId, String status, String amount) {
        // 在任务执行过程中发送状态更新
        if (callBack != null) {
            callBack.sendStatus("处理中: 订单ID=" + orderId, ActionState.IN_PROGRESS);
            // TODO: 这里添加订单处理逻辑
            callBack.sendStatus("完成: 订单ID=" + orderId, ActionState.COMPLETED);
        }
        return "已处理订单: " + orderId;
    }
}

@Service
@Agent(groupName = "payment support", groupDescription = "处理支付相关的操作")
public class PaymentService {
    @Action(description = "处理支付")
    public String processPayment(String paymentId, String status, String amount) {
        // TODO: 添加支付处理逻辑
        return "已完成支付: " + paymentId;
    }
}

@Service
@Agent(groupName = "alert support", groupDescription = "处理系统告警相关的操作")
public class AlertService {
    @Action(description = "处理系统告警")
    public String processAlert(String alertId, String type, String severity) {
        // TODO: 添加告警处理逻辑
        return "已处理告警: " + alertId;
    }
}
  • 每个服务类都被 @Agent 注解标记,指定了代理的分组和描述信息。
  • 每个可执行方法都用 @Action 注解,并提供了中文描述。方法参数会自动从 Task 中的参数部分映射。
  • OrderService 示例中,我们使用了 A2AActionCallBack 回调来发送任务状态(如 IN_PROGRESSCOMPLETED),便于任务调用方跟踪进度;其他服务也可按需加入类似回调。

Kafka-A2A 桥接代理

接下来实现一个监听 Kafka 的组件,将消息转换成 A2A 任务并发送给本地 A2A 服务:

@Component
public class SpringKafkaAgent {
    private final LocalA2ATaskClient client;
    private final ObjectMapper objectMapper;

    // 将 Kafka 消息转换为 A2A 任务并发送
    private void processMessage(String messageType, String topic, String key, String value) {
        // 构建任务描述信息
        String description = String.format("Kafka消息任务: 类型=%s, 主题=%s, 键=%s, 值=%s",
                                           messageType, topic, key, value);
        // 使用 A2A 客户端发送任务
        Task task = client.sendTask(description);
        // 等待任务完成(超时时间秒)
        Task result = client.getTask(task.getId(), 5);
        // TODO: 可以根据 result 获取任务输出并处理
    }

    @KafkaListener(topics = "orders", groupId = "a2a-group")
    public void consumeOrderMessages(ConsumerRecord<String, String> record, Acknowledgment ack) {
        try {
            processMessage("order-processing", record.topic(), record.key(), record.value());
            ack.acknowledge();
        } catch (Exception e) {
            // 错误处理逻辑
        }
    }

    // 可类似地为 payments 和 alerts 主题添加监听方法
}
  • 通过 @KafkaListener 监听 Kafka 的 "orders" 主题(可以为 "payments""alerts" 分别再写两个监听方法)。
  • 收到消息后调用 processMessage,将消息内容拼装成字符串,并使用 LocalA2ATaskClient 创建一个 A2A 任务。
  • 随后可以调用 client.getTask 等待任务执行完成,或在后续步骤实现异步回调逻辑。

示例

@SpringBootApplication
@ComponentScan({"io.github.vishalmysore.a2a", "io.github.vishalmysore.agent", "io.github.vishalmysore.a2a.kafka"})
public class KafkaA2AApplication {
    public static void main(String[] args) {
        SpringApplication.run(KafkaA2AApplication.class, args);
    }

    @Bean
    public CommandLineRunner demoData(KafkaTestProducer producer) {
        return args -> {
            // 向 Kafka 发布示例消息
            producer.sendOrderMessage("ORD-1", "{\"id\":\"ORD-1\",\"status\":\"created\",\"amount\":150.00}");
            producer.sendPaymentMessage("PAY-1", "{\"id\":\"PAY-1\",\"status\":\"authorized\",\"amount\":150.00}");
            producer.sendAlertMessage("ALT-1", "{\"type\":\"CPU_USAGE\",\"severity\":\"HIGH\",\"value\":95.2}");
        };
    }
}
  • CommandLineRunner 中,通过 KafkaTestProducer 向不同主题发送示例 JSON 消息。
  • 桥接代理启动后会自动消费这些消息,转化成 A2A 任务并触发对应服务处理。

image.png

  1. Kafka Producer 将消息推送到对应主题(如 orders)。
  2. SpringKafkaAgent 监听消息并调用本地 A2A 客户端的 tasks/send 接口,将任务下发给相应代理(如 OrderService)。
  3. 目标代理执行任务,期间通过回调发送状态更新,最后返回结果数据。
  4. SpringKafkaAgent 可进一步将任务结果写回 Kafka 或触发其他后续动作。

任务状态回调与监控

任务状态推送

A2A 协议支持客户在发送任务时通过 SSE 或推送通知配置实时获取状态更新。客户端可调用 tasks/sendSubscribe 建立流式连接,或使用 tasks/pushNotification/set 注册回调地址,让服务端主动回传状态。在上述示例中,我们通过 A2AActionCallBack 在服务端主动发送状态,客户端则通过 getTask 或 SSE 接收更新。

监控与指标

可结合 Spring Boot Actuator、Micrometer 等框架,为 A2A 服务和 Kafka 消费添加指标采集。比如统计每秒处理任务数、任务平均耗时、Kafka 消费滞后等,并通过 Prometheus/Grafana 实时监控。借助 Kafka 的持久化日志,还能轻松审计历史任务流。合理的监控和日志有助于保障系统稳定性、及时发现问题。

结语

本文介绍了 Google A2A 协议的核心理念和消息机制,并演示了如何使用 Spring Boot 将 A2A 与 Kafka 结合,实现多智能体间的异步协作。A2A 通过标准化任务和能力发现,为智能体互操作建立了统一语言;Kafka 则提供事件驱动的松耦合骨干,使系统更易扩展和维护。这样的架构特别适合需要高度解耦和可观测性的企业级 AI 方案。

未来,随着 A2A 协议生态的完善,我们预计会看到更多工具链和云服务原生支持 A2A。如 Google 官方所述,A2A 有望开启智能体互操作的新纪元,让不同供应商、不同平台的 AI 代理能够无缝协同解决复杂问题。

对于国内开发者而言,掌握 A2A + Kafka 的实践,将有助于构建符合未来趋势的 AI 系统架构。此外,A2A 与 Anthropic MCP 等上下文协议结合,结合流处理框架(如 Flink)和现代容器云原生平台,将进一步丰富企业智能化解决方案的设计思路。