Guía10 min

Consumir agentes externos con A2A: comprar, no criar

Resumen

Criar un segundo agente no es lo mismo que comprar uno. A2A (Linux Foundation) es el contrato agent-to-agent: Agent Card en /.well-known/agent-card.json, SendMessage/GetTask/CancelTask, estados SUBMITTED→WORKING→COMPLETED. Filtro build-vs-buy, wrapper tipado y evals como si el remoto fuera un proveedor. Distinto de orquestar los tuyos y de MCP.

MCPGemini
Cliente A2A hablando con un agente remoto opaco a través de un Agent Card, sin compartir tools ni memoria

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

Orquestar es criar: tú pones el supervisor, los especialistas y el presupuesto de tokens. Esta guía es comprar: un agente de otro vendor (o de otro equipo) expone un endpoint A2A y tú lo consumes como proveedor. No heredas su prompt, sus tools ni su memoria. Heredas un contrato: Agent Card, tareas con ciclo de vida y un wrapper que valida, recorta y evalúa.

A2A nació en Google y vive en la Linux Foundation. La spec (verificada 2026-09-06) lo dice sin rodeos: agentes opacos. MCP equipa a un agente con tools; A2A deja que dos agentes colaboren sin mezclar contextos. No es MCP y no es envolver tu API como tools.

Contrato: si no hay Agent Card, no hay proveedor. Si no hay wrapper tipado, no hay cliente. Si no hay eval contra el remoto, no hay compra: hay fe.

Una línea

Descubre el Card, autentica, envía una Task, espera un estado terminal, recorta el Artifact. Cero tools del proveedor en tu prompt.

Build vs buy (filtro de 7 minutos)

SeñalCría (tuyos)Compra (A2A)
El especialista cambia cada sprintUn subagente en tu repoNo: el Card se mueve sin tu deploy
El vendor ya resuelve el dominio (KYC, nómina, legal)Reinventar es caroConsume el Card y evalúa SLA
Necesitas su memoria o su toolsetNo es A2A: es integración íntimaRechaza; A2A es opaco a propósito
Latencia p95 > 8 s mata el webhookUn tool localSolo si el Card declara streaming o tú haces async
El fallo del remoto no puede tumbar tu botCircuito internoBreaker por dependencia
Quieres “un segundo cerebro” por modaOrquestación dice que noTampoco: compra un skill, no un alma

Si la fila ganadora es “cría”, cierra esta pestaña. A2A no sustituye a un buen tool.

El Card es el contrato, no el README

El servidor MUST publicar un Agent Card. El path canónico (spec §8 + discovery, RFC 8615) es:

GET /.well-known/agent-card.json HTTP/1.1
Host: agente.proveedor.example

El JSON declara identidad, skills, endpoint, capabilities (streaming, pushNotifications, extendedAgentCard) y securitySchemes. Tres estrategias de discovery: well-known, registro curado, o URL pegada a mano. Para un SaaS, well-known o URL fija. No scrapees un marketing site.

Reglas del cliente:

  1. Cachea el Card con TTL corto (minutos, no días). Un skill que desaparece es un 400, no un alucinación.
  2. Si extendedAgentCard: true, pide GetExtendedAgentCard después de autenticar. La spec: el Card público puede ocultar skills.
  3. Si streaming es false, no llames SendStreamingMessage. El servidor MUST devolver UnsupportedOperationError.
  4. Verifica firma JWS si el Card trae signatures (RFC 7515). Un Card sin autenticar es un menú, no un pasaporte.

Auth vive en securitySchemes, no en el prompt. Si el remoto pide OAuth del usuario, eso es consentimiento, no un header inventado.

Operaciones que tu wrapper sí conoce

La spec separa operaciones abstractas de bindings (JSON-RPC 2.0, gRPC, HTTP/REST). El cliente mínimo no habla “el protocolo entero”: habla cuatro verbos.

OperaciónPara quéQué no hagas
SendMessageCrear o continuar una TaskMeter el system prompt del proveedor
GetTaskPoll del estadoParsear HTML de un dashboard
CancelTaskAbortar; es idempotenteReintentar cancel contra un terminal
SendStreamingMessageSSE/chunks si capabilities.streamingAsumir que todos lo soportan

Estados de TaskState (spec §4.1.3) que el wrapper traduce a tu dominio:

