Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 248 additions & 0 deletions _posts/2025-09-15-quarkus-a2a-multi-agent-content-creation.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
---
layout: post
title: 'Multi-Language Agent Collaboration and Interoperability with A2A'
date: 2025-09-15
tags: ai a2a
synopsis: Let's learn how to build a multi-agent system where agents written in different languages and with different LLM frameworks can seamlessly collaborate using A2A.
author: fjuma
---
:imagesdir: /assets/images/posts/quarkus-a2a-multi-agent-content-creation

Building a multi-agent system can involve using different languages to meet specific needs. The https://a2a-protocol.org/latest/[Agent2Agent (A2A) protocol] is an open standard that enables AI agents to communicate and collaborate with one another, regardless of each agent's underlying technology stack.

In this post, we'll see how to create a multi-agent system, where agents written in Java, Python, and TypeScript work together to accomplish a goal: content creation. The multi-agent system uses A2A for communication between the AI agents.

image::ContentCreationDiagram.png[scaledwidth=100%]

== Content Creation Sample

We're going to do a deep dive into the https://github.com/a2aproject/a2a-samples/tree/main/samples/python/hosts/content_creation[Content Creation] sample from the https://github.com/a2aproject/a2a-samples[a2a-samples] project.

This sample showcases a content creation pipeline with a `Host` agent that acts as the central orchestrator,
dynamically routing requests to a set of specialized agents.

=== Agents

Here's a quick overview of all the agents in our multi-agent system:

[cols="a,a,a,a",options=header]
|===
| Agent | Role | Technology Stack | Description

| *Host*
| A2A Client
| Python, Google ADK, A2A Python SDK
| Serves as the central orchestrator, routing requests to the appropriate agent based on the task at hand.

| *Content Planner*
| A2A Server
| Python, Google ADK, A2A Python SDK
| Receives a high-level content request and creates a detailed content outline.

| *Content Writer*
| A2A Server
| Java, Quarkus LangChain4j, A2A Java SDK
| Generates engaging content from a content outline.

| *Content Editor*
| A2A Server
| TypeScript, Genkit, A2A JS SDK
| Proofreads and polishes the given content.
|===

Notice that the agents are written in different programming languages and make use of different LLM frameworks.
This is to demonstrate what's possible with the A2A protocol.

=== Handling a Content Creation Request

Upon receiving a content creation request from the user, the `Host` agent breaks down the content creation task
into a few different sub-tasks: planning, writing, and editing.

==== Dynamic Agent Selection
The `Host` agent uses an LLM and the agent cards from our specialized A2A server agents to determine which agent to assign a particular sub-task to. For example, let's take a look at the agent card for our `Content Writer` agent:

[source,json]
----
{
"name": "Content Writer Agent",
"description": "An agent that can write a comprehensive and engaging piece of content based on the provided outline and high-level description of the content",
"url": "http://localhost:10002",
"version": "1.0.0",
"documentationUrl": "http://example.com/docs",
"capabilities": {
"streaming": true,
"pushNotifications": false,
"stateTransitionHistory": false
},
"defaultInputModes": [
"text"
],
"defaultOutputModes": [
"text"
],
"skills": [
{
"id": "writer",
"name": "Writes content using an outline",
"description": "Writes content using a given outline and high-level description of the content",
"tags": [
"writer"
],
"examples": [
"Write a short, upbeat, and encouraging twitter post about learning Java. Base your writing on the given outline."
]
}
],
"supportsAuthenticatedExtendedCard": false,
"additionalInterfaces": [
{
"transport": "JSONRPC",
"url": "http://localhost:10002"
}
],
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0"
}
----

[NOTE]
====
The agent card for an A2A server agent can be found using its Well-Known URI, e.g., for the `Content Writer` agent, we can fetch its agent card using http://localhost:10002/.well-known/agent-card.json.
====

The description and skills specified in the agent card for the `Content Writer` agent allow the `Host` agent's LLM to determine that the writing sub-task should be sent to the `Content Writer` agent.

==== Agent Communication

