A2A (Agent-to-Agent)¶
agentscope-extensions-a2a implements the A2A protocol and ships two sub-modules:
agentscope-extensions-a2a-client: wraps a remote A2A Agent as a localAgentyou cancall(...)directly.agentscope-extensions-a2a-server: exposes a localReActAgentas an A2A Server.
The two modules are independent — use either one alone.
Client: call a remote A2A Agent¶
Add the dependency¶
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-extensions-a2a-client</artifactId>
<version>${agentscope.version}</version>
</dependency>
Pass an AgentCard directly¶
import io.a2a.spec.AgentCard;
import io.agentscope.core.a2a.agent.A2aAgent;
AgentCard card = AgentCard.builder()
.name("remote-translator")
.url("http://other-service:8080")
// ...
.build();
A2aAgent remote = A2aAgent.builder()
.name("remote-translator")
.agentCard(card)
.build();
Msg result = remote.call(new UserMessage("Translate to English: 你好")).block();
Auto-discover via well-known¶
import io.agentscope.core.a2a.agent.card.WellKnownAgentCardResolver;
WellKnownAgentCardResolver resolver = new WellKnownAgentCardResolver(
"http://127.0.0.1:8080",
"/.well-known/agent-card.json",
Map.of()
);
A2aAgent remote = A2aAgent.builder()
.name("remote")
.agentCardResolver(resolver)
.build();
A2aAgent is a subclass of AgentBase, so it composes naturally with Pipeline, MsgHub, Subagent, etc.
Server: expose a ReActAgent as an A2A Server¶
Add the dependency¶
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-extensions-a2a-server</artifactId>
<version>${agentscope.version}</version>
</dependency>
Build the server¶
import io.agentscope.core.a2a.server.AgentScopeA2aServer;
import io.agentscope.core.a2a.server.transport.jsonrpc.JsonRpcTransportProperties;
ReActAgent.Builder agentBuilder = ReActAgent.builder()
.name("backend-agent")
.model(model);
AgentScopeA2aServer server = AgentScopeA2aServer.builder()
.agentBuilder(agentBuilder)
.transportProperties(new JsonRpcTransportProperties())
// .agentCard(customCard)
// .agentRegistry(myRegistry)
.build();
// Delegate inbound requests to the transport wrapper from your web framework
TransportWrapper wrapper = server.getTransportWrapper("JSONRPC");
// ... Spring/Quarkus controller forwards to wrapper.handle(...)
server.postEndpointReady(); // call after the web server is listening — triggers registration etc.
AgentScopeA2aServer does not bind a port or expose endpoints itself; it only assembles components and the request-handling chain. You wire transport into Spring Boot, Quarkus, Vert.x, etc. as you prefer.
Optional components¶
TaskStore/QueueManager: task and event queue stores; in-memory by default, swap for persistent versions in production.PushNotificationConfigStore/PushNotificationSender: outbound notifications.AgentRegistry: registerAgentCardto an external registry such as Nacos (see Nacos).
Spring Boot Starter¶
If you’re on Spring Boot, prefer agentscope-spring-boot-starter-a2a-server — it auto-configures the server and controller. See Spring Boot Starters.