Red Hat 的 Quarkus 和 WildFly 团队与 Google 合作发布 Agent2Agent Java SDK

代理的革命向前迈进了一大步!在 Google 将 Agent2Agent (A2A) 协议捐赠给 Linux 基金会的 最新里程碑公告 之后,我们很高兴地宣布推出由 WildFly 和 Quarkus 团队紧密合作创建的 A2A Java SDK,该 SDK 现在已贡献给官方 A2A 项目。

Linux 基金会管理下的新时代

A2A 协议向 Linux 基金会的过渡不仅仅是治理的改变:它更是对厂商中立、社区驱动创新的承诺。这与 WildFly 和 Quarkus 最近加入 CommonHaus 基金会的方式类似。这确保了 A2A 作为关键的互操作性标准,能够对所有人保持开放和可访问。随着超过 100 家公司现在支持该协议,我们正在目睹行业领导者称之为“开放、可互操作的代理互联网”的形成。随着 A2A Java SDK 现已成为这一运动的一部分,企业开发者可以从第一天起就参与到这个开放的代理生态系统中。

为什么 Java SDK 很重要

从技术角度来看,令人兴奋之处在于:真正的多语言代理生态系统

代理领域一直存在碎片化,Python 主导 AI/ML 工作流,JavaScript 驱动基于 Web 的代理,而 Java 则作为企业后端系统的支柱。跨语言生态系统的孤立开发阻碍了代理应用程序的真正潜力。

我们的 Java SDK 通过原生 Java 实现 A2A 协议规范,打破了这些障碍,从而实现了

  • 企业级代理集成,与现有的 Java 基础设施集成

  • 无缝互操作性,可在 Java 代理与用 Python、JavaScript 或任何 A2A 兼容语言编写的代理之间实现(具有经过充分测试的企业功能,包括可观测性、安全性…)

您知道吗?用 Java 编写代理现在就像编写

1. 创建 A2A Agent Card 的类

import io.a2a.spec.AgentCapabilities;
import io.a2a.spec.AgentCard;
import io.a2a.spec.AgentSkill;
import io.a2a.spec.PublicAgentCard;
...

@ApplicationScoped
public class WeatherAgentCardProducer {

    @Produces
    @PublicAgentCard
    public AgentCard agentCard() {
        return new AgentCard.Builder()
                .name("Weather Agent")
                .description("Helps with weather")
                .url("https://:10001")
                .version("1.0.0")
                .capabilities(new AgentCapabilities.Builder()
                        .streaming(true)
                        .pushNotifications(false)
                        .stateTransitionHistory(false)
                        .build())
                .defaultInputModes(Collections.singletonList("text"))
                .defaultOutputModes(Collections.singletonList("text"))
                .skills(Collections.singletonList(new AgentSkill.Builder()
                        .id("weather_search")
                        .name("Search weather")
                        .description("Helps with weather in city, or states")
                        .tags(Collections.singletonList("weather"))
                        .examples(List.of("weather in LA, CA"))
                        .build()))
                .build();
    }
}

2. 创建 A2A Agent Executor 的类

import io.a2a.server.agentexecution.AgentExecutor;
import io.a2a.server.agentexecution.RequestContext;
import io.a2a.server.events.EventQueue;
import io.a2a.server.tasks.TaskUpdater;
import io.a2a.spec.JSONRPCError;
import io.a2a.spec.Message;
import io.a2a.spec.Part;
import io.a2a.spec.Task;
import io.a2a.spec.TaskNotCancelableError;
import io.a2a.spec.TaskState;
import io.a2a.spec.TextPart;
...

@ApplicationScoped
public class WeatherAgentExecutorProducer {

    @Inject
    WeatherAgent weatherAgent;

    @Produces
    public AgentExecutor agentExecutor() {
        return new WeatherAgentExecutor(weatherAgent);
    }

    private static class WeatherAgentExecutor implements AgentExecutor {

        private final WeatherAgent weatherAgent;

        public WeatherAgentExecutor(WeatherAgent weatherAgent) {
            this.weatherAgent = weatherAgent;
        }

        @Override
        public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError {
            TaskUpdater updater = new TaskUpdater(context, eventQueue);

            // mark the task as submitted and start working on it
            if (context.getTask() == null) {
                updater.submit();
            }
            updater.startWork();

            // extract the text from the message
            String userMessage = extractTextFromMessage(context.getMessage());

            // call the weather agent with the user's message
            String response = weatherAgent.chat(userMessage);

            // create the response part
            TextPart responsePart = new TextPart(response, null);
            List<Part<?>> parts = List.of(responsePart);

            // add the response as an artifact and complete the task
            updater.addArtifact(parts, null, null, null);
            updater.complete();
        }

        @Override
        public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError {
            Task task = context.getTask();

            if (task.getStatus().state() == TaskState.CANCELED) {
                // task already cancelled
                throw new TaskNotCancelableError();
            }

            if (task.getStatus().state() == TaskState.COMPLETED) {
                // task already completed
                throw new TaskNotCancelableError();
            }

            // cancel the task
            TaskUpdater updater = new TaskUpdater(context, eventQueue);
            updater.cancel();
        }