The `Host` agent communicates with each A2A server agent using an A2A client. Notice that an A2A client
does not need to be written in the same programming language as an A2A server since all that matters is
that both are using the A2A protocol to communicate with each other.

Later on in this post, we'll see how we can easily swap out the TypeScript `Content Editor` agent for
an equivalent agent written in Java, highlighting the flexibility and interoperability that's made
possible by the A2A protocol.

=== Running the Agents

Let's get this multi-agent system running locally.

==== Content Planner

In a terminal:

[source,shell]
----
cd samples/python/agents/content_planner
----

Follow the instructions in the `content_planner` https://github.com/a2aproject/a2a-samples/blob/main/samples/python/agents/content_planner/README.md[README.md] to start the `Content Planner` agent.

==== Content Writer

In a terminal:

[source,shell]
----
cd samples/java/agents/content_writer
----

Follow the instructions in the `content_writer` https://github.com/a2aproject/a2a-samples/blob/main/samples/java/agents/content_writer/README.md[README.md] to start the `Content Writer` agent.

==== Content Editor

In a terminal:

[source,shell]
----
cd samples/js/src/agents/content-editor
----

Follow the instructions in the `content-editor` https://github.com/a2aproject/a2a-samples/blob/main/samples/js/src/agents/content-editor/README.md[README.md] to start the `Content Editor` agent.

==== Host

In a terminal:

[source,shell]
----
cd samples/python/hosts/content_creation
uv run .
----

[NOTE]
====
As mentioned in the agent `README.md` files, don't forget to create a `.env` file for each agent with your
`GOOGLE_API_KEY`. This is needed since the agents in this sample make use of Gemini. You can create a
Google AI Studio API Key for free https://aistudio.google.com/[here].
====

=== Access the Content Creation Application

Now that all of our agents are up and running, from your browser, navigate to http://localhost:8083.

Try asking questions like:

* Create a short, concise LinkedIn post about getting started with the Agent2Agent protocol
* Create a short, upbeat X post about Quarkus LangChain4j

image::UI.png[scaledwidth=100%]

=== Swap Out an Agent

One of the most powerful features of the A2A protocol is its interoperability. Let's see this in
action by swapping out the TypeScript-based `Content Editor` agent for an equivalent agent written
in Java.

image::ContentCreationSwapped.png[scaledwidth=100%]

==== Stop the TypeScript Content Editor Agent and Host Agent

First, stop the `Host` agent and the `Content Editor` agent so we can swap out the `Content Editor` agent for
an equivalent agent written with Java instead of TypeScript.

==== Start the Java Content Editor Agent

In a terminal:

[source,java]
----
cd samples/java/agents/content_editor
----

Follow the instructions in the `content_editor` https://github.com/a2aproject/a2a-samples/blob/main/samples/java/agents/content_editor/README.md[README.md] to start the `Content Editor` agent.

==== Start the Host Agent

In a terminal:

[source,shell]
----
cd samples/python/hosts/content_creation
uv run .
----

==== Access the Content Creation Application

From your browser, navigate to http://localhost:8083 and try asking some questions.

This time, the `Host` agent will seamlessly use the Java-based `Content Editor` agent for editing
content instead of the TypeScript-based `Content Editor` agent. This flexibility is made possible
because the A2A protocol is language-agnostic. This can be really useful for prototyping agents
in one language to get things up and running quickly and then migrating to another language for
a production environment.

== Conclusion

In this post, we saw how to use the A2A protocol to enable agents written in different programming
languages and with different LLM frameworks to collaborate seamlessly to accomplish a goal. We also
saw how easy it is to swap out one of the agents for an equivalent agent written in a different language.

=== Further Reading

* https://github.com/a2aproject/a2a-samples/blob/main/samples/python/hosts/content_creation/README.md[Content Creation Sample]
* https://quarkus.io/blog/quarkus-a2a-java-0-3-0-alpha-release/[Getting Started with Quarkus and A2A Java SDK 0.3.0]
* https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents[A2A Java SDK Samples]
* https://github.com/a2aproject/a2a-java/blob/main/README.md[A2A Java SDK Documentation]
* https://a2a-protocol.org/latest/specification/[A2A Specification]


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading