Skip to content

Commit 10d2e6c

Browse files
committed
adding code snippets
1 parent 53afbd0 commit 10d2e6c

File tree

2 files changed

+188
-6
lines changed

2 files changed

+188
-6
lines changed

_data/authors.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,4 +618,4 @@ maeste:
618618
emailhash: "c97a0cf6b2f42295f8bfa8670ada8f63"
619619
job_title: "Senior Engineering Manager"
620620
twitter: "maeste"
621-
bio: "Senior Engineering Manager at Red Hat / IBM"
621+
bio: "Senior Engineering Manager at Red Hat / IBM with an old passion for Open Source and more recent one for AI Engineering."

_posts/2025-06-27-a2a-project-lanunches-java-sdk.adoc

Lines changed: 187 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ The agent revolution just took a massive leap forward! Following the
1515
recent landmark https://developers.googleblog.com/en/google-cloud-donates-a2a-to-linux-foundation/[announcement that Google has donated the Agent2Agent
1616
(A2A) protocol to the Linux Foundation], we’re thrilled to announce the
1717
launch of the *https://github.com/a2aproject/a2a-java[A2A Java SDK]*, built by WildFly and Quarkus teams in close collaboration, and now contributed to the official A2A project.
18-
teams’ contribution.
1918

2019

2120
=== A New Era Under Linux Foundation Stewardship
2221

