Skip to content
Open
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
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ mvn clean install
- Try to use existing code instead of generating new similar code
- Use the same code convention than existing code. If the existing convention seems incorrect, make suggestion before doing any changes

### Documentation Site

The docs site (`docs/`) uses versioned content folders (`docs/content/1.0.0.Final/`, `docs/content/1.1.0.Final/`, `docs/content/dev/`). When updating documentation to reflect code changes, only edit pages under `docs/content/dev/` — released version folders are frozen snapshots and must not be modified. New versioned folders are created at release time (see RELEASE.md).

### PR instructions
- Follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) for the commit title and message
- Always ask if the commit is related to a GitHub issue. If that's the case, add a `This fixes #{issue_number}` at the end of the commit message
Expand Down
27 changes: 26 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,32 @@ Artifacts should include:
- `.pom` files
- `.asc` GPG signatures for all artifacts

### 9. Increment to Next SNAPSHOT
### 9. Update Versioned Documentation

Create a new documentation version for the release:

```bash
# Copy dev docs to the new version folder
cp -r docs/content/dev docs/content/X.Y.Z.Final

# Create a new version data file
cp docs/data/versions/dev.yml docs/data/versions/X.Y.Z.Final.yml
```

Edit `docs/data/versions/X.Y.Z.Final.yml`:
- Set `label` to `"X.Y.Z.Final"`
- Set `path` to `"X.Y.Z.Final"`
- Set `sortOrder` to the next number (higher than the previous release)
- Set `defaultVersion` to `true`
- Set `devVersion` to `false`
- Adjust the `menu` list if the new version adds or removes pages

Update the previous default version's data file (e.g., `docs/data/versions/OLD_VERSION.yml`):
- Set `defaultVersion` to `false`

Review the new version's content for accuracy — ensure all pages reflect features available in this release.

### 10. Increment to Next SNAPSHOT