        private String extractTextFromMessage(Message message) {
            StringBuilder textBuilder = new StringBuilder();
            if (message.getParts() != null) {
                for (Part part : message.getParts()) {
                    if (part instanceof TextPart textPart) {
                        textBuilder.append(textPart.getText());
                    }
                }
            }
            return textBuilder.toString();
        }
    }
}

相当直接,对吧?该 SDK 提供了创建代理卡片、处理代理执行和管理代理之间通信所需的所有必要组件。

注意:未来我们预计 Quarkus 和其他使用 A2A Java SDK 的框架将简化部分样板代码。

而在客户端开发方面,则更加简单。该 SDK 包括一个简单的 A2A 客户端,允许您使用 A2A 协议与 A2A 代理进行交互。该客户端抽象了协议的复杂性,使发送消息、接收响应和管理代理交互变得容易。用 Java 创建 A2A 客户端就像

1. 创建一个 A2A 客户端

// Create an A2AClient (the URL specified is the server agent's URL, be sure to replace it with the actual URL of the A2A server you want to connect to)
A2AClient client = new A2AClient("https://:1234");

2. 向 A2A 服务器代理发送消息

// Send a text message to the A2A server agent
Message message = A2A.toUserMessage("tell me a joke"); // the message ID will be automatically generated for you
MessageSendParams params = new MessageSendParams.Builder()
        .message(message)
        .build();
SendMessageResponse response = client.sendMessage(params);

请注意,当您创建 `Message` 时,如果未指定,A2A#toUserMessage 将自动为您生成消息 ID。您也可以像这样显式指定消息 ID

Message message = A2A.toUserMessage("tell me a joke", "message-1234"); // messageId is message-1234

该 SDK 还提供了一种便捷的任务管理方式,让您可以轻松地创建、获取当前状态和取消任务。这对于管理长时间运行的操作或协调多个代理之间的复杂工作流特别有用。您可以在 **A2A Java SDK** 存储库中找到有关任务管理和许多其他功能的更多详细信息。

您想看更多代码吗?您对实际的互操作性感兴趣吗?探索我们的 多语言示例实现,该实现展示了 Python 和 Java 代理如何无缝协作。查看此图以获得鸟瞰图,并查看代码以获得更多见解

a2a agentic

技术卓越:Mutiny-Zero 的优势

如果您需要代理具有响应性,请不用担心您添加的依赖项,因为 Java SDK 利用 **Mutiny-Zero** 作为其响应式基础,这一决定反映了我们对框架无关的卓越性的承诺。Mutiny Zero 是一个用于创建符合 Reactive Streams 的发布者的最小 API,其大小不到 50K,并且除 Reactive Streams API 外,拥有**零**外部依赖项。这种架构提供了几个引人注目的优势

  • 无供应商锁定:您的代理没有特定的技术承诺。

  • 轻量级性能:更快的启动速度,减少资源消耗。

  • 最大兼容性:与现有的 Java 响应式生态系统无缝集成。

  • 面向未来的设计:为 Java 的现代 Flow API 做好准备,向后兼容。

这种响应式基础确保了您的 Java 代理能够处理高吞吐量、低延迟的代理间通信,同时保持轻量级和可组合性。

社区驱动的创新

最初的外部贡献现在已成为 A2A 项目存储库的官方组成部分,这展示了生态系统如何通过多样化的贡献快速发展。这正是将加速 A2A 采用和创新的协作开发。

准备好深入研究了吗?这是您的路线图

  1. 探索 SDK:访问 github.com/a2aproject/a2a-java 查看实现

  2. 学习实际示例:查看 多语言示例,了解互操作性

  3. 加入社区:与 A2A 生态系统中的其他开发者联系

  4. 开始构建:开始原型设计您的第一个多语言代理团队

更大的图景:协作智能

A2A 协议旨在通过提供一种通用的语言,使 AI 代理能够发现彼此的能力、安全地交换信息并协调复杂任务,从而打破目前限制 AI 注入式应用程序潜力的孤岛。

随着 Java 现在加入 Python 和 JavaScript 的 A2A 生态系统,我们正在构建一个智能真正协作的未来,其中最复杂的 AI 系统由专门的代理组成,每个代理针对特定任务进行了优化,但通过标准化的通信协议统一起来。

此次 Java SDK 的发布只是一个开始。在 Linux 基金会管理下的 A2A 项目有望快速扩展,未来还将推出其他语言实现、增强的安全功能和企业级工具。

您的贡献很重要。无论您是修复错误、添加功能、创建示例还是构建与其他框架的集成——每一笔提交都将帮助构建这个协作的未来。代理革命已经到来,借助 A2A Java SDK,整个 Java 生态系统都可以参与进来。让我们一起构建一些令人惊叹的东西!🚀