23-
The [A2A](https://a2aproject.github.io/A2A/latest/specification) protocol’s transition to the Linux Foundation represents more
22+
The https://a2aproject.github.io/A2A/latest/specification[A2A] protocol’s transition to the Linux Foundation represents more
2423
than just a change of governance: it’s a commitment to vendor-neutral,
2524
community-driven innovation. Similar how WildFly and Quarkus both recently joined CommonHaus fouundation. This ensures A2A as a critical interoperability
2625
standard remains open and accessible to all. With more than 100
@@ -49,10 +48,193 @@ infrastructure +
4948
Python, JavaScript, or any A2A-compatible language +
5049
well-tested enterprise capabilities (including observability, security...)
5150

52-
Want to see this interoperability in action? Explore our
51+
And you know what? Writing agents in Java is now as easy as writing
52+
53+
==== 1. A class that creates an A2A Agent Card
54+
55+
[source,java]
56+
----
57+
import io.a2a.spec.AgentCapabilities;
58+
import io.a2a.spec.AgentCard;
59+
import io.a2a.spec.AgentSkill;
60+
import io.a2a.spec.PublicAgentCard;
61+
...
62+
63+
@ApplicationScoped
64+
public class WeatherAgentCardProducer {
65+
66+
@Produces
67+
@PublicAgentCard
68+
public AgentCard agentCard() {
69+
return new AgentCard.Builder()
70+
.name("Weather Agent")
71+
.description("Helps with weather")
72+
.url("http://localhost:10001")
73+
.version("1.0.0")
74+
.capabilities(new AgentCapabilities.Builder()
75+
.streaming(true)
76+
.pushNotifications(false)
77+
.stateTransitionHistory(false)
78+
.build())
79+
.defaultInputModes(Collections.singletonList("text"))
80+
.defaultOutputModes(Collections.singletonList("text"))
81+
.skills(Collections.singletonList(new AgentSkill.Builder()
82+
.id("weather_search")
83+
.name("Search weather")
84+
.description("Helps with weather in city, or states")
85+
.tags(Collections.singletonList("weather"))
86+
.examples(List.of("weather in LA, CA"))
87+
.build()))
88+
.build();
89+
}
90+
}
91+
----
92+
93+
==== 2. A class that creates an A2A Agent Executor
94+
95+
[source,java]
96+
----
97+
import io.a2a.server.agentexecution.AgentExecutor;
98+
import io.a2a.server.agentexecution.RequestContext;
99+
import io.a2a.server.events.EventQueue;
100+
import io.a2a.server.tasks.TaskUpdater;
101+
import io.a2a.spec.JSONRPCError;
102+
import io.a2a.spec.Message;
103+
import io.a2a.spec.Part;
104+
import io.a2a.spec.Task;
105+
import io.a2a.spec.TaskNotCancelableError;
106+
import io.a2a.spec.TaskState;
107+
import io.a2a.spec.TextPart;
108+
...
109+
110+
@ApplicationScoped
111+
public class WeatherAgentExecutorProducer {
112+
113+
@Inject
114+
WeatherAgent weatherAgent;
115+
116+
@Produces
117+
public AgentExecutor agentExecutor() {
118+
return new WeatherAgentExecutor(weatherAgent);
119+
}
120+
121+
private static class WeatherAgentExecutor implements AgentExecutor {
122+
123+
private final WeatherAgent weatherAgent;
124+
125+
public WeatherAgentExecutor(WeatherAgent weatherAgent) {
126+
this.weatherAgent = weatherAgent;
127+
}
128+
129+
@Override
130+
public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError {
131+
TaskUpdater updater = new TaskUpdater(context, eventQueue);
132+
133+
// mark the task as submitted and start working on it
134+
if (context.getTask() == null) {
135+
updater.submit();
136+
}
137+
updater.startWork();
138+
139+
// extract the text from the message
140+
String userMessage = extractTextFromMessage(context.getMessage());
141+
142+
// call the weather agent with the user's message
143+
String response = weatherAgent.chat(userMessage);
144+
145+
// create the response part
146+
TextPart responsePart = new TextPart(response, null);
147+
List<Part<?>> parts = List.of(responsePart);
148+
149+
// add the response as an artifact and complete the task
150+
updater.addArtifact(parts, null, null, null);
151+
updater.complete();
152+
}
153+
154+
@Override
155+
public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError {
156+
Task task = context.getTask();
157+
158+
if (task.getStatus().state() == TaskState.CANCELED) {
159+
// task already cancelled
160+
throw new TaskNotCancelableError();
161+
}
162+
163+
if (task.getStatus().state() == TaskState.COMPLETED) {
164+
// task already completed
165+
throw new TaskNotCancelableError();
166+
}
167+
168+
// cancel the task
169+
TaskUpdater updater = new TaskUpdater(context, eventQueue);
170+
updater.cancel();
171+
}
172+
173+
private String extractTextFromMessage(Message message) {
174+
StringBuilder textBuilder = new StringBuilder();
175+
if (message.getParts() != null) {
176+
for (Part part : message.getParts()) {
177+
if (part instanceof TextPart textPart) {
178+
textBuilder.append(textPart.getText());
179+
}
180+
}
181+
}
182+
return textBuilder.toString();
183+
}
184+
}
185+
}
186+
----
187+
188+
Pretty straightforward, right? The SDK provides all the necessary
189+
components to create agent cards, handle agent execution, and manage
190+
communication between agents.
191+
192+
And when it comes to client-side development, it's even easier. The SDK
193+
includes a simple HTTP client that allows you to interact with A2A agents
194+
using the A2A protocol. This client abstracts away the complexities of
195+
the protocol, making it easy to send messages, receive responses, and
196+
manage agent interactions. Creating an A2A client in Java is as simple as:
197+
198+
==== 1. Create an A2A client
199+
200+
[source,java]
201+
----
202+
// 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)
203+
A2AClient client = new A2AClient("http://localhost:1234");
204+
----
205+
206+
==== 2. Send a message to the A2A server agent
207+
208+
[source,java]
209+
----
210+
// Send a text message to the A2A server agent
211+
Message message = A2A.toUserMessage("tell me a joke"); // the message ID will be automatically generated for you
212+
MessageSendParams params = new MessageSendParams.Builder()
213+
.message(message)
214+
.build();
215+
SendMessageResponse response = client.sendMessage(params);
216+
----
217+
218+
Note that `+A2A#toUserMessage+` will automatically generate a message ID
219+
for you when creating the `+Message+` if you don’t specify it. You can
220+
also explicitly specify a message ID like this:
221+
222+
[source,java]
223+
----
224+
Message message = A2A.toUserMessage("tell me a joke", "message-1234"); // messageId is message-1234
225+
----
226+
227+
And the SDK also provides a convenient way to handle task management,
228+
allowing you to create, get gurrent state, and cancel tasks with ease. This is
229+
especially useful for managing long-running operations or coordinating
230+
complex workflows between multiple agents. You can find more details
231+
about task management and many other features in the *https://github.com/a2aproject/a2a-java[A2A Java SDK]* repository's.
232+
233+
You just want more code? Are you interested to see interoperability in action? Explore our
53234
https://github.com/a2aproject/a2a-samples/tree/main/samples/multi_language/python_and_java_multiagent[multi-language
54235
sample implementation&#44;] which demonstrates how Python and Java
55-
agents collaborate seamlessly.
236+
agents collaborate seamlessly. See this picture for a bird-eye overview,
237+
and checkout the code for more insights
56238

57239
image::A2A_multi_agent.png[scaledwidth=100%]
58240

@@ -61,7 +243,7 @@ image::A2A_multi_agent.png[scaledwidth=100%]
61243
And if you need your agent to be reactive, don't worry about the dependencies you are adding, because
62244
the Java SDK leverages *mutiny-zero* as its reactive foundation, a
63245
decision that reflects our commitment to framework-agnostic excellence.
64-
[Mutiny Zero](https://smallrye.io/smallrye-mutiny-zero/latest/) is a minimal API for creating reactive streams-compliant
246+
https://smallrye.io/smallrye-mutiny-zero/latest/[Mutiny Zero] is a minimal API for creating reactive streams-compliant
65247
publishers that weighs less than 50K and have **zero** external dependencies
66248
beyond the Reactive Streams API. This architecture delivers several
67249
compelling advantages:

0 commit comments

Comments
 (0)