---
title: "A2A Java SDKの使い方｜Quarkusでのサーバー・クライアント実装とLLM連携、0.3系からの移行【1.5対応】"
url: "https://www.issoh.co.jp/tech/details/7234/"
published: 2025-06-13
updated: 2026-11-05
categories: ["AIエージェント・MCP"]
publisher: "株式会社一創"
---

# A2A Java SDKの使い方｜Quarkusでのサーバー・クライアント実装とLLM連携、0.3系からの移行【1.5対応】

A2A Java SDK（a2a-java）は、AIエージェント同士をつなぐAgent2Agent（A2A）プロトコルの公式Java実装です。この記事では、2026年11月3日公開の1.5.0.Finalを使い、QuarkusのA2AサーバーとJavaクライアントを書いて手元で動かした結果を載せます。2025年に書かれた解説の多くは0.2〜0.3系のままで、1.xではコンパイルできません。移行で変わった点と、既定設定でつまずく箇所も扱います。

## まとめ：A2A Java SDKの要点

- 公式SDKはGitHubの [a2aproject/a2a-java](https://github.com/a2aproject/a2a-java)（Apache-2.0）です。1.0.0.Final（2026年6月10日）が初のGA版で、最新は1.5.0.Final（2026年11月3日）です。Java 17以上とMaven 3.8以上が要ります。
- サーバーは、エージェントの名刺にあたるAgentCardと、処理本体のAgentExecutorの2つのBeanで動きます。LLMを使うなら、LangChain4jのAIサービスをAgentExecutorから呼びます。
- 1.3.0から認可は既定で拒否（fail-closed）です。認可プロバイダを置かないと、新規の `SendMessage` も `-32001 Task not found` で返ります。ひとりで試すときだけ `a2a.authorization.required=false` を設定します。
- 1.2.0〜1.3.1には、認可の素通りやSSRFなど5件の脆弱性勧告が出ています。使うなら1.3.2.Final以上、新規なら1.5.0.Finalにします。
- 0.3系から上げると、`groupId` とパッケージが `org.a2aproject.sdk` に変わり、`EventQueue`・`TaskUpdater` は `AgentEmitter` に置き換わります。Google ADK for Java（1.14.0）は2026年11月5日時点でも0.3系に依存しています。

## A2A Java SDKの位置づけと版の履歴

A2Aは、別々のフレームワークや言語で作られたエージェントが、互いの能力を調べて仕事を頼み合うための通信規約で、Linux Foundationのプロジェクトとして運営されています。仕様そのものやMCPとの違いは[A2A（Agent2Agent）プロトコルとは？v1.0の仕組み・MCPとの違い・セキュリティ対策と実装手順](/tech/details/6732/)で解説しているので、ここではJava実装に絞ります。

A2A Java SDKは、Red HatのQuarkusチームとWildFlyチームがGoogleと協力して立ち上げました。2025年の0.2系・0.3系を経て、A2A仕様1.0.0に合わせた1.0.0.FinalからGAです。その後はおよそ月1回のペースで出ています（日付は[GitHubのリリース一覧](https://github.com/a2aproject/a2a-java/releases)の公開日）。

| 版           | 公開日        | 主な変更                   |
| ----------- | ---------- | ---------------------- |
| 1.0.0.Final | 2026-06-10 | 初のGA版。A2A仕様1.0.0に準拠    |
| 1.1.0.Final | 2026-06-29 | タスク単位の認可SPI（既定は許可）     |
| 1.2.0.Final | 2026-08-07 | 認可の強化、ストリームのフック        |
| 1.3.0.Final | 2026-08-27 | マルチテナント、認可の既定を拒否に      |
| 1.3.2.Final | 2026-09-08 | Android版HTTPクライアントの修正  |
| 1.4.0.Final | 2026-09-28 | SSE解析の上限、RESTの新メディアタイプ |
| 1.5.0.Final | 2026-11-03 | HTTPクライアント設定の統合、リダイレクト |

[1.5.0.Finalのリリースノート](https://github.com/a2aproject/a2a-java/releases/tag/v1.5.0.Final)では、互換性を壊す変更が2件告知されています。1件はサーバー側の入力検証の一元化で、transportのハンドラーを直接使う統合ライブラリ向けです。PRには「利用者向けの公開APIは変わらない」とあり、実際に1.4.0.Final用に書いたサーバーとクライアントは、ソースを変えずに1.5.0.Finalでビルドと実行が通りました。もう1件はHTTPクライアントの設定を `A2AHttpClientConfiguration` にまとめた変更で、JDKの `HttpClient` を自前で渡している場合に影響します（後述）。

## 依存関係の選び方：BOMとトランスポート

座標はすべて `org.a2aproject.sdk` です。BOMは3種類あり、Quarkusで作るなら参照実装用を読み込みます。

| BOM                          | 使う場面                  |
| ---------------------------- | --------------------- |
| `a2a-java-sdk-bom`           | Spring Bootや素のJavaで組む |
| `a2a-java-sdk-extras-bom`    | DB永続化・複数台構成を足す        |
| `a2a-java-sdk-reference-bom` | Quarkusの参照実装を使う       |

サーバーはトランスポートごとに `a2a-java-sdk-reference-jsonrpc`・`-grpc`・`-rest` を選び、複数を同時に入れられます。クライアントは `a2a-java-sdk-client` にJSON-RPCが含まれ、gRPCとRESTは `a2a-java-sdk-client-transport-grpc`・`-rest` を足します。検証に使ったサーバーのpom.xmlの要点は次のとおりです。

```
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.a2aproject.sdk</groupId>
      <artifactId>a2a-java-sdk-reference-bom</artifactId>
      <version>1.5.0.Final</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>org.a2aproject.sdk</groupId>
    <artifactId>a2a-java-sdk-reference-jsonrpc</artifactId>
  </dependency>
</dependencies>
<!-- build の quarkus-maven-plugin は 3.40.1.1（SDK 1.5.0の親pomが使う版）に揃える -->
```

プラグインの版は、SDKの親pomにある `quarkus.platform.version` に合わせます。BOMが持ち込むQuarkus本体は3.40.1.1なので、プラグインだけ古い3.39.2のままでも起動はしましたが、ビルド時と実行時でQuarkusの版がずれた状態になります。importやファイル配置を含む完全な構成は、公式リポジトリの [examples/helloworld](https://github.com/a2aproject/a2a-java/tree/v1.5.0.Final/examples/helloworld)（Quarkusのサーバーと、それを呼ぶクライアント）が参考になります。検証では `mvn package` でビルドし、`java -jar target/quarkus-app/quarkus-run.jar` で起動しました。

## A2Aサーバーの実装手順（Quarkus）

サーバー側で書くのは、AgentCardを返すBeanと、AgentExecutorを返すBeanの2つです。まず、受け取った文字列を大文字にして返すだけのエージェントで仕組みを確かめ、次にLLMを呼ぶ形へ広げます。動作確認はTemurin 25.0.5とQuarkus 3.40.1.1で行いました。以下の接続先に合わせ、サーバーの `src/main/resources/application.properties` に `quarkus.http.port=9999` を設定します。

### AgentCardの定義と公開先

`@PublicAgentCard` を付けたAgentCardは `/.well-known/agent-card.json` で公開されます。`supportedInterfaces` に、どの方式でどのURLに接続できるかを書きます。

```
@ApplicationScoped
public class AgentCardProducer {

    @Produces
    @PublicAgentCard
    public AgentCard agentCard() {
        return AgentCard.builder()
                .name("Upper Agent")
                .description("受け取ったテキストを大文字にして返す")
                .supportedInterfaces(List.of(
                        new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999")))
                .version("1.0.0")
                .capabilities(AgentCapabilities.builder().streaming(true).pushNotifications(false).build())
                .defaultInputModes(List.of("text"))
                .defaultOutputModes(List.of("text"))
                .skills(List.of(AgentSkill.builder()
                        .id("upper")
                        .name("Uppercase")
                        .description("テキストを大文字に変換する")
                        .tags(List.of("text"))
                        .examples(List.of("hello a2a"))
                        .build()))
                .build();
    }
}
```

起動後に `curl http://localhost:9999/.well-known/agent-card.json` で取得すると、上の内容がJSONで返り、応答ヘッダーには `Cache-Control: public, max-age=3600` が付きました。キャッシュ時間は `a2a.agent-card.cache.max-age` で変えられます。認証済みの相手にだけ見せたい能力は `@ExtendedAgentCard` 側に書き、`GetExtendedAgentCard` で返します。SDKはこのメソッドを個別に認証しないので、Quarkus Securityなどで認証をかけてください。

### AgentExecutorとAgentEmitterによるタスク処理

AgentExecutorの `execute` が処理の本体で、`AgentEmitter` を通じてタスクの状態とアウトプット（Artifact）を送ります。

```
@ApplicationScoped
public class AgentExecutorProducer {

    @Produces
    public AgentExecutor agentExecutor() {
        return new AgentExecutor() {
            @Override
            public void execute(RequestContext context, AgentEmitter emitter) throws A2AError {
                if (context.getTask() == null) {
                    emitter.submit();          // 新規タスクとして受け付ける
                }
                emitter.startWork();           // TASK_STATE_WORKING へ
                StringBuilder sb = new StringBuilder();
                for (Part<?> part : context.getMessage().parts()) {
                    if (part instanceof TextPart text) {
                        sb.append(text.text());
                    }
                }
                emitter.addArtifact(List.of(new TextPart(sb.toString().toUpperCase())));
                emitter.complete();            // TASK_STATE_COMPLETED へ
            }

            @Override
            public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError {
                emitter.cancel();
            }
        };
    }
}
```

ストリーミングで呼ぶと、この順序がそのままSSEのイベントになります。実測では `TASK_STATE_SUBMITTED` → `TASK_STATE_WORKING` → Artifactの更新 → `TASK_STATE_COMPLETED` の4件が届きました。キャンセルできない状態のタスクには `TaskNotCancelableError` を投げます。

### LangChain4jによるLLM呼び出しとタイムアウト設定

Quarkusの公式ブログや多くのチュートリアルは、Quarkus LangChain4jのAIサービスをA2Aで公開する構成を取ります。1.xでも形は同じで、AIサービスをAgentExecutorに注入し、戻り値を `addArtifact` に渡します。依存に `io.quarkiverse.langchain4j:quarkus-langchain4j-openai` の1.14.2を足し、次のインターフェースを置きます。

```
@RegisterAiService
public interface Summarizer {

    @SystemMessage("受け取った文章を日本語で3行に要約してください。")
    String summarize(@UserMessage String text);
}
```

上のAgentExecutorProducerに `@Inject Summarizer summarizer;` を足し、`toUpperCase()` を含む行全体を `emitter.addArtifact(List.of(new TextPart(summarizer.summarize(sb.toString()))));` に置き換えます。APIキーは `quarkus.langchain4j.openai.api-key`、接続先は `quarkus.langchain4j.openai.base-url` で指定します。接続先をローカルに立てたOpenAI互換のモックへ向けて `SendMessage` を送ると、システムメッセージとユーザーの文章がモデルへ渡り、モックの応答がArtifactに入って `TASK_STATE_COMPLETED` で返りました。モデル名を省くと、リクエストには既定の `gpt-4o-mini` が入っていたので、本番では `quarkus.langchain4j.openai.chat-model.model-name` を明示します。

LLMを呼ぶときは、2つのタイムアウトが重なる点に注意してください。Quarkus LangChain4jのOpenAI呼び出しは既定10秒（`quarkus.langchain4j.openai.timeout`）、A2A側の同期呼び出しでエージェントの完了を待つ時間は既定30秒（`a2a.blocking.agent.timeout.seconds`）です。長い生成では先に10秒の側で失敗します。SDKの[設定ガイド](https://github.com/a2aproject/a2a-java/blob/v1.5.0.Final/docs/content/dev/configuration.md)はLLMを使うエージェントに60〜120秒を勧めているので、LLM呼び出し側のタイムアウトを生成時間に合わせて伸ばします。そのうえで、A2A側も同期呼び出しの待機時間を伸ばすか、ストリーミング受信に切り替えます。

### 既定のfail-closed認可でリクエストが拒否される理由

AgentCardとAgentExecutorだけで起動し、JSON-RPCで `SendMessage` を送ると、エージェントは呼ばれず次のエラーが返ります。1.5.0.Finalでも同じでした。

```
curl -s -X POST http://localhost:9999/ \
  -H 'Content-Type: application/json' -H 'A2A-Version: 1.0' \
  -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{"message":{"role":"ROLE_USER","parts":[{"text":"hello a2a"}],"messageId":"m-1"}}}'

{"jsonrpc":"2.0","id":1,"error":{"code":-32001,"message":"Task not found", ...}}
```

原因は、1.3.0で認可の既定が「プロバイダが無ければ全操作を拒否」に変わったことです。拒否はタスクの存在を推測させないよう `Task not found` として返るため、エラー文から認可の問題だと気づきにくくなっています。ストリーミングの `SendStreamingMessage` でも、SSEの最初のイベントとして同じ `-32001` が届きました。ひとりで試すときは `application.properties` に次の1行を足します。

```
a2a.authorization.required=false
```

この設定で再起動すると、同じリクエストに `"state":"TASK_STATE_COMPLETED"` と `"text":"HELLO A2A"` を含む結果が返りました。ただし、この設定はプロバイダが無いときの拒否を外すだけで、プロバイダを置けばそちらの判定が常に優先されます（[認可ガイド](https://github.com/a2aproject/a2a-java/blob/v1.5.0.Final/docs/content/dev/authorization.md)）。複数の利用者が使う本番では、この設定に頼らず `TaskAuthorizationProvider` を実装します。新規タスクは `checkCreate` で受け付けて `recordOwnership` で作成者を記録し、既存タスクは `checkRead`・`checkWrite` で作成者と呼び出し元が一致するかを判定します。認証基盤の候補は[Keycloakとは？Oktaとの違いと連携手順｜Auth0・Cognito比較で導入を判断【2026年10月】](/tech/details/7663/)で比較しています。

## Javaクライアントの実装：AgentCard取得からストリーミング受信まで

クライアントはAgentCardを取得し、その内容から `Client` を組み立てます。受け取ったイベントは登録したコンシューマに届きます。

```
AgentCard card = A2ACardResolver.builder()
        .baseUrl("http://localhost:9999")
        .build()
        .getAgentCard();

CountDownLatch done = new CountDownLatch(1);   // ストリーム終了を待つ

List<BiConsumer<ClientEvent, AgentCard>> consumers = List.of((event, c) -> {
    if (event instanceof TaskUpdateEvent u) {
        System.out.println("update: " + u.getTask().status().state());
    }
});

try (Client client = Client.builder(card)
        .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig())
        .addConsumers(consumers)
        .streamingErrorHandler(e -> {
            if (e != null) e.printStackTrace();   // null は正常終了の合図
            done.countDown();
        })
        .build()) {
    client.sendMessage(A2A.toUserMessage("hello a2a"));   // 送信後すぐ戻る
    if (!done.await(30, TimeUnit.SECONDS)) {
        throw new java.util.concurrent.TimeoutException("A2Aストリームが30秒以内に終了しませんでした");
    }
}
```

サーバーがストリーミングに対応していれば、`sendMessage` は自動でストリーミングを使い、応答を待たずに戻ります。`main` から呼ぶなら、上のように `CountDownLatch` などで終わりを待ちます。待たないと、イベントが届く前にJVMが終了します。1.5.0.Finalで実行すると、`TaskUpdateEvent` が4回（SUBMITTED、WORKING、Artifact追加時のWORKING、COMPLETED）届き、最後のタスクに `HELLO A2A` のArtifactが入っていました。`streamingErrorHandler` は正常終了のときにも引数 `null` で1回呼ばれます。ソースの `AbstractSSEEventListener` にも `null to signal normal completion` と書かれているので、null判定を入れないとエラー処理が誤って動きます。

既定のHTTPクライアントはリダイレクトを追いません。認証情報が別のドメインへ転送されるのを防ぐためです。1.5.0では、リクエストごとに `followRedirects(true)` を付けると1回だけ追えるようになり、AgentCardの取得ではこれが自動で有効です。ストリーミングの通信はリダイレクトを追いません。自前の `HttpClient` を `JdkA2AHttpClient` に渡す場合は、JDK側のリダイレクト設定を既定の `NEVER` のままにします。それ以外を設定すると、`followRedirects(true)` を付けたリクエストは `IOException` で拒否されます。APIキーを送るヘッダー名も、`Authorization`・`X-API-Key` など5種類の許可リストに無ければ付与されません。

## 脆弱性勧告と上げるべき版

A2A Java SDKには、1.2.0.Final〜1.3.1.Finalを対象とする[GitHubセキュリティアドバイザリ](https://github.com/a2aproject/a2a-java/security/advisories)が5件出ています。いずれも1.3.0.Finalか1.3.2.Finalで修正済みです。

| 勧告                                                                                                    | 深刻度    | 内容                        | 修正版         |
| ----------------------------------------------------------------------------------------------------- | ------ | ------------------------- | ----------- |
| [GHSA-qw47-mcm5-934w](https://github.com/a2aproject/a2a-java/security/advisories/GHSA-qw47-mcm5-934w) | High   | タスク認可の既定が許可               | 1.3.0.Final |
| [GHSA-q78c-5jjq-57g8](https://github.com/a2aproject/a2a-java/security/advisories/GHSA-q78c-5jjq-57g8) | Medium | プッシュ通知送信のSSRF             | 1.3.0.Final |
| [GHSA-9rhm-2h4x-jwmx](https://github.com/a2aproject/a2a-java/security/advisories/GHSA-9rhm-2h4x-jwmx) | Medium | 相手指定のヘッダー名で認証情報を送信        | 1.3.0.Final |
| [GHSA-x32g-jvvm-4725](https://github.com/a2aproject/a2a-java/security/advisories/GHSA-x32g-jvvm-4725) | Medium | 通知用の認証情報をログに平文出力          | 1.3.0.Final |
| [GHSA-4fpj-g9jf-9rgg](https://github.com/a2aproject/a2a-java/security/advisories/GHSA-4fpj-g9jf-9rgg) | High   | Android版POSTが別ホストへ認証情報を転送 | 1.3.2.Final |

上の認可の既定変更とヘッダー名の許可リストは、この勧告への対応として入ったものです。認可プロバイダを置かずに1.1〜1.2系で動かしているサーバーは、上げただけで拒否側に切り替わり、それまで通っていたリクエストが `-32001` になります。先に `TaskAuthorizationProvider` を用意してから上げてください。0.3系（`io.github.a2asdk`）は2026年11月3日に保守版の0.3.4が出ていますが、Maven上の版名は `.Final` の付かない `0.3.4` です。

## 0.3系の記事やサンプルから移行するときの差分

「A2A Java」で見つかるチュートリアルの多くは2025年の0.2〜0.3系向けです。0.3.3.Finalのjarと1.x のソースを照合した差分は次のとおりです。

| 項目            | 0.3系                          | 1.x                     |
| ------------- | ----------------------------- | ----------------------- |
| groupId       | `io.github.a2asdk`            | `org.a2aproject.sdk`    |
| パッケージ         | `io.a2a.*`                    | `org.a2aproject.sdk.*`  |
| 処理の引数         | `EventQueue` \+ `TaskUpdater` | `AgentEmitter`          |
| 値の取得          | `task.getStatus()`            | `task.status()`（record） |
| JSON-RPCメソッド  | `message/send`                | `SendMessage`           |
| AgentCardの接続先 | `url` \+ `preferredTransport` | `supportedInterfaces`   |

1.5.0のサーバーに対して確かめると、`A2A-Version` ヘッダーを省いたリクエストは0.3扱いになり `-32009 Protocol version '0.3' is not supported` で拒否され、旧メソッド名の `message/send` は `-32601` でした。`params` を省いた `SendMessage` は `-32602 Parameter 'message' may not be null` です。古いクライアントを残したまま移行するなら、`a2a-java-sdk-reference-multiversion-jsonrpc`（RESTは `-multiversion-rest`）を使うと、ヘッダーが `1.0` なら1.0、`0.3` か省略なら0.3の処理系へ振り分けられ、`AgentExecutor` は書き換えずに済みます。この場合はAgentCardのビルダーに、0.3のクライアントが見る `url`・`preferredTransport`・`additionalInterfaces`（`Legacy_0_3_AgentInterface` を渡す）も設定します。0.3系のエージェントを呼ぶ側は、`a2a-java-sdk-compat-0.3-client` の `Client_v0_3` を使います。

## Spring Boot・Google ADKと組み合わせるときの選択肢

公式SDKの参照実装はQuarkusで、Jakarta EE向けにはWildFlyチームの `a2a-jakarta` があります。Spring Bootで使う選択肢は、2026年11月時点で次の4つです。

| 選択肢            | 最新版                | 依存するA2A SDK |
| -------------- | ------------------ | ----------- |
| 公式SDKを手で配線     | 1.5.0.Final        | 1.x         |
| spring-ai-a2a  | 0.4.0（2026-10-23）  | 1.4.0.Final |
| a2a-spring     | 0.1.0-SNAPSHOT     | 1.x         |
| google-adk-a2a | 1.14.0（2026-11-02） | 0.3.2.Final |

- **公式SDKを手で配線する**：[サーバーガイド](https://github.com/a2aproject/a2a-java/blob/v1.5.0.Final/docs/content/dev/server.md)に、`MainEventBus`・`DefaultRequestHandler` などをSpringのBeanとして登録する例があります。手で組んだハンドラーには `a2a.blocking.*` の設定が効かないので、タイムアウトはビルダーの `agentCompletionTimeoutSeconds(int)` などで指定します。
- **spring-ai-a2a**：Spring AIのChatClientをA2Aサーバーとして公開するコミュニティ製の統合です。[0.4.0](https://github.com/spring-ai-community/spring-ai-a2a/releases/tag/v0.4.0)でSpring Boot 4.1.1・Spring AI 2.0.1へ上がり、A2A 1.0のJSON-RPCをSDKの処理系で受けるようになりました。READMEのサンプルは旧APIの書き方を含むため、依存の版番号だけでなく、AgentCardのビルダーや接続先の定義、JSON-RPCリクエストも1.x向けに修正します。Spring AI自体の組み込みは[Spring AIの使い方：Spring Bootへの組み込み手順と2.0の変更点](/tech/details/2590/)を参照してください。
- **a2a-spring**：公式のサーバーガイドに1.5.0から載ったSpring MVC向けの統合です。READMEは自らを初期のMVPとしており、Maven Centralには未公開なので、本番では採用を見送るべきです。
- **Google ADK for Java**：`com.google.adk:google-adk-a2a` でADKのエージェントをA2Aで公開できますが、[1.14.0のpom](https://repo1.maven.org/maven2/com/google/adk/google-adk-a2a/1.14.0/google-adk-a2a-1.14.0.pom)が依存しているのは旧座標の0.3.2.Finalです。ADK自体は[ADKとは？GoogleのAgent Development Kitの仕組みと始め方【2.11対応】](/tech/details/7936/)で紹介しています。

新規に作るなら、公式SDKの1.xか、それに乗ったspring-ai-a2a 0.4.0を選びます。ADKなど0.3系に依存する統合から1.0専用のエージェントを呼ぶと、`message/send` が通らず `-32601` で弾かれます。相手が0.3系なら、受ける側は互換モジュールで両方の版を受け付け、呼ぶ側は `Client_v0_3` を使います。言語をまたいだフレームワーク選びは[AIエージェントフレームワークとは？主要8種の比較・動作コード・選定基準【2026年9月版】](/tech/details/15367/)で比べています。業務システムへのエージェント組み込みを外部に相談するなら、一創の[AIエージェント開発](/service/ai/agent/)でも設計から支援しています。

## 本番運用で差し替えるコンポーネント

既定のタスクストアとキューはメモリ上にあり、再起動で消え、複数台では共有されません。extrasモジュールを足して接続先を設定すれば、`AgentExecutor` を変えずに差し替わります。

| 用途          | モジュール                                       |
| ----------- | ------------------------------------------- |
| タスクの永続化     | `a2a-java-extras-task-store-database-jpa`   |
| 複数台でのイベント共有 | `a2a-java-queue-manager-replicated-core` ほか |
| 分散トレース      | `a2a-java-sdk-opentelemetry-server`         |
| マルチテナント     | `a2a-java-extras-multitenancy`              |

1.5.0では、JPAのタスクストアに所有者を保存する `JpaTaskAuthorizationProvider` が加わりました。モジュールを入れただけでは有効にならず、Quarkusでは `quarkus.arc.selected-alternatives` で明示的に選びます。タスク一覧の取得で、他人のタスクを除いた件数とページをDB側で絞り込めるようになります。OpenTelemetryのモジュールも、ストリーミングとプッシュ通知の区間を記録するようになりました。トレースの基盤は[OpenTelemetryとは？仕組み・Collectorの導入手順とPrometheusとの違い【2026年10月】](/tech/details/3625/)で解説しています。

複数台構成のイベント共有は、`replicated-core` に `a2a-java-queue-manager-replication-mp-reactive` を組み合わせ、Kafka・Pulsar・AMQPのいずれかを使います。プッシュ通知の送り先URLは既定で `https` のみ、社内ネットワーク宛ては拒否されます（上のSSRF勧告への対策）。開発中に `http://localhost` へ送りたいときだけ、`a2a.push-notification.url.allowed-schemes=http,https` と `a2a.push-notification.url.allow-private-network-targets=true` を設定します。エージェントをいくつに分けるべきかは[マルチエージェントとは？仕組み・構成パターンと採用判断を研究データで解説【2026年10月】](/tech/details/13604/)で扱っています。

## よくある質問

### A2A Java SDKはJava 11で動きますか？

1.x はJava 17以上が必要です。SDKのビルド設定も `release` 17で、入門ガイドの要件はJava 17以上とMaven 3.8以上です。

### Python製のA2Aエージェントと通信できますか？

できます。A2Aは言語に依存しない規約で、公式のHello Worldサンプルも、JavaサーバーをPythonクライアントから呼ぶ構成です。双方が同じプロトコル版（1.0か0.3）を話しているかを先に確かめてください。

### 「A2Aバス」や「sendEvent」というAPIはありますか？

公式SDKにはありません。1.xの公開APIは、サーバー側が `AgentExecutor` と `AgentEmitter`、クライアント側が `Client` の `sendMessage`・`getTask`・`cancelTask` などです。内部の `MainEventBus` は、イベントをタスクストアへ保存してから配信する仕組みで、エージェント間のメッセージバスではありません。

### gRPCとJSON-RPCのどちらを選べばよいですか？

SDKは3方式を同格に扱い、依存関係を並べれば同時に公開できます。ブラウザや他言語のクライアントから呼ぶならJSON-RPCかREST、社内のJava同士で型付きの通信をしたいならgRPCが向きます。

### MCPとA2Aは両方必要ですか？

役割が違います。MCPはエージェントが外部ツールやデータを呼ぶための規約で、A2Aはエージェント同士が仕事を頼み合うための規約です。ツール接続の実装は[MCPサーバーの作り方とAIエージェントへの接続手順｜Python SDK 2.3でツール定義・認可を実装](/tech/details/15365/)で解説しています。

## 関連記事

- [A2A（Agent2Agent）プロトコルとは？v1.0の仕組み・MCPとの違い・セキュリティ対策と実装手順](/tech/details/6732/)
- [ADKとは？GoogleのAgent Development Kitの仕組みと始め方【2.11対応】](/tech/details/7936/)
- [マルチエージェントとは？仕組み・構成パターンと採用判断を研究データで解説【2026年10月】](/tech/details/13604/)
- [AIエージェントフレームワークとは？主要8種の比較・動作コード・選定基準【2026年9月版】](/tech/details/15367/)
- [Spring AIの使い方：Spring Bootへの組み込み手順と2.0の変更点](/tech/details/2590/)

---

出典: [A2A Java SDKの使い方｜Quarkusでのサーバー・クライアント実装とLLM連携、0.3系からの移行【1.5対応】](<https://www.issoh.co.jp/tech/details/7234/>)（株式会社一創）