Prepare repository for next development cycle:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class ExtrasBomVerifier extends DynamicBomVerifier {

private static final Set<String> EXTRAS_EXCLUSIONS = Set.of(
"boms/", // BOM test modules themselves
"docs/", // Documentation site (not an SDK artifact)
"examples/", // Example applications
"itk/", // Integration Test Kit agent
"tck/", // TCK test suite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class ReferenceBomVerifier extends DynamicBomVerifier {

private static final Set<String> REFERENCE_EXCLUSIONS = Set.of(
"boms/", // BOM test modules themselves
"docs/", // Documentation site (not an SDK artifact)
"examples/", // Example applications
"itk/", // Integration Test Kit agent
"tck/", // TCK test suite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class SdkBomVerifier extends DynamicBomVerifier {

private static final Set<String> SDK_EXCLUSIONS = Set.of(
"boms/", // BOM test modules themselves
"docs/", // Documentation site (not an SDK artifact)
"examples/", // Example applications
"itk/", // Integration Test Kit agent
"tck/", // TCK test suite
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions docs/content/client.md → docs/content/1.0.0.Final/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ Client client = Client

## Communicating with v0.3 Agents

See [Backward Compatibility]({site.url('compatibility')}#client-communicating-with-v03-agents) for using `Client_v0_3` with older protocol agents.
See [Backward Compatibility](compatibility#client-communicating-with-v03-agents) for using `Client_v0_3` with older protocol agents.

## Examples

See [Examples]({site.url('examples')}) for Hello World walkthroughs and sample applications.
See [Examples](examples) for Hello World walkthroughs and sample applications.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ mvn exec:java -Dopentelemetry=true

The client expects an OpenTelemetry collector on port 5317. The easiest way is to run the Java server with `-Popentelemetry` (which starts the collector automatically), then run the client with `-Dopentelemetry=true` for end-to-end traces.

For more information, see the [OpenTelemetry extras module]({site.url('/extras/opentelemetry')}).
For more information, see the [OpenTelemetry extras module](extras/opentelemetry).

## More Examples

Expand Down
8 changes: 4 additions & 4 deletions docs/content/extras.md → docs/content/1.0.0.Final/extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ Import the extras BOM to manage versions:
</dependencyManagement>
```

## [HTTP Clients]({site.url('/extras/http-clients')})
## [HTTP Clients](extras/http-clients)

Alternative `A2AHttpClient` implementations. The **Vert.x HTTP Client** (`a2a-java-sdk-http-client-vertx`) replaces the default JDK HttpClient with a reactive, non-blocking Vert.x WebClient — recommended for Quarkus, reactive frameworks, and high-throughput scenarios. An **Android HTTP Client** (`a2a-java-sdk-http-client-android`) is also available for mobile applications.

## [Storage & Persistence]({site.url('/extras/storage')})
## [Storage & Persistence](extras/storage)

JPA-backed replacements for the in-memory stores, providing database persistence for production and load-balanced deployments. Includes a **JPA Task Store** (`a2a-java-extras-task-store-database-jpa`) and a **JPA Push Notification Config Store** (`a2a-java-extras-push-notification-config-store-database-jpa`). Both use Jakarta Persistence API (JPA 3.0+) and share the same datasource configuration.

## [Replicated Queue Manager]({site.url('/extras/replicated-queue-manager')})
## [Replicated Queue Manager](extras/replicated-queue-manager)

Replaces the default `InMemoryQueueManager` with event replication across multiple A2A server instances via message brokers. Required for multi-instance deployments. The core module (`a2a-java-queue-manager-replicated-core`) pairs with a MicroProfile Reactive Messaging strategy (`a2a-java-queue-manager-replication-mp-reactive`) supporting Apache Kafka, Pulsar, or AMQP. You can also write your own `ReplicationStrategy`.

## [OpenTelemetry]({site.url('/extras/opentelemetry')})
## [OpenTelemetry](extras/opentelemetry)

Distributed tracing, metrics, and context propagation for A2A servers and clients using OpenTelemetry. The server module (`a2a-java-sdk-opentelemetry-server`) adds automatic span creation for all protocol methods with context propagation across async boundaries. Client modules (`a2a-java-sdk-opentelemetry-client`, `a2a-java-sdk-opentelemetry-client-propagation`) instrument A2A client operations.
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,19 @@ Add the reference server dependency to your Maven project:
</dependency>
```

Then implement an `AgentExecutor` and define an `AgentCard`. See the [Server Guide]({site.url('server')}) for the full walkthrough.
Then implement an `AgentExecutor` and define an `AgentCard`. See the [Server Guide](server) for the full walkthrough.

## Guides

| Guide | Description |
|-------|-------------|
| [Server Guide]({site.url('server')}) | Run your Java application as an A2A server |
| [Client Guide]({site.url('client')}) | Communicate with A2A-compliant agents |
| [Configuration]({site.url('configuration')}) | Config properties, MicroProfile Config, custom providers |
| [Task Authorization]({site.url('authorization')}) | Per-user access control for multi-user deployments |
| [Backward Compatibility]({site.url('compatibility')}) | Serve v1.0 and v0.3 clients simultaneously |
| [Extras]({site.url('extras')}) | Optional add-ons: database storage, OpenTelemetry, HTTP clients |
| [BOMs]({site.url('boms')}) | Dependency management with Bill of Materials |
| [Examples]({site.url('examples')}) | Hello World walkthroughs and sample applications |
| [Server Guide](server) | Run your Java application as an A2A server |
| [Client Guide](client) | Communicate with A2A-compliant agents |
| [Configuration](configuration) | Config properties, MicroProfile Config, custom providers |
| [Backward Compatibility](compatibility) | Serve v1.0 and v0.3 clients simultaneously |
| [Extras](extras) | Optional add-ons: database storage, OpenTelemetry, HTTP clients |
| [BOMs](boms) | Dependency management with Bill of Materials |
| [Examples](examples) | Hello World walkthroughs and sample applications |

## Requirements

Expand Down
166 changes: 166 additions & 0 deletions docs/content/1.0.0.Final/server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: A2A Server Guide
description: Run your agentic Java application as an A2A server following the Agent2Agent Protocol.
layout: page
---

# A2A Server

The A2A Java SDK provides a Java server implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). To run your agentic Java application as an A2A server, follow the steps below.

## Supported Transports

- JSON-RPC 2.0
- gRPC
- HTTP+JSON/REST

## 1. Add a Server Dependency

### JSON-RPC

```xml
<dependency>
<groupId>org.a2aproject.sdk</groupId>
<artifactId>a2a-java-sdk-reference-jsonrpc</artifactId>
<!-- Use a released version from https://github.com/a2aproject/a2a-java/releases -->
<version>$\{org.a2aproject.sdk.version}</version>
</dependency>
```

### gRPC

```xml
<dependency>
<groupId>org.a2aproject.sdk</groupId>
<artifactId>a2a-java-sdk-reference-grpc</artifactId>
<version>$\{org.a2aproject.sdk.version}</version>
</dependency>
```

### HTTP+JSON/REST

```xml
<dependency>
<groupId>org.a2aproject.sdk</groupId>
<artifactId>a2a-java-sdk-reference-rest</artifactId>
<version>$\{org.a2aproject.sdk.version}</version>
</dependency>
```

You can add more than one transport dependency to support multiple protocols simultaneously.

## 2. Define an Agent Card

```java
@ApplicationScoped
public class WeatherAgentCardProducer {

private static final String AGENT_URL = "http://localhost:10001";

@Produces
@PublicAgentCard
public AgentCard agentCard() {
return AgentCard.builder()
.name("Weather Agent")
.description("Helps with weather")
.supportedInterfaces(List.of(
new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL)))
.version("1.0.0")
.capabilities(AgentCapabilities.builder()
.streaming(true)
.pushNotifications(false)
.build())
.defaultInputModes(Collections.singletonList("text"))
.defaultOutputModes(Collections.singletonList("text"))
.skills(Collections.singletonList(AgentSkill.builder()
.id("weather_search")
.name("Search weather")
.description("Helps with weather in cities or states")
.tags(Collections.singletonList("weather"))
.examples(List.of("weather in LA, CA"))
.build()))
.build();
}
}
```

## 3. Implement an Agent Executor

```java
@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, AgentEmitter agentEmitter) throws JSONRPCError {
if (context.getTask() == null) {
agentEmitter.submit();
}
agentEmitter.startWork();

String userMessage = extractTextFromMessage(context.getMessage());
String response = weatherAgent.chat(userMessage);

agentEmitter.addArtifact(List.of(new TextPart(response)));
agentEmitter.complete();
}

@Override
public void cancel(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError {
Task task = context.getTask();
if (task == null) {
agentEmitter.cancel();
return;
}
if (task.status().state() == TaskState.CANCELED ||
task.status().state() == TaskState.COMPLETED) {
throw new TaskNotCancelableError();
}
agentEmitter.cancel();
}

private String extractTextFromMessage(Message message) {
if (message == null) {
return "";
}
StringBuilder textBuilder = new StringBuilder();
for (Part<?> part : message.parts()) {
if (part instanceof TextPart textPart) {
textBuilder.append(textPart.text());
}
}
return textBuilder.toString();
}
}
}
```

## 4. Configuration

See [Configuration](configuration) for all config properties and tuning.

## Backward Compatibility with v0.3

See [Backward Compatibility](compatibility) for multi-version modules, version routing, and v0.3 client support.

## Server Integrations

- **Quarkus** — Reference implementations are Quarkus-based (JSON-RPC, gRPC, REST)
- **Jakarta EE** — [a2a-jakarta](https://github.com/wildfly-extras/a2a-jakarta) works with any Jakarta EE Web Profile runtime

See [CONTRIBUTING_INTEGRATIONS.md](https://github.com/a2aproject/a2a-java/blob/main/CONTRIBUTING_INTEGRATIONS.md) to submit your own integration.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class MyTaskAuthorizationProvider implements TaskAuthorizationProvider {

@Override
public boolean isTaskRecorded(String taskId) {
return ownershipStore.contains(taskId);
return ownershipStore.containsKey(taskId);
}

@Override
Expand Down
Loading