Agent Registry の Agent2Agent(A2A)エージェントは、エンドポイント URL とプロトコル バインディング(HTTP_JSON など)を含むプロトコル インターフェースをアドバタイズします。レジストリでエージェントの URL を検出して、カスタム オーケストレーターまたはクライアントから A2A メソッドを呼び出すことができます。
概要
| 仕様 | 詳細 |
|---|---|
| Discovery API | agentregistry.googleapis.com(v1) |
| 呼び出しプロキシ ホスト | LOCATION-discoveryengine.googleapis.com |
| プロトコル バインディング | HTTP_JSON |
| URL プロジェクト ID | Google Cloud プロジェクト番号(プロジェクト ID ではありません) |
| サポートされている A2A メソッド | GET /v1/card、POST /v1/message:send、POST /v1/message:stream |
| 必要なメッセージ スキーマ | message.role = "ROLE_USER"、content[].text、一意の messageId |
| 必要な IAM 権限 | roles/agentregistry.viewer(検出)と discoveryengine.assistants.assist(呼び出し) |
始める前に
- Google Cloud プロジェクトで Agent Registry API(
agentregistry.googleapis.com)と Discovery Engine API(discoveryengine.googleapis.com)を有効にします。 - エージェントが Gemini Enterprise app で直接作成されていない場合は、Agent Registry からエージェントをインポートし、エンドユーザーにアクセス権を付与します。手順については、Agent Registry から A2A エージェントをインポートするをご覧ください。
- 呼び出し元プリンシパルに適切な IAM 権限を付与します。
- レジストリを読み取る: Agent Registry 閲覧者(
roles/agentregistry.viewer)。 - エージェントを呼び出す: ディスカバリー エンジン編集者(
roles/discoveryengine.editor)またはdiscoveryengine.assistants.assistを含むカスタムロール。
- レジストリを読み取る: Agent Registry 閲覧者(
- アプリケーションのデフォルト認証情報(ADC)を使用して認証する場合は、割り当てプロジェクト ヘッダー
-H "X-Goog-User-Project: PROJECT_ID"を送信するようにクライアントを構成します。 - リモート エージェントをプログラムによるサブエージェントとしてラップする場合は、Agent Development Kit(ADK)ライブラリ(
pip install "google-adk[a2a]>=1.29.0")をインストールします。
ステップ 1: エージェントとその A2A エンドポイントを検出する
A2A エージェントを呼び出すには、まず Agent Registry でアドバタイズされた url を検出します。レジストリのロケーション(グローバル agentregistry.googleapis.com ホストのパスパラメータとして渡される us や eu など)にあるエージェントを一覧表示します。
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://agentregistry.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/agents?pageSize=100"
Google Cloud CLI を使用して、表示名の接頭辞でエージェントを検索することもできます。
gcloud agent-registry agents search \
--project=PROJECT_ID \
--location=LOCATION \
--search-string="displayName:My_Agent_*"
返されたエージェント リソースで、protocols 配列を確認します。type が A2A_AGENT に等しく、interfaces[].protocolBinding が HTTP_JSON に等しいエントリを見つけます。対応する url を抽出します。
{
"name": "projects/PROJECT_ID/locations/LOCATION/agents/AGENT_RESOURCE_ID",
"displayName": "My Agent",
"protocols": [
{
"type": "A2A_AGENT",
"protocolVersion": "0.3.0",
"interfaces": [
{
"url": "https://LOCATION-discoveryengine.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/collections/default_collection/engines/ENGINE_ID/assistants/default_assistant/agents/AGENT_ID/a2a",
"protocolBinding": "HTTP_JSON"
}
]
}
]
}
エージェント リソース スキーマの完全なリストについては、projects.locations.agents REST API リファレンスをご覧ください。
ステップ 2: エージェントカードを取得する
エージェント カードには、エージェントの ID、説明、入出力機能について記述したメタデータが用意されています。カードを取得するには、エージェントの A2A エンドポイント URL に追加された /v1/card パスに HTTP GET リクエストを送信します。
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"A2A_ENDPOINT_URL/v1/card"
レスポンス ペイロードの例:
{
"name": "My Agent",
"description": "What the agent does.",
"url": "A2A_ENDPOINT_URL",
"capabilities": {},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"preferredTransport": "HTTP+JSON"
}
ステップ 3: メッセージを送信する
ユーザーのクエリをエージェントに送信するには、/v1/message:send に POST リクエストを行います。リクエストの本文は A2A メッセージ スキーマに準拠している必要があります。role を ROLE_USER に設定し、テキスト部分を含む content 配列と一意に生成された messageId が必要です。
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"A2A_ENDPOINT_URL/v1/message:send" \
-d '{
"message": {
"role": "ROLE_USER",
"content": [
{
"text": "What can you help me with?"
}
],
"messageId": "UNIQUE_UUID_STRING"
}
}'
レスポンス ペイロードでは、エージェントの返信は message オブジェクト内で返されます。
{
"message": {
"contextId": "projects/PROJECT_NUMBER/locations/LOCATION/collections/default_collection/engines/ENGINE_ID/sessions/SESSION_ID",
"role": "ROLE_AGENT",
"content": [
{
"text": "I am an AI assistant..."
}
]
}
}
content[].text 内のテキスト文字列を連結して、完了した回答を表示します。同じセッション内で会話を続けるには、返された contextId 文字列を保存し、次のリクエストで message.contextId として指定します。
メッセージ ペイロード スキーマの完全なリストについては、A2A message:send REST API リファレンスをご覧ください。
レスポンスを増分的にストリーミングする
ストリーミング出力の場合、同じメッセージ本文を含む POST リクエストを /v1/message:stream に送信します。
curl -N -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"A2A_ENDPOINT_URL/v1/message:stream" \
-d '{
"message": {
"role": "ROLE_USER",
"content": [
{
"text": "Say hello."
}
],
"messageId": "UNIQUE_UUID_STRING"
}
}'
このエンドポイントは、HTTP 経由でストリーミングされたチャンク オブジェクトの JSON 配列を返します。content[].text フラグメントが到着するたびに、順次追加します。ストリーミングされたチャンクにも metadata.sessionInfo と metadata.assistToken が含まれます。
ストリーミング ペイロードの仕様については、A2A message:stream REST API リファレンスをご覧ください。
Python を使用して A2A エンドポイントを呼び出す
この Python スクリプトは、Agent Registry で A2A エンドポイントを解決し、未加工の HTTP リクエストを使用してメッセージを送信します。
# Install dependencies: pip install google-auth requests
import uuid
import google.auth
from google.auth.transport.requests import AuthorizedSession
# TODO(developer): Replace placeholder values with your project ID and location.
project_id = "PROJECT_ID"
location = "LOCATION" # Registry location (for example: "us" or "eu")
target_display_name = "My Agent"
query_text = "What can you help me with?"
# Initialize credentials and authorized session
creds, _ = google.auth.default(
scopes=["https://www.googleapis.com/auth/cloud-platform"]
)
session = AuthorizedSession(creds)
# Step 1: Resolve the A2A endpoint URL from the Agent Registry
registry_url = (
f"https://agentregistry.googleapis.com/v1/"
f"projects/{project_id}/locations/{location}/agents"
)
response = session.get(registry_url)
response.raise_for_status()
agents = response.json().get("agents", [])
def get_a2a_url(agent_resource):
for proto in agent_resource.get("protocols") or []:
if proto.get("type") == "A2A_AGENT":
for iface in proto.get("interfaces", []):
if iface.get("protocolBinding") == "HTTP_JSON":
return iface.get("url")
return None
target_agent = next(
(a for a in agents if a.get("displayName") == target_display_name),
None
)
if not target_agent:
raise SystemExit(f"Agent '{target_display_name}' not found in registry.")
endpoint_url = get_a2a_url(target_agent)
if not endpoint_url:
raise SystemExit("Target agent does not publish an HTTP_JSON A2A endpoint.")
# Step 2: Fetch and verify the agent card
card_resp = session.get(f"{endpoint_url}/v1/card")
card_resp.raise_for_status()
card = card_resp.json()
print("Resolved Agent:", card.get("name"))
# Step 3: Send an A2A message
body = {
"message": {
"role": "ROLE_USER",
"content": [{"text": query_text}],
"messageId": str(uuid.uuid4()),
}
}
send_resp = session.post(f"{endpoint_url}/v1/message:send", json=body)
send_resp.raise_for_status()
reply_message = send_resp.json().get("message", {})
full_reply_text = "".join(
part.get("text", "") for part in reply_message.get("content", [])
)
print("Agent Reply:", full_reply_text)
ADK を使用してオーケストレーションを簡素化する
Agent Development Kit(ADK)は、レジストリ エンドポイントを自動的に解決し、リモート A2A エージェントをサブエージェントとしてラップします。
from google.adk.integrations.agent_registry import AgentRegistry
# Initialize registry client
registry = AgentRegistry(project_id="PROJECT_ID", location="LOCATION")
# Resolve remote A2A agent directly by resource name
remote_agent = registry.get_remote_a2a_agent(
agent_name="agents/AGENT_RESOURCE_ID"
)
その他の情報
A2A エンドポイントの動作は次のとおりです。
- 厳密なパス命名: HTTP+JSON バインディングでは
GET {url}/v1/card、POST {url}/v1/message:send、POST {url}/v1/message:streamのみがサポートされます。 - 厳密なスキーマ検証: プレーン
"user"をロールとして渡すと、HTTP400 Bad Requestエラーが返されます。列挙型文字列"ROLE_USER"を渡す必要があります。同様に、メッセージ テキストはpartsではなくcontent配列内に存在する必要があり、messageIdは厳密に必要です。 - 非 A2A エージェントの呼び出しエラー: エージェントのレジストリに
A2A_AGENTプロトコル エントリがない場合(特定の事前構築済みエージェントやマネージド エージェントなど)、そのプロキシ URL でgetCardを呼び出すと501 UNIMPLEMENTED(「... is not supported yet」)が返され、message:sendを呼び出すと400 INVALID_ARGUMENT(「Unsupported agent」)が返されます。 - URL 内のプロジェクト番号: レジストリは、プロジェクト ID ではなくプロジェクト番号を含む A2A URL を返します。HTTP リクエストを行う際は、この数値文字列を変更しないでください。
トラブルシューティング
次の表を使用して、一般的な A2A エンドポイント エラーのトラブルシューティングを行います。
| 症状 | 考えられる原因 | 解決策 |
|---|---|---|
getCard リクエストで HTTP 404 が返される |
間違ったパス エイリアス(/v1:getCard や /.well-known/agent-card.json など)を使用している。 |
GET リクエストは厳密に GET {url}/v1/card に送信します。 |
| HTTP 400 *「Unknown name 'parts'」* | 古い AI クライアントまたは生成 AI クライアントの本文形式を使用している。 | テキスト文字列は parts ではなく content の内側に配置します。 |
role の HTTP 400 無効な列挙値 |
小文字の "user" または "user_role" を渡す。 |
message.role を "ROLE_USER" に正確に設定します。 |
| HTTP 501 *"is not supported yet"* | A2A インターフェースを公開しないエージェントで getCard を呼び出す。 |
呼び出す前に、レジストリ リソースの protocols 配列を調べて A2A_AGENT のサポートを確認します。 |
| HTTP 400 *「Unsupported agent」(サポートされていないエージェント)* | A2A 以外のエージェントで message:send を呼び出す。 |
レジストリ定義にアクティブな A2A_AGENT プロトコル バインディングが含まれているエージェントを選択します。 |
HTTP 401 または HTTP 403 Permission Denied |
OAuth スコープがない、IAM ロールがない、割り当てプロジェクト ヘッダーがない。 | 呼び出し元の IAM ロール(agentregistry.viewer と assistants.assist)を確認し、cloud-platform スコープを検証します。ADC を使用している場合は -H "X-Goog-User-Project: PROJECT_ID" を渡します。 |
関連資料
- Agent Registry の概要
- Agent Registry でエージェントとツールを検索する
- エンドポイントを解決してオーケストレーターを構築する(ADK)
- A2A メッセージ:送信 REST API リファレンス