Ghosty
Blog

A2A v1.0 — lo que aprendimos implementando un estándar que casi nadie implementa

Implementamos Agent2Agent de punta a punta en producción. El AgentCard que publicábamos estaba inválido y no lo sabíamos, el material de estudio enseña una versión muerta, y de 20,185 hosts sondeados sólo diez pasan la validación. Crónica honesta de lo que sí sirve y lo que no.

9 min de lecturaFixter
  • agentes
  • A2A
  • protocolos
  • interoperabilidad
  • Ghosty Teams
Pintura de una ciudad antigua monumental en ruinas, con columnatas y escalinatas enormes vacías bajo un cielo tormentoso
Ruins of an Ancient City, John Martin, c. 1810–20 — Cleveland Museum of Art (CC0)

Nuestro AgentCard estuvo inválido en producción durante semanas y no teníamos forma de saberlo. Se servía con 200, tenía el JSON bien formado, los campos que pide la documentación, y cualquier cliente casero lo leía sin quejarse. El día que lo pasamos por el SDK oficial de Python —cuyos tipos son literalmente el protobuf generado de la spec— lo rechazó de dos maneras distintas.

Esa tarde entendimos algo sobre A2A que ningún tutorial dice.

Primero: el material que hay enseña un dialecto muerto

A2A —Agent2Agent, el protocolo para que agentes de distintos proveedores se hablen entre sí— llegó a v1.0 en abril de 2026 bajo la Linux Foundation. La v1.0 rompió con la 0.3 en casi todo lo que se toca al escribir un cliente:

Conceptov0.3v1.0
Métodosmessage/sendSendMessage (PascalCase)
Endpoint del agenteurl en la raíz del cardsupportedInterfaces[]
Discriminador de tiposkindya no existe
Partes de un mensajeobjetos tipadosoneof aplanado {text|raw|url|data}
Estados de tareasubmitted, workingTASK_STATE_SUBMITTED, …
Eventos de streamtraen finalya no lo traen
Ruta del card/.well-known/agent.json/.well-known/agent-card.json

Ahora la parte incómoda. El curso de A2A de DeepLearning.AI —hecho con Google Cloud e IBM— es de enero de 2026. Es anterior al release de v1.0. Los codelabs de Google, casi todos, igual. Lo de Udemy, igual. Quien estudie hoy con el material que sale primero en cualquier búsqueda va a escribir un cliente que no habla con nada.

No es un detalle de purista: un SendMessage contra un servidor que espera message/send no degrada, no negocia, no avisa. Simplemente no existe.

Segundo: el .proto manda sobre la documentación, y la documentación no lo sabe

La spec dice en su §1.4 que specification/a2a.proto es "the single authoritative normative definition". Es una frase que uno lee como formalidad legal y sigue adelante. Es literal, y sus propios ejemplos la contradicen.

Los dos rechazos que nos comió el validador:

jsonc
// Lo que muestra el ejemplo de la §8.5 — estilo OpenAPI, se ve razonable:{  "security": [ { "oauth2": ["agent:read"] } ]}
// Lo que dice el proto. SecurityRequirement no es un mapa de esquema→scopes:// es un mensaje con un campo `schemes` que mapea string → StringList.{  "securitySchemes": { "oauth2": { "oauth2": { /* … */ } } },  "securityRequirements": [    { "schemes": { "oauth2": { "list": ["agent:read"] } } }  ]}

Dos cosas pasan aquí. La primera es que la forma del ejemplo está mal, y es la forma que uno escribiría de memoria porque es la de OpenAPI. La segunda duele más: el alias security no existe en el proto. Emitirlo no es un campo de más que un parser ignora — un parser estricto rechaza el card entero por campo desconocido. Un campo que salió de la documentación oficial invalidaba todo el documento.

La lección práctica cabe en una línea: si vas a implementar A2A, tu prueba de humo no es "mi card carga en el navegador", es "el SDK oficial parsea mi card". Nosotros usamos el de Python, 1.1.2, porque sus tipos vienen del protobuf y no de la prosa.

Tercero: ¿cuánta gente está del otro lado?

Aquí es donde la investigación dejó de ser técnica. Un audit de API Evangelist del 29 de julio de 2026 sondeó 20,185 hosts buscando agent cards.

20,185 hosts sondeados     └── 65 sirven un agent card              (0.32%)           └── 10 pasan validación de v1.0    (0.05%)           └── 15 siguen en /.well-known/agent.json  (path de 0.3)

Diez. En todo el sondeo. Y hay un detalle que resume el estado del ecosistema mejor que cualquier gráfica: a2a-registry.org publica un card que declara protocolVersion: 1.0 y tiene url en la raíz. Es decir, un card 0.3 diciendo que es 1.0. El registro central del protocolo no pasa su propia validación.

Contra el otro estándar de la casa, medido con la API de GitHub y la de npm en agosto de 2026:

Estrellas en el repo de la specDescargas/mes del SDK
A2A25,4026.8 M (@a2a-js/sdk)
MCP8,991196 M

Casi tres veces más estrellas y veintiocho veces menos uso. Eso no es una métrica de adopción, es una métrica de interés.

Cuarto: lo que dice la gente que sí lo probó

El documento más útil que encontramos no fue un post de ingeniería sino un . Hay quien lo corre en producción y lo describe bien —"es como microservicios para agentes"—, pero las dos frases que se repiten en el hilo son:

"Lo probamos y nos quedamos con patrones agent-behind-MCP."

"Nos dimos cuenta de que no necesitábamos un agente del otro lado."