EstadoQué significa para ti
SUBMITTED / WORKINGSigue vivo. No dispares un segundo Send
COMPLETEDLee Artifacts. Recorta. Guarda el task_id
FAILED / REJECTEDError de proveedor. No reintentes a ciegas
CANCELEDTerminal. Un segundo Cancel MAY ser TaskNotFoundError
INPUT_REQUIREDEl remoto te pide más. Eso es HITL del otro, no el tuyo
AUTH_REQUIREDCredencial, no otro prompt. Interrumpe, no inventes

return_immediately en SendMessageConfiguration decide si bloqueas o contestas el webhook y sigues por push/poll. Un bot de Telegram no espera 40 s: envía, guarda task_id, contesta “en proceso”.

Flujo cliente A2A: Card, auth, SendMessage y estados de Task

Wrapper tipado: el modelo no es el cliente A2A

El LLM no debe ver JSON-RPC crudo. Expón una o dos tools de intención (consultar_kyc, pedir_dictamen_legal) cuyo adapter:

  1. Resuelve el Card (cache).
  2. Inyecta auth fuera del contexto.
  3. Arma un Message con Parts de texto o data — no un dump de tu historial.
  4. Espera un estado terminal o se suscribe si hay streaming.
  5. Devuelve un recorte: status, artifact_preview, task_id. Presupuesto duro. Tijera muda prohibida: marca truncated.

Idempotencia: el task_id es la clave. Un retry de red no es un segundo trabajo. Si el proveedor no es idempotente, guardas el mapa intent_hash → task_id.

Timeouts: AbortSignal en el HTTP del adapter, no setTimeout decorativo. Si el remoto se pone Open, el breaker corta esa dependencia. Tu bot sigue vivo.

Evalúa al proveedor como evalúas una tool

Comprar sin eval es un vendor lock emocional. Trata el remoto como caja negra:

  • Golden set de 20–50 casos: input canónico → Artifact esperado (schema, no prosa).
  • Contrato de Card: si un skill desaparece o securitySchemes cambia, el CI falla antes de producción.
  • SLA: p95, tasa FAILED/REJECTED, tiempo en WORKING. Eso entra a evals, no a un dashboard de marketing.
  • Canary: 5 % del tráfico real con comparación humana semanal. Kappa, no “se siente bien”.

Si el proveedor no te deja un sandbox A2A, no lo compras. Un PDF de “enterprise ready” no es un Card.

Checklist de compra

  • Card en well-known o URL fija; TTL de cache documentado.
  • securitySchemes reales; token fuera del prompt.
  • Wrapper con 1–2 tools de intención; el modelo no habla JSON-RPC.
  • Mapeo explícito de TaskState → tu dominio (incluido AUTH_REQUIRED).
  • CancelTask cableado; no dejes WORKING eternos.
  • Breaker por este proveedor; kill switch aparte.
  • Golden set + alerta si el Card cambia skills.
  • Recorte de Artifacts; PII del remoto no se loguea cruda.
  • Distinción escrita: MCP = tools propias; A2A = agente ajeno.

Contrato A2A: Agent Card, securitySchemes y skills como frontera

Errores que ya vimos

Pegar el Card entero al system prompt. El Card es para el adapter. El modelo necesita el nombre del skill y dos frases de cuándo usarlo.

Tratar A2A como MCP. MCP te da tools/list. A2A te da un agente que piensa. Si lo que quieres es create_invoice, envuelve la API; no pagues un LLM remoto.

Poll infinito en WORKING. Sin techo (N intentos o wall clock) el webhook ya contestó 200 y tú sigues gastando. Cancela y marca fallo.

Reusar task_id de otro tenant. El contexto A2A agrupa tasks. Tu clave es tenant_id + task_id, siempre.

FAQ

¿A2A reemplaza a LangGraph o CrewAI? No. La spec: A2A no es un ADK. Es el cable entre agentes ya construidos.

¿JSON-RPC es obligatorio? No. La spec tiene bindings JSON-RPC, gRPC y HTTP/REST. El Card declara lo que habla el servidor. Tu wrapper habla uno.

¿Puedo exponer mi agente por A2A y a la vez consumir otro? Sí. Entonces eres servidor y cliente. Dos Cards, dos breakers. No mezcles los task_id.

¿Y si el remoto pide input a mitad? INPUT_REQUIRED no es tu HITL interno. Tradúcelo a una pregunta al usuario o rechaza el skill: no dejes al modelo “adivinar el dato que el otro agente quiere”.

Siguiente paso: el curso para el loop local; esta guía solo cuando el especialista no vive en tu repo. Hub: construir agentes.