10分くらいでできるA2Aのはじめ方
(2025/05/08)uv venv
の手順に誤りがあり修正しました。
概要
対象者:エージェント連携やA2Aに興味のあるAIエンジニアや開発者
内容:Google製のA2Aプロトコルを用いた複数エージェント連携チュートリアルの実践解説
できること:複数のAIエージェントをA2Aで接続し、統合チャットUIから対話・実行できるようになる
序説
本日、A2Aチュートリアルを触りました。
1回目構築: 1時間30分(エラーで2回ハマる)
2回目構築: 10分くらい !? ※個人差あり
という感じでちょっと詰まった部分がありましたので、共有したいと思います!
A2Aとは
エージェントとエージェントをつなげるプロトコルです!
たとえば、チャットボット・画像生成・為替変換など異なるAIサービスを連携させて、一貫したユーザー体験を提供できます。
An open protocol enabling communication and interoperability between opaque agentic applications.
作るもの
この図のようなものを作ります。
ユーザが何か入力したら、ホストエージェントが、どのエージェント動かせるか確認し、
A2Aを介して、各エージェントに依頼し、実行し、結果を返し、ホストエージェントがいい感じにまとめ、ユーザに返す。
こんなチュートリアルがあるのでやってみましょう!
事前準備
- python3.12以上
- uv
- gemini apiキー
手順
セットアップ
まず、以下のコマンドよりgitcloneします。
git clone https://github.com/google/A2A.git
cd A2A
目安ここまでで1分くらいです。(ここまでは大丈夫ですよね!)
gemini apiキー取得
Get API keyから、Create API keyを選択し、取得します。
セキュリティに注意!
.env ファイルには秘密情報が含まれるため、Gitにコミットしないよう .gitignore に追加しておきましょう。
目安ここまでで2分くらいです。(ここもよくあるやつですよね!)
リモートエージェント
uv の仮想環境を作り、リモートエージェントを立ち上げる作業をします。
エージェント | ポート | 機能概要 |
---|---|---|
経費申請エージェント | 10000 | ユーザーの入力をもとに仮の経費申請処理を行う |
画像生成エージェント | 10001 | テキストをもとに画像を生成する |
為替エージェント | 10002 | 円からドルへの為替変換を行う |
経費申請エージェント作成
経費申請をしてくれる(?)エージェントを作成します。
※どこかフォームに送信されることはありません。
以下のコマンドより実装します。
cd samples/python/agents/google_adk
uv venv
source .venv/bin/activate
echo "GOOGLE_API_KEY=your_api_key_here" > .env
uv run . --host 0.0.0.0 --port 10000
※ uv venv
で、仮想環境を作成します
画像生成エージェント
画像生成するエージェントを作成します。
別のターミナルを開き、以下のコマンドより実装します。
※先ほど起動した、localhost:10000は停止しないようにします。
cd samples/python/agents/langgraph
uv venv
source .venv/bin/activate
echo "GOOGLE_API_KEY=your_api_key_here" > .env
uv run . --host 0.0.0.0 --port 10001
為替エージェント
為替(円からドル計算など)をしてくれるエージェントを作成します。
別のターミナルを開き、以下のコマンドより実装します。
※先ほど起動した、localhost:10000、localhost:10001は停止しないようにします。
cd samples/python/agents/crewai
uv venv
source .venv/bin/activate
echo "GOOGLE_API_KEY=your_api_key_here" > .env
uv run . --host 0.0.0.0 --port 10002
missing field ‘version’
以下のエラーが出ない場合は、スキップしてください。
error: Failed to parse `uv.lock`
Caused by: TOML parse error at line 1, column 1
|
1 | revision = 2
| ^^^^^^^^^^^^
missing field `version`
versionがないので、エラーが出ていますので、versionを追加します。
samples/python/uv.lockの先頭に以下追加します。
version = 1
目安ここまでで6分くらいです。(ここまで作成完了していれば、もう少しです!)
ホストエージェント作成
3つのリモートエージェントとA2Aで接続するエージェントです。
別のターミナルを開き、以下のコマンドより実装します。
cd demo/ui
uv venv
source .venv/bin/activate
uv run main.py
成功すると、以下表示されます。
以下のurlをブラウザから開きます。
http://0.0.0.0:12000/
about blank
http://0.0.0.0:12000/ で開けた人はスキップしてください。
http://0.0.0.0:12000/ のままでは、開かない可能性があります。
その場合は、urlを以下に直してみてください
http://localhost:12000
以下の画面が表示されれば、成功です。
目安ここまでで8分くらいです。(ほぼゴール直前!)
エージェントカード追加
左のタブから「Agents」を選択します。
そして、リスト一覧にある「↑」を選択します。
Agent Addressには、以下のリモートエージェントのアドレスを追加します。
0.0.0.0:10000
追加されるエージェントを確認し、Saveを選択します。
同様の手順で、別のエージェントも追加します。
0.0.0.0:10001
0.0.0.0:10002
目安ここまでで9分くらいです。(ほぼゴールしました。おめでとうございます!)
チャットのテスト
左のタブより「Home」を選択します。
そして、リストにある「+」を選択します。
そうすると、チャットボットが動きます。
はじめにおすすめの聞き方として、どういうエージェントがあるのか聞くと良さそうです。
あなたは、何ができます?
あとは、そのエージェントとやりとりを楽しんでください!
「画像を生成して」
「1万円をドルに換算して」
「経費申請をお願い」
こんな感じで、10分くらいでできると思います!(お疲れ様でした!)
流れ
ここでは、経費申請のエージェントがどいう流れか追ってみます。
- ユーザーがA2Aクライアントを通じてリクエストを送信
- A2Aサーバーがリクエストを受け取り、TaskManagerに転送
- TaskManagerがReimbursementAgentを呼び出し
- エージェントがフォームを生成し、ユーザーに返す
- ユーザーがフォームに入力して返信
- エージェントが入力を検証し、経費精算を実行
- 結果をユーザーに返す
経費精算を実行は、agent.pyのreimburse()で実行していますが、
ただ、文字列"approved"を返しているだけです。
本来は、ここのreturnの前に処理を追加する必要がありそうです。
おまけ: 厳しい経費担当者にする
エージェントが入力を検証は、agent.pyの_build_agent()で実行しています。
よくみると、日付、金額、目的さえあれば承認するというシステムになってます。
なので、例えば豪遊というとんでもない目的でも承認の判定になります。
そこで、一部instructionを変更してやることで、承認の判定を制御することができます。
例えば、以下のように変更してみます。
For valid reimbursement requests and valide use for business such as not private enjoyment, you can then use reimburse() to reimburse the employee.
すると、今度は、豪遊は適切でないと判断され拒否されました。
A2Aとは
さてここから本題なのですが、A2Aとは一体なんなのでしょうか?
An open protocol enabling communication and interoperability between opaque agentic applications.
冒頭でサラッと流したのですが、これ訳すと「不透明なエージェント アプリケーション間の通信と相互運用性を可能にするオープンプロトコル」なんですよ。
ちゃんと読むしかないですね!!
背景
まず、A2Aの作られた背景が書かれていました。
One of the biggest challenges in enterprise AI adoption is getting agents built on different frameworks and vendors to work together.That's why we created an open Agent2Agent (A2A) protocol,
Google is driving this open protocol initiative for the industry because we believe this protocol will be critical to support multi-agent communication by giving your agents a common language – irrespective of the framework or vendor they are built on.
今エージェントフレームワーク戦国時代が幕開けしているのですが、
一旦手をとりやって仲良くやって行こうじゃないですか。
それが、AI国の繁栄に繋がり、きっと将来役に立つと思うんですよ。(Google主体で)
という思想を感じました。
コア要素
用語 | 説明 |
---|---|
Agent Skills | エージェントがどういうことができるか。 |
Agent Capabilities | エージェントがどのようにうのか。 |
Agent Card | Agent Skills・Agent Capabilities・エンドポイントURL・認証要 |
Agent Skills
エージェントがエージェントがどういうことができるかという情報です。
例えば、今回のチュートリアルの該当箇所はこちらです。
仕様はここに書かれていました。
ホストAgentがサーバAgentを選ぶ際、ここを元にする重要な要素です。
idとnameが必須でした。
項目 | 説明 |
---|---|
id | スキルのユニーク識別子。例:"translate-text"
|
name | スキルの人間向け名称。例:"Text Translation"
|
description | スキルの説明文。クライアントや人間がスキルの機能を理解するためのヒント。例:"Translate input text into multiple languages."
|
tags | このスキルが属する能力クラスのタグ一覧。例:["translation", "language", "NLP"]
|
examples | このスキルが対応できる具体的なプロンプト例。例:["Translate this to French", "How do you say 'hello' in Japanese?"]
|
inputModes | 入力に対応するMIMEタイプ一覧(任意)。例:["text/plain", "application/json"]
|
outputModes | 出力に対応するMIMEタイプ一覧(任意)。例:["text/plain", "application/json"]
|
Agent Capabilites
エージェントがどのように通信できるかという情報です。
例えば、今回のチュートリアルの該当箇所はこちらです。
仕様はここに書かれていました。
-
streaming
trueの場合、エージェントはServer-Sent Events(SSE)を使用してリアルタイムの更新を提供できます。
クライアントはtasks/sendSubscribeメソッドを使用して、タスクの進行状況やアーティファクトの更新をリアルタイムで受け取ることができます。
chatgptにみたいに一文字ずつ出したい場合は、Trueです。 -
pushNotifications
trueの場合、エージェントはクライアントが提供するWebhook URLに対して、タスクの更新を能動的に送信できます。
クライアントはtasks/pushNotification/setを使用してWebhook URLを設定できます。 -
stateTransitionHistory
trueの場合、エージェントはタスクの状態遷移履歴を提供できます。
これにより、クライアントはタスクがどのように進行したかの履歴を確認できます。
フィールド名 | 説明 |
---|---|
streaming | エージェントがストリーミングレスポンスをサポートしているかどうかを示す。(任意) |
pushNotifications | エージェントがプッシュ通知メカニズムをサポートしているかどうかを示す。(任意) |
stateTransitionHistory | エージェントが状態遷移履歴の提供をサポートしているかどうかを示す。 (任意) |
Agent Card
Remote Agents are required to publish an Agent Card in JSON format describing the agent's capabilities and skills in addition to authentication mechanisms. In other words, this lets the world know about your agent and how to interact with it. You can find more details in the
Agent SkillsやAgent Capabilities紐付け、エージェントのメタデータや機能を記述するための情報です。いわば、エージェントの名刺です。
例えば、今回のチュートリアルの該当箇所はこちらです。
仕様はここに書かれていました。
skillsやcapabilitiesやauthなど細かいことは切り出して作っておき、
それを最後まとめるところがこのAgent Cardです。
フィールド名 | 説明 |
---|---|
name | エージェントの人間向け名称(例:"Recipe Agent") |
description | エージェントの説明。ユーザーや他のエージェントが機能を理解するために使用される |
url | エージェントのホストURL |
provider | エージェントの提供者情報(組織名とURL) |
version | エージェントのバージョン(例:"1.0.0") |
documentationUrl | エージェントのドキュメントへのリンク(オプション) |
capabilities | エージェントがどういう通信をするか |
skills | エージェントがどういうスキルがあるか |
authentication | 使用可能な認証スキーム(例:"Basic", "Bearer")やプライベートカード用のクレデンシャル(オプション) |
defaultInputModes | エージェントがデフォルトで受け付ける入力形式(例:"text/plain") |
defaultOutputModes | エージェントがデフォルトで出力する形式(例:"application/json") |
skills | エージェントが提供するスキルのリスト |
Agent Cardのサンプルは以下のとおりです。
JSON-RPC形式になっています。
{
"name": "Google Maps Agent",
"description": "Plan routes, remember places, and generate directions",
"url": "https://maps-agent.google.com",
"provider": {
"organization": "Google",
"url": "https://google.com"
},
"version": "1.0.0",
"authentication": {
"schemes": "OAuth2"
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain", "application/html"],
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"skills": [
{
"id": "route-planner",
"name": "Route planning",
"description": "Helps plan routing between two locations",
"tags": ["maps", "routing", "navigation"],
"examples": [
"plan my route from Sunnyvale to Mountain View",
"what's the commute time from Sunnyvale to San Francisco at 9AM",
"create turn by turn directions from Sunnyvale to Mountain View"
],
// can return a video of the route
"outputModes": ["application/html", "video/mp4"]
},
{
"id": "custom-map",
"name": "My Map",
"description": "Manage a custom map with your own saved places",
"tags": ["custom-map", "saved-places"],
"examples": [
"show me my favorite restaurants on the map",
"create a visual of all places I've visited in the past year"
],
"outputModes": ["application/html"]
}
]
}
JSON-RPC形式とは、JSON形式でリクエスト&レスポンスを表現する仕様です。
A2AはJSON-RPCベースで設計されており、各エージェントのインタフェースや仕様はJSON Schemaで定義されています。OpenAPIに似た感覚で、形式的な記述によりインターオペラビリティが担保されています。
脱線しましたが、まとめるとクラス図はこんな感じです。
AgentCardは中心的なクラスで、エージェントのメタデータと機能を記述します。
AgentSkill: エージェントが提供する特定のスキルを定義します
AgentCapabilities: エージェントがサポートする機能を表します
そのほかにも以下の要素があります
AgentProvider: エージェントの提供者情報を表します
AgentAuthentication: 認証スキームと資格情報を定義します
結言
A2Aと関係ないのですが、
Zennでアンダースコア_
付きのgithubリンクを書く際、バックスラッシュ\
の追加もお忘れなく!
_
があるとリンクと認識されないみたいです
Discussion