🐾

たぬきが学ぶA2A入門

に公開

はじめに

業務上A2A技術というものと仲良くなる必要が出てきたので、アウトプット学習的な意味でもこの記事を書いてみることにした。
公式的なA2Aプロトコルに関するドキュメントはこれのようだ。最初にこれを読みつつ、実装を試す。
https://a2a-protocol.org/dev/tutorials/

これを読んでわかること:
A2Aの基本のき、A2Aのスタートロードマップの一例、動かしたスクリプト、困ったことなど

A2Aとは

定義

公式ドキュメントによると、
『A2Aプロトコルは「オープン標準(誰でも使える公開仕様)」で、AIエージェント同士が途切れなくスムーズに通信・協力できるようにするもの。
これはさまざまなフレームワークで作られたり、異なるベンダー(開発会社)によって作られたエージェントたちが共通に使える「言語」を提供する』
とのこと。
MCPはいろいろなツールをLLMに付属させて動かすためのUSB-C的なアイディアだという話は有名だが、それのAgentバージョンだと思えばよさそうだ。
ちなみに本や著者によってエージェントの定義って微妙に異なっているようだけれど、この公式ドキュメントでは
「エージェントとは、自律的に問題を解決し、自分の環境の中で独立して行動する存在」
と定義されている。
ふむ。

使用例

公式ドキュメントはご親切にどんなケースで使えるかまで説明してくれている。
海外旅行を計画したい、というときに
このタスクには、複数の専門エージェントを「オーケストレーション(調整・統合)」する必要がある。

・航空券予約エージェント
・ホテル予約エージェント
・現地ツアーのおすすめを出すエージェント
・為替レート変換エージェント
のような感じだ。

公式ドキュメントより引用

しかしこれをやろうとすると課題がある。

・開発者はよくエージェントを「ツールとしてラップ(包む)」ことで他のエージェントから使えるようにする。これは「Multi-agent Control Platform (Model Context Protocol)」でツールを公開する方法に似ている。ただエージェントは本来「直接交渉する」ように設計されているから。ツールとして包むと本来の能力が制限されてしまう。

・エージェント同士がやり取りするたびに「個別の専用ソリューション」を作らなきゃならず、大きなエンジニアリング負荷になる。

・新しい統合をするたびに特注開発が必要になり、イノベーションのスピードが遅くなる。

・エージェントややり取りの数が増えるほど、システムの拡張・維持が難しくなる。

・相互運用性が制限されるため、自然に複雑なAIエコシステムが形成されにくくなる。

・場当たり的な通信は一貫したセキュリティ対策に欠けることが多い。

これらを解決してくれるのがA2Aらしい。

A2AとMCPの違い

私はMCPとA2Aの違いがいまいちよくわからなかったのだが、詳しいサイトがあった。これも紹介しておこう。
https://a2a-protocol.org/dev/topics/a2a-and-mcp/

MCPは呼び出して戻り値を得るツールで、A2Aはより対話性や状態管理を重視されているという違いらしい。
ただし境界が曖昧なケースもあって、たとえば、あるエージェントのスキルが「ツールライク」であれば MCP にも見えるし、それを使う時はツール的な振る舞いになる場合もあるようだし、
実際のシステムの実装ではMCPとA2Aの両方を使うことが基本になるだろうとのこと。

MCP → モデルが外部データやツールにアクセスできるようにする「窓口」
A2A → 複数のエージェントが組織や技術の壁を越えてやり取りできる「共通言語」

のようなイメージらしい。

A2Aのリクエストの流れ

A2Aでのリクエスト処理は、4つの主要ステップから成り立つ。

・エージェントの発見: どのエージェントとやり取りできるかを探す。
・認証:信頼できる相手か確認する。
・メッセージ送信:エージェントにリクエストを送る
・ストリーミング:ストリーミング形式でメッセージをやり取りする(長時間タスクや逐次応答に対応)。

クライアント、A2Aサーバ、OAuthサーバとの3者間で情報をやりとりしながらこれらステップを行っていく。

A2Aエージェントが必要とするもの

A2Aエージェントは3つのものを必要としている。

・Skills(スキル):「このエージェントは何ができるか」という機能一覧。
・Agent Card:他のエージェントやクライアントが「どんなスキルがあるか」を見つけられるプロフィール情報
・Agent Executer:エージェントを実際に動かす部分

それぞれについて解説する。

スキル(Skill)について

Agent Skillとはエージェントが持つ個別の能力や機能を表す。

主な属性(a2a.types.AgentSkillで定義されているもの)は下記:
・id: スキルの一意な識別子
・name: 人間が読める名前
・description: 具体的に何をするかの説明
・tags: カテゴリーや検索用キーワード
・examples: サンプルのプロンプトやユースケース
・inputModes / outputModes: 入出力で扱えるメディアタイプ(例: "text/plain", "application/json")

で、例としては下のようなものがある。これはHelloworldを返すエージェントの例だ。

skill = AgentSkill(
    id='hello_world',
    name='Returns hello world',
    description='just returns hello world',
    tags=['hello world'],
    examples=['hi', 'hello world'],
)

AgentCardとは

エージェントカードはAgent CardとはA2Aサーバーが外部に公開する JSONドキュメントで、
通常は /.well-known/agent-card.json というエンドポイントでアクセスできる。
他のエージェントやクライアントはこれを読んで「このエージェントは何ができるのか」を知るらしい。

主な属性は下記のとおり:
・name, description, version: エージェントの基本情報(名前、説明、バージョン)
・url: このエージェントのA2Aサービスが動いている場所
・capabilities:サポートするA2A機能(例: ストリーミング、プッシュ通知など)
・defaultInputModes / defaultOutputModes: 標準の入出力フォーマット(例: "text", "application/json")
・skills:このエージェントが持っているスキルの一覧(前に定義した AgentSkill オブジェクト)

例はこう:

public_agent_card = AgentCard(
    name='Hello World Agent',
    description='Just a hello world agent',
    url='http://localhost:9999/',
    version='1.0.0',
    default_input_modes=['text'],
    default_output_modes=['text'],
    capabilities=AgentCapabilities(streaming=True),
    skills=[skill],  # Only the basic skill for the public card
    supports_authenticated_extended_card=True,
)

ここではskills=[skill]で上のHelloworldが呼び出している例。

Agent Executer

Agent Executer(直訳:エージェント実行者)というように、これは応答ロジックを担う部分。
A2A Python SDKではa2a.server.agent_execution.AgentExecutorクラスで定義されている。

主なメソッドは↓の通り:
・execute(self, context: RequestContext, event_queue: EventQueue)
: ユーザーからのリクエストが来たときに呼ばれる。コンテキスト情報をもとに処理して、event_queue を使ってメッセージなどをクライアントに送り返す。

・cancel(self, context: RequestContext, event_queue: EventQueue)
: 実行中のタスクをキャンセルするコマンドを受け付けたときの処理。例外を投げたり、適切に中断処理をする仕様。

試しに使ってみた例

ここまで読んできたドキュメントのクイックスタートをやってみる。
https://a2a-protocol.org/dev/tutorials/python/1-introduction/
PythonのSDKを使ったチュートリアルを体験できる。

※参考までに紹介するとGoogleのツールを使っていくことを考えるとこんなものもある。
https://codelabs.developers.google.com/intro-a2a-purchasing-concierge?hl=ja#1
映えるものをサッと作りたいならこっちがいいかも。

環境構築

環境セットアップはここに書いてあるのを上からやっていけばOK.
https://a2a-protocol.org/dev/tutorials/python/2-setup/#prerequisites
特につまるところはなかったけど、
リポジトリの中にrequirements.txtの似たようなファイルがいくつかあるから

pip install -r samples/python/requirements.txt

とちゃんとパスを指定してあげる必要があることに注意。じゃないと

python -c "import a2a; print('A2A SDK imported successfully')"

を実行したときにModule not found errorが出る。

A2Aサーバーを起動

このGitをCloneしている状態でエージェントカードとエージェントエグゼキューターができている状態なので、サーバをセットアップする。
環境を構築した後にコマンドを実行する。

.\a2a-start\a2a-samples> python samples/python/agents/helloworld/__main__.py

成功すると下のような表示がでる。

INFO:     Started server process [2****] #この[]内の番号は人によって違うかも
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:9999 (Press CTRL+C to quit)

これでサーバーが立ち上がって listening 状態になっている状態。

サーバと対話してみる

サーバーからエージェントカードを取得、A2AClientインスタンスを作成し、
非ストリーミング リクエストとストリーミングリクエストの両方を送信します。

まず違うウィンドウを立ち上げて、仮想環境をアクティベートします。
そのうえで、下を実行する。

cd a2a-samples
# the a2a-samples directoryから実行
python samples/python/agents/helloworld/test_client.py

すると、Hello worldというエージェントとSuper Hello worldというエージェントのカードを見て返事をしてきた様子が返ってくる。

おわりに

動かしながらA2A技術の基本要素に触れることができた。
チュートリアルにはLanggraphを使って実装する例も一緒に挙げられていた。
https://a2a-protocol.org/dev/tutorials/python/7-streaming-and-multiturn/
こちらもフォローアップしていけたらと思う。

読んでいただきありがとうございました。

Discussion