Os agentes Agent2Agent (A2A) no Agent Registry anunciam interfaces de protocolo que contêm um URL de endpoint e uma vinculação de protocolo (como HTTP_JSON). É possível descobrir o URL de um agente no registro para chamar os métodos A2A dele em orquestradores ou clientes personalizados.
Resumo
| Especificação | Detalhes |
|---|---|
| API Discovery | agentregistry.googleapis.com (v1) |
| Host de proxy de invocação | LOCATION-discoveryengine.googleapis.com |
| Vinculação de protocolo | HTTP_JSON |
| Identificador do projeto de URL | Google Cloud número do projeto (não o ID do projeto) |
| Métodos A2A compatíveis | GET /v1/card, POST /v1/message:send, POST /v1/message:stream |
| Esquema de mensagem obrigatório | message.role = "ROLE_USER", content[].text, messageId exclusivo |
| Permissões do IAM obrigatórias | roles/agentregistry.viewer (descoberta) e discoveryengine.assistants.assist (invocação) |
Antes de começar
- Ative a API Agent Registry (
agentregistry.googleapis.com) e a API Discovery Engine (discoveryengine.googleapis.com) no seu Google Cloud projeto. - Se o agente não foi criado diretamente no app Gemini Enterprise, importe-o do Agent Registry e conceda acesso a ele aos usuários finais. Para instruções, consulte Importar agentes A2A do Agent Registry.
- Conceda ao principal do autor da chamada as permissões do IAM adequadas:
- Para ler o registro: leitor do Agent Registry (
roles/agentregistry.viewer). - Para invocar o agente: editor do Discovery Engine (
roles/discoveryengine.editor) ou um papel personalizado que incluadiscoveryengine.assistants.assist.
- Para ler o registro: leitor do Agent Registry (
- Se você fizer a autenticação usando as Application Default Credentials (ADC), configure o cliente para enviar o cabeçalho do projeto de cota:
-H "X-Goog-User-Project: PROJECT_ID". - Opcionalmente, instale a biblioteca do Kit de Desenvolvimento de Agente (ADK) se você planeja encapsular agentes remotos como subagentes programáticos:
pip install "google-adk[a2a]>=1.29.0".
Etapa 1: descobrir o agente e o endpoint A2A dele
Para invocar um agente A2A, primeiro descubra o url anunciado no Agent Registry. Liste os agentes no local do registro (como us ou eu, transmitido como um parâmetro de caminho no host global 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"
Também é possível pesquisar um agente pelo prefixo do nome de exibição usando a Google Cloud CLI:
gcloud agent-registry agents search \
--project=PROJECT_ID \
--location=LOCATION \
--search-string="displayName:My_Agent_*"
No recurso do agente retornado, inspecione a matriz protocols. Localize a entrada em que type é igual a A2A_AGENT e interfaces[].protocolBinding é igual a HTTP_JSON. Extraia o url correspondente:
{
"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"
}
]
}
]
}
Consulte a referência da API REST projects.locations.agents para o esquema completo de recursos do agente.
Etapa 2: buscar o card do agente
O card do agente fornece metadados que descrevem a identidade, a descrição e os recursos de entrada/saída do agente. Para recuperar o card, envie uma solicitação GET HTTP para o caminho /v1/card anexado ao URL do endpoint A2A do agente:
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"A2A_ENDPOINT_URL/v1/card"
Exemplo de payload de resposta:
{
"name": "My Agent",
"description": "What the agent does.",
"url": "A2A_ENDPOINT_URL",
"capabilities": {},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"preferredTransport": "HTTP+JSON"
}
Etapa 3: enviar uma mensagem
Para enviar uma consulta do usuário ao agente, faça uma solicitação POST para /v1/message:send. O corpo da solicitação precisa estar em conformidade com o esquema de mensagens A2A, exigindo que role seja definido como ROLE_USER, uma matriz content que contenha partes de texto e um messageId gerado de maneira exclusiva:
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"
}
}'
No payload de resposta, a resposta do agente é retornada no objeto 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..."
}
]
}
}
Concatene as strings de texto dentro de content[].text para mostrar a resposta completa. Para continuar a conversa na mesma sessão, salve a string contextId retornada e forneça-a como message.contextId na próxima solicitação.
Consulte a referência da API REST A2A message:send para o esquema completo de payload de mensagens.
Respostas de stream de forma incremental
Para saída de streaming, envie uma solicitação POST com um corpo da mensagem idêntico para /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"
}
}'
O endpoint retorna uma matriz JSON de objetos de blocos transmitidos por HTTP. Anexe os fragmentos content[].text sequencialmente à medida que chegam. Os blocos transmitidos também contêm metadata.sessionInfo e metadata.assistToken.
Consulte a referência da API REST A2A message:stream para a especificação de payload de streaming.
Chamar um endpoint A2A usando Python
Esse script Python resolve um endpoint A2A no Agent Registry e envia uma mensagem usando solicitações HTTP brutas:
# 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)
Simplificar a orquestração usando o ADK
O Kit de Desenvolvimento de Agente (ADK) resolve endpoints de registro automaticamente e encapsula agentes A2A remotos como subagentes:
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"
)
Outras observações
Os endpoints A2A têm os seguintes comportamentos:
- Nomenclatura de caminho estrita: apenas
GET {url}/v1/card,POST {url}/v1/message:sendePOST {url}/v1/message:streamsão compatíveis com vinculações HTTP+JSON. - Validação de esquema estrita: transmitir simples
"user"como o papel retorna um erro HTTP400 Bad Requesterror. É necessário transmitir a string de enumeração"ROLE_USER". Da mesma forma, o texto da mensagem precisa residir na matrizcontentem vez departs, emessageIdé estritamente obrigatório. - Erro de invocação de agente não A2A: se um agente não tiver uma entrada de protocolo
A2A_AGENTno registro (como alguns agentes pré-criados ou gerenciados), chamargetCardno URL do proxy retornará501 UNIMPLEMENTED("... ainda não é compatível"), e chamarmessage:sendretornará400 INVALID_ARGUMENT("Agente não compatível"). - Número do projeto no URL: o registro retorna um URL A2A que contém o número do projeto em vez do ID do projeto. Não altere essa string numérica ao fazer solicitações HTTP.
Solução de problemas
Use a tabela a seguir para resolver problemas comuns de endpoints A2A:
| Sintoma | Causa provável | Resolução |
|---|---|---|
HTTP 404 na solicitação getCard |
Usar um alias de caminho incorreto (como /v1:getCard ou /.well-known/agent-card.json). |
Envie a solicitação GET estritamente para GET {url}/v1/card. |
| HTTP 400 *"Nome desconhecido 'parts'"* | Usar formatação de corpo do cliente de IA generativa ou antiga. | Coloque strings de texto dentro de content, não parts. |
HTTP 400 valor de enumeração inválido para role |
Transmitir "user" ou "user_role" em letras minúsculas. |
Defina message.role exatamente como "ROLE_USER". |
| HTTP 501 *"indisponível"* | Chamar getCard em um agente que não publica uma interface A2A. |
Inspecione a matriz protocols do recurso de registro para confirmar o suporte A2A_AGENT antes de chamar. |
| HTTP 400 *"Agente não compatível"* | Chamar message:send em um agente não A2A. |
Escolha um agente cuja definição de registro inclua uma vinculação de protocolo A2A_AGENT ativa. |
HTTP 401 ou HTTP 403 Permission Denied |
Escopos OAuth ausentes, papéis do IAM ausentes ou cabeçalho do projeto de cota ausente. | Verifique os papéis do IAM do autor da chamada (agentregistry.viewer e assistants.assist); verifique o escopo cloud-platform; transmita -H "X-Goog-User-Project: PROJECT_ID" se estiver usando o ADC. |