레지스트리 A2A 엔드포인트를 사용하여 에이전트 호출

Agent Registry의 Agent2Agent (A2A) 에이전트는 엔드포인트 URL과 프로토콜 바인딩 (예: HTTP_JSON)이 포함된 프로토콜 인터페이스를 알립니다. 레지스트리에서 에이전트의 URL을 검색하여 커스텀 오케스트레이터 또는 클라이언트에서 A2A 메서드를 호출할 수 있습니다.

요약 정보

사양 세부정보
Discovery API agentregistry.googleapis.com (v1)
호출 프록시 호스트 LOCATION-discoveryengine.googleapis.com
프로토콜 바인딩 HTTP_JSON
URL 프로젝트 식별자 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 (호출)

시작하기 전에

  1. your Google Cloud project에서 Agent Registry API (agentregistry.googleapis.com) 및 Discovery Engine API (discoveryengine.googleapis.com)를 사용 설정합니다.
  2. Gemini Enterprise 앱에서 직접 에이전트를 만들지 않은 경우 Agent Registry에서 에이전트를 가져오고 최종 사용자에게 액세스 권한을 부여합니다. 자세한 내용은 Agent Registry에서 A2A 에이전트 가져오기를 참고하세요.
  3. 호출자 주 구성원에게 적절한 IAM 권한을 부여합니다.
    • 레지스트리 읽기: Agent Registry 뷰어 (roles/agentregistry.viewer)
    • 에이전트 호출: Discovery Engine 편집자 (roles/discoveryengine.editor) 또는 discoveryengine.assistants.assist가 포함된 커스텀 역할
  4. 애플리케이션 기본 사용자 인증 정보 (ADC)를 사용하여 인증하는 경우 할당량 프로젝트 헤더를 전송하도록 클라이언트를 구성합니다. -H "X-Goog-User-Project: PROJECT_ID".
  5. 원격 에이전트를 프로그래매틱 하위 에이전트로 래핑하려는 경우 선택적으로 에이전트 개발 키트(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"

CLI를 사용하여 표시 이름 프리픽스로 에이전트를 검색할 수도 있습니다: Google Cloud

gcloud agent-registry agents search \
  --project=PROJECT_ID \
  --location=LOCATION \
  --search-string="displayName:My_Agent_*"

반환된 에이전트 리소스에서 protocols 배열을 검사합니다. typeA2A_AGENT와 같고 interfaces[].protocolBindingHTTP_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 요청을 합니다. 요청 본문은 ROLE_USER로 설정된 role, 텍스트 부분이 포함된 content 배열, 고유하게 생성된 messageId가 필요한 A2A 메시지 스키마를 준수해야 합니다.

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 참조를 확인하세요.

응답을 점진적으로 스트리밍

출력을 스트리밍하려면 동일한 메시지 본문으로 /v1/message:stream에 POST 요청을 전송합니다.

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.sessionInfometadata.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를 사용하여 오케스트레이션 간소화

에이전트 개발 키트 (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"를 역할로 전달하면 HTTP 400 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 엔드포인트 오류를 해결하세요.

증상 가능한 원인 해결 방법
요청에 대한 HTTP 404getCard 잘못된 경로 별칭 (예: /v1:getCard 또는 /.well-known/agent-card.json)을 사용합니다. GET 요청을 GET {url}/v1/card로 엄격하게 전송합니다.
HTTP 400 *"Unknown name 'parts'"* 이전 또는 생성형 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.viewerassistants.assist)을 확인하고 cloud-platform 범위를 확인하며 ADC를 사용하는 경우 -H "X-Goog-User-Project: PROJECT_ID"를 전달합니다.