סוכני Agent2Agent (A2A) ב-Agent Registry מפרסמים ממשקי פרוטוקול שמכילים כתובת URL של נקודת קצה וקישור פרוטוקול (למשל HTTP_JSON). אתם יכולים למצוא את כתובת ה-URL של סוכן במאגר כדי להפעיל את שיטות ה-A2A שלו מלקוחות או מכלים מותאמים אישית לניהול תהליכים.
בקצרה
| מפרט | פרטים |
|---|---|
| Discovery API | agentregistry.googleapis.com (v1) |
| מארח של שרת proxy להפעלה | LOCATION-discoveryengine.googleapis.com |
| קישור לפרוטוקול | HTTP_JSON |
| מזהה פרויקט של כתובת URL | Google Cloud מספר הפרויקט (לא מזהה הפרויקט) |
| שיטות A2A נתמכות | GET /v1/card, POST /v1/message:send, POST /v1/message:stream |
| סכימת ההודעה הנדרשת | message.role = "ROLE_USER", content[].text, messageId ייחודי |
| הרשאות IAM נדרשות | roles/agentregistry.viewer (discovery) ו-discoveryengine.assistants.assist (invocation) |
לפני שמתחילים
- מפעילים את Agent Registry API (
agentregistry.googleapis.com) ואת Discovery Engine API (discoveryengine.googleapis.com) בפרויקט ב- Google Cloud . - אם הסוכן לא נוצר ישירות באפליקציית Gemini Enterprise, צריך לייבא אותו ממאגר הסוכנים ולתת למשתמשי הקצה גישה אליו. הוראות מפורטות מופיעות במאמר ייבוא סוכני A2A ממאגר הסוכנים.
- נותנים לחשבון המשתמש של מבצע הקריאה את ההרשאות המתאימות ב-IAM:
- כדי לקרוא את המרשם: צפייה במרשם הסוכנים (
roles/agentregistry.viewer). - כדי להפעיל את הנציג: עריכה ב-Discovery Engine (
roles/discoveryengine.editor) או תפקיד בהתאמה אישית שכולל אתdiscoveryengine.assistants.assist.
- כדי לקרוא את המרשם: צפייה במרשם הסוכנים (
- אם אתם מבצעים אימות באמצעות Application Default Credentials (ADC), אתם צריכים להגדיר את הלקוח כך שישלח את כותרת פרויקט המכסה:
-H "X-Goog-User-Project: PROJECT_ID". - אופציונלי: אם אתם מתכננים לעטוף סוכנים מרוחקים כסוכני משנה פרוגרמטיים, אתם יכולים להתקין את ספריית הערכה לפיתוח סוכנים (ADK):
pip install "google-adk[a2a]>=1.29.0".
שלב 1: מאתרים את הסוכן ואת נקודת הקצה שלו מסוג A2A
כדי להפעיל סוכן A2A, קודם צריך למצוא את url שפורסם במאגר הסוכנים. מפרטים את הסוכנים במיקום הרישום (למשל us או eu, שמועברים כפרמטר של הנתיב במארח הגלובלי agentregistry.googleapis.com):
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"
אפשר גם לחפש נציג לפי הקידומת של השם המוצג באמצעות ה-CLI של Google Cloud :
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"
}
]
}
]
}
לסכימת משאבי הסוכן המלאה, אפשר לעיין במאמרי העזרה של ה-API בארכיטקטורת REST projects.locations.agents.
שלב 2: מאחזרים את כרטיס הנציג
בכרטיס הסוכן מופיעים מטא-נתונים שמתארים את הזהות, התיאור והיכולות של הסוכן בנוגע לקלט ולפלט. כדי לאחזר את הכרטיס, שולחים בקשת HTTP GET לנתיב /v1/card שמצורף לכתובת ה-URL של נקודת הקצה של הנציג:
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"A2A_ENDPOINT_URL/v1/card"
דוגמה למטען ייעודי (payload) של תגובה:
{
"name": "My Agent",
"description": "What the agent does.",
"url": "A2A_ENDPOINT_URL",
"capabilities": {},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"preferredTransport": "HTTP+JSON"
}
שלב 3: שולחים הודעה
כדי לשלוח שאילתת משתמש לסוכן, שולחים בקשת POST אל /v1/message:send. גוף הבקשה צריך להיות בהתאם לסכימת ההודעות A2A, ולכלול את הערך ROLE_USER בשדה role, מערך 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"
}
}'
במטען הייעודי (payload) של התגובה, התשובה של הנציג מוחזרת בתוך האובייקט 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 בבקשה הבאה.
אפשר לעיין במאמרי העזרה של API בארכיטקטורת REST של message:send A2A כדי לראות את הסכימה המלאה של תוכן ההודעה.
הצגת התשובות באופן שוטף
כדי לקבל פלט בסטרימינג, שולחים בקשת 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"
}
}'
נקודת הקצה מחזירה מערך JSON של אובייקטים של נתחים שמוזרמים דרך HTTP. מצרפים את חלקי content[].text ברצף כשהם מגיעים. החלקים שמועברים בסטרימינג מכילים גם את metadata.sessionInfo ו-metadata.assistToken.
מידע על מפרט המטען הייעודי (payload) של הסטרימינג זמין במאמר A2A message:stream REST API reference.
קריאה לנקודת קצה (endpoint) של A2A באמצעות Python
סקריפט Python הזה מפענח נקודת קצה של A2A ב-Agent Registry ושולח הודעה באמצעות בקשות 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
הערכה לפיתוח סוכנים (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"
)
הערות נוספות
לנקודות קצה (endpoints) של A2A יש את ההתנהגויות הבאות:
- מתן שמות קפדני לנתיבים: רק
GET {url}/v1/card,POST {url}/v1/message:sendו-POST {url}/v1/message:streamנתמכים בקישורי HTTP+JSON. - אימות סכמה מחמיר: העברת
"user"רגיל בתור התפקיד מחזירה שגיאת HTTP400 Bad Request. צריך להעביר את מחרוזת ה-enum"ROLE_USER". באופן דומה, הטקסט של ההודעה צריך להיות במערךcontentולא ב-parts, וחובה להשתמש ב-messageId. - שגיאה בהפעלת סוכן שאינו סוכן A2A: אם לסוכן אין רשומת פרוטוקול
A2A_AGENTבמרשם (כמו סוכנים מסוימים שנוצרו מראש או מנוהלים), קריאה ל-getCardבכתובת ה-URL של שרת ה-Proxy שלו מחזירה את הערך501 UNIMPLEMENTED("... is not supported yet"), וקריאה ל-message:sendמחזירה את הערך400 INVALID_ARGUMENT("Unsupported agent"). - מספר הפרויקט בכתובת ה-URL: המאגר מחזיר כתובת URL של A2A שמכילה את מספר הפרויקט ולא את מזהה הפרויקט. אל תשנו את המחרוזת המספרית הזו כשאתם שולחים בקשות HTTP.
פתרון בעיות
אתם יכולים להיעזר בטבלה הבאה כדי לפתור שגיאות נפוצות בנקודות קצה של A2A:
| תיאור הבעיה | סיבה אפשרית | רזולוציה |
|---|---|---|
שגיאת HTTP 404 בבקשה getCard |
שימוש בכינוי נתיב שגוי (כמו /v1:getCard או /.well-known/agent-card.json). |
שולחים את בקשת ה-GET רק אל GET {url}/v1/card. |
| HTTP 400 *"Unknown name 'parts'"* | שימוש בפורמט ישן או בפורמט של גוף לקוח שנוצר על ידי AI גנרטיבי. | מחרוזות הטקסט צריכות להיות בתוך content ולא בתוך parts. |
HTTP 400 ערך enum לא תקין עבור role |
העברת "user" או "user_role" באותיות קטנות. |
מגדירים את message.role בדיוק לערך "ROLE_USER". |
| HTTP 501 *"is not supported yet"* | מתקשרים אל getCard לסוכן שלא מפרסם ממשק A2A. |
לפני ששולחים קריאה, בודקים את המערך protocols של משאב המרשם כדי לוודא שיש תמיכה ב-A2A_AGENT. |
| HTTP 400 *"Unsupported agent"* | מתקשרים אל message:send באמצעות סוכן שאינו סוכן A2A. |
בוחרים סוכן שהגדרת הרישום שלו כוללת קישור לפרוטוקול A2A_AGENT פעיל. |
HTTP 401 או HTTP 403 Permission Denied |
חסרים היקפי הרשאות של OAuth, חסרים תפקידי IAM או חסרה כותרת של פרויקט מכסות. | בודקים את התפקידים ב-IAM של המתקשר (agentregistry.viewer ו-assistants.assist), מאמתים את ההיקף של cloud-platform ומעבירים את -H "X-Goog-User-Project: PROJECT_ID" אם משתמשים ב-ADC. |
מקורות מידע שקשורים לנושא
- סקירה כללית על Agent Registry
- חיפוש סוכנים וכלים ב-Agent Registry
- פתרון נקודות קצה ובניית תזמורים (ADK)
- הפניה ל-REST API של A2A message:send