Nadie está enojado con A2A. El sentimiento dominante en ese hilo no es hostilidad: es indiferencia, que es un problema bastante peor para un estándar cuyo valor entero depende de que haya alguien a quien llamar.

Lo comprobamos por otro lado: ningún agente de código publica un AgentCard. Ni Codex, ni opencode, ni Roo Code —estos dos con issues abiertas pidiéndolo—, ni siquiera Goose, que vive en la misma fundación que A2A e implementó ACP en su lugar. Ese mundo entero eligió MCP para herramientas y ACP para editores.

Lo que hicimos con ese hueco

Un hueco documentado es una invitación. Publicamos (MIT): el agente de código en Rust —binario estático de 4.29 MiB— con AgentCard propio y A2A v1.0 completo.

No lo forkeamos, y la razón es interesante. noob tiene en su CI un tope duro de 8 MiB de binario y 45 crates, y renuncia al runtime async a propósito. Meterle un servidor HTTP con streaming habría violado las tres cosas. Entonces el agente expone un modo serve que habla frames JSON por línea sobre un contrato versionado, y un sidecar traduce.

  cliente A2A            sidecar (Node)              noob serve (Rust)  ───────────            ──────────────              ─────────────────  SendMessage    ──────► spawn / stdin      ──────►  {"t":"text.delta"}                         traduce frames     ◄──────  {"t":"tool.start"}  TaskArtifact   ◄──────                             {"t":"ask"}  UpdateEvent                                        {"t":"turn.end"}

Y el mapeo salió casi identidad, que es la mejor señal de que un protocolo está bien diseñado:

Frame de noobEvento A2A
text.deltaartifactUpdate con append
tool.start / tool.endstatusUpdate con DataPart
prompt.queuees el STEER de A2A
askTASK_STATE_INPUT_REQUIRED

Esos dos últimos merecen una nota. STEER —inyectar contexto en un turno vivo— es de esas cosas de la spec que uno lee y piensa "¿quién necesita esto?", hasta que ya tenías exactamente esa primitiva con otro nombre. Y ask es el único caso real de INPUT_REQUIRED que hemos visto en la práctica: el agente bloquea el turno esperando un sí o un no. Todo lo demás que se documenta como input-required suele ser en realidad una tarea nueva.

La trampa que costó dos bugs

Al reabrir una sesión, noob serve reproduce todos los frames previos. Nuestro primer intento fue tragar el replay hasta el primer turn.start. No funciona: ese turn.start es el del turno viejo, así que el cliente veía la conversación entera repetida en cada mensaje.

El segundo intento fue un reloj de silencio —cuando dejen de llegar frames por un rato, el replay terminó— arrancado en el spawn. Tampoco: el proceso tarda unos 100 ms en levantar, y para cuando el reloj empieza a contar, el replay ya se coló.

Lo que sí funciona es de una obviedad que sólo llega después: el reloj lo arranca el primer frame, no el spawn.

Cinco bugs que sólo aparecen cuando despliegas de verdad

Nuestros agentes corren en microVMs Firecracker aisladas, y ahí el protocolo dejó de ser el problema:

  1. Alpine no arrancaba. El horneado de la imagen declara units de systemd; en Alpine /sbin/init es busybox y no sabe nada de units.
  2. El unit no se declaraba con CMD sino con un runtime.yaml — que es exactamente el tipo de cosa que no aparece en ningún error, sólo en un silencio.
  3. spawn('noob') daba ENOENT. El PATH de systemd no incluye /usr/local/bin.
  4. systemd no hereda los ENV del Dockerfile, así que el sidecar caía a un workspace inexistente. Y aquí está la trampa cruel de Node: spawn con un cwd que no existe reporta ENOENT señalando al binario, no al directorio. Se pierde un buen rato diagnosticando la pieza equivocada.
  5. Un fallo de spawn sin manejar el evento 'error' es excepción no capturada en Node, y tumbaba todas las sesiones del proceso, no sólo la que falló.

Ninguno de los cinco es culpa de A2A. Todos son el costo real de "implementamos el protocolo", y ninguno sale en la spec.

El veredicto honesto

A2A no fue un error. Es un estándar de la Linux Foundation con AWS, Microsoft, Google, Salesforce y SAP en el comité técnico; es una casilla que abre conversaciones empresariales que sin ella no se abren; costó días, no meses; y no excluye nada —MCP sigue, nuestros formatos propios siguen.

Tampoco es un motor de crecimiento, y decirlo importa. El riesgo real no es que A2A falle: es que se quede donde están esos estándares que todos "soportan" en la nota de prensa mientras la integración de verdad sigue siendo a medida, caso por caso.

Hay un antecedente que se parece demasiado. UDDI proponía directorios centrales de servicios descritos en un formato común para que los sistemas se descubrieran solos. Agent cards firmadas más registros centrales es, estructuralmente, lo mismo. UDDI murió por falta de servicios que registrar — que es exactamente lo que dice el sondeo de los 20,185 hosts.

Nosotros apostamos a que el hueco se llena por abajo, con implementaciones que funcionen de verdad, no con anuncios. Por eso noob-a2a es MIT y por eso Ghosty Teams ya consume cards de terceros: si vas a publicar uno, ya tienes con quién probarlo.


Parte 2: ACP, el otro protocolo — el que sí eligieron los agentes de código. La comparación de primera mano da un resultado distinto, y esa es una historia con menos ruinas.

Pruébalo gratis hoy

Sin código. Sin complicaciones. Crea tu agente y ponlo a trabajar en minutos.

Ghosty ® 2026. Todos los derechos reservados.