IAProtocolo A2A: cómo diseñar un agente al que llaman otros agentes
A2A v1.0 salió en marzo de 2026. Seis pasos para diseñar un servidor A2A: Agent Card, skills por resultado, ocho estados de tarea, bindings, auth y versiones.

Al terminar esta guía tendrás el diseño de un servidor A2A para un agente que ya tienes en producción: una Agent Card publicada, skills entre las que el modelo de otro agente sabe elegir, un ciclo de vida de tareas alineado con los estados de tus trabajos, un canal de actualizaciones que encaja con tu infraestructura, autorización en cada llamada y un plan de versiones. El protocolo Agent2Agent (A2A) es un estándar abierto con el que un agente de IA encuentra a otro, le delega una tarea y recoge el resultado, sin que ninguno vea los prompts, la memoria ni las herramientas del otro.
A2A llegó a su primera versión estable, la 1.0, en marzo de 2026. Google lo anunció en abril de 2025 y lo cedió a la Linux Foundation en junio de 2025. En agosto de 2026 pasó a ser un proyecto alojado por la Agentic AI Foundation, la misma casa neutral que MCP. La Linux Foundation cuenta más de 150 organizaciones que lo respaldan y despliegues en producción dentro de Azure AI Foundry y Amazon Bedrock AgentCore. El protocolo es lo bastante estable para diseñar sobre él. Las decisiones de diseño siguen siendo tuyas, y de ellas trata esta guía.
¿Dónde encaja A2A frente a MCP?
La documentación de A2A describe MCP como vertical y A2A como horizontal. MCP le da a un agente más herramientas: una base de datos, la API de un calendario, un almacén de archivos. A2A conecta ese agente con otros agentes que no controlas. Un agente de planificación dentro de tu SaaS usa MCP para leer el servicio de calendario y A2A para recibir trabajo del agente de compras de un cliente. Casi todos los productos que exponen un agente acabarán usando los dos.
Para el diseño, lo que cuenta es la opacidad. Un cliente MCP llama a tus herramientas una por una y ve cada resultado. Un cliente A2A te entrega un objetivo y recibe una tarea, actualizaciones de estado y artifacts. Los prompts, la cadena de herramientas y el razonamiento intermedio quedan en privado. Si aún no tienes la parte MCP, empieza por qué hace un servidor MCP por un SaaS.
Qué necesitas antes de empezar
- Un agente que ya completa un trabajo de principio a fin dentro del producto, con sus propias herramientas.
- Un almacén de trabajos que sobreviva a los reinicios, una tabla o una cola. Una tarea A2A puede durar horas, y quien la pidió la vuelve a leer por su id.
- Un proveedor de identidad que hable OAuth 2.0 u OpenID Connect. Las Agent Cards declaran esquemas con API key, autenticación HTTP, OAuth 2.0, OpenID Connect y TLS mutuo.
- Uno de los SDK oficiales: Python, Go, Java, JavaScript, C#/.NET o Rust. La especificación exige a los SDK que gestionen la negociación de versión, que es justo la parte que menos conviene escribir a mano.
Paso 1: describe cada skill como el resultado que busca quien llama
Las skills son lo que lee el modelo del agente que llama para decidir si te delega el trabajo. Cada skill de la Agent Card lleva un id, un name, una description, tags, examples y los formatos que acepta y devuelve. Ese texto es un prompt para un modelo que no conoces. Escríbelo como documentación para un desconocido: qué hace la skill, qué necesita y qué devuelve.
Agrupa las skills por resultado. «Concilia una factura con su orden de compra» es una skill. Las funciones que hay detrás (recuperar la factura, cruzar las líneas, marcar la diferencia) son tu implementación, y la ejecución opaca de A2A las deja fuera de la card. Mantén la lista corta: cada skill de más es otra opción en la que el modelo de quien llama puede equivocarse. Dale a cada skill al menos un ejemplo en lenguaje natural y, cuando la entrada sea estructurada, otro en JSON, como hace la card de ejemplo de la propia especificación.
Paso 2: publica la Agent Card en la dirección well-known
Un servidor A2A tiene que publicar una Agent Card. El sitio estándar es https://tu-dominio/.well-known/agent-card.json; también valen los registros y la configuración directa. Una card mínima en v1.0, con una sola skill, tiene este aspecto:
{
"name": "Invoice Reconciliation Agent",
"description": "Matches supplier invoices against purchase orders and flags variances.",
"version": "2.1.0",
"provider": { "organization": "Example SaaS", "url": "https://example.com" },
"supportedInterfaces": [
{ "url": "https://agents.example.com/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" }
],
"capabilities": { "streaming": true, "pushNotifications": true, "extendedAgentCard": true },
"securitySchemes": {
"oidc": { "openIdConnectSecurityScheme": { "openIdConnectUrl": "https://auth.example.com/.well-known/openid-configuration" } }
},
"securityRequirements": [{ "schemes": { "oidc": { "list": ["openid"] } } }],
"defaultInputModes": ["application/json", "text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [
{
"id": "reconcile-invoice",
"name": "Reconcile an invoice",
"description": "Compares one supplier invoice with its purchase order. Returns matched lines, variances and a pass or hold decision.",
"tags": ["finance", "invoices", "reconciliation"],
"examples": ["Reconcile invoice INV-2291 against PO-7781."],
"inputModes": ["application/json", "application/pdf"],
"outputModes": ["application/json"]
}
]
}Cuatro campos cargan con casi todo el peso del diseño.
supportedInterfacesenumera los endpoints por orden de preferencia. El cliente coge el primero que sabe usar, así que pon arriba el binding que más has probado.capabilitiestiene que decir la verdad. Si un cliente llama a una función opcional que la card no declara, el servidor debe responder con un error. Declara el streaming solo cuando el streaming funcione.securitySchemesle dice a quien llama cómo conseguir un token antes de la primera petición.extendedAgentCarddeja corta la card pública y muestra las skills propias de cada tenant solo a quien se ha autenticado, conGetExtendedAgentCard.
Sirve la card con Cache-Control y un ETag derivado de su versión, como recomienda la especificación. Cuando quien llama necesite comprobar de dónde viene la card, fírmala con JSON Web Signature sobre su forma JSON canónica (RFC 7515 y RFC 8785).
Paso 3: haz corresponder los estados de tus trabajos con el ciclo de vida de la tarea
En A2A v1.0 una tarea pasa por ocho estados. Antes de escribir un solo handler, apunta qué estado interno de tus trabajos cae en cada uno.
- Submitted y working: aceptada y, después, en curso.
- Input-required: el agente necesita más información. Quien llama responde con un mensaje nuevo que lleva el mismo id de tarea.
- Auth-required: el agente necesita una credencial o la aprobación de una persona para seguir.
- Completed, failed, canceled y rejected: estados finales. Una tarea en estado final no acepta más mensajes.
Tres reglas de la especificación marcan el resto. Los id de las tareas los genera el servidor, y un cliente no puede crear una tarea con un id propio. Los resultados van en los artifacts; los mensajes llevan conversación y estado, así que quien busca la salida lee los artifacts. Y una respuesta rápida que no necesita seguimiento puede volver como un único mensaje, sin tarea. Usamos rejected para el trabajo que el agente decide no hacer (fuera de alcance, contra una norma) y reservamos failed para el trabajo que se ha roto por un error, porque el siguiente paso de quien llama cambia: probar en otro sitio o volver a intentarlo más tarde.
El contextId agrupa las tareas relacionadas en una misma conversación. Un agente puede hacer caducar los contextos, y la especificación pide documentar esa política. Escribe la caducidad en las descripciones de las skills o en la documentación enlazada, para que quien llama sepa cuánto tiempo sigue siendo válida una petición de seguimiento.
Paso 4: elige un binding y un canal de actualizaciones
La v1.0 define tres bindings que deben comportarse igual: JSON-RPC 2.0, gRPC y HTTP+JSON. Las operaciones se llaman igual en los tres: SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask. En el binding REST se convierten en rutas como POST /message:send y GET /tasks/{id}. Elige el binding que tu gateway y tu sistema de observabilidad ya manejan. En un stack web suele ser JSON-RPC o HTTP+JSON sobre HTTPS.
Quien llama puede seguir una tarea de tres formas: consultando GetTask cada cierto tiempo, con streaming o con notificaciones push a un webhook que registra. Nuestra opción por defecto es el streaming para las tareas que terminan mientras quien llama espera, y el push para las que duran lo suficiente como para que se corte la conexión. En el push la especificación es muy concreta en seguridad:
- Envía las credenciales configuradas en cada llamada al webhook.
- Corta las peticiones al webhook a los 10-30 segundos y reintenta con backoff exponencial.
- Rechaza las URL de webhook que apunten a localhost, a direcciones link-local o a redes privadas como 10.0.0.0/8 y 192.168.0.0/16. Sin ese control, el agente se convierte en una herramienta de request forgery contra su propia red.
- En el lado que recibe, procesa las notificaciones de forma idempotente: los duplicados están previstos.
Paso 5: autoriza cada llamada según quién llama
La especificación exige un control de autorización en cada operación, antes de cualquier consulta que pueda revelar si un recurso existe. ListTasks devuelve solo las tareas que quien llama puede ver, aunque la petición no lleve filtros. GetTask sobre la tarea de otro tenant responde como si la tarea no existiera. Saca el tenant del token de quien llama a la entrada y pásalo a cada lectura del almacén.
Usa el estado auth-required para los permisos que el agente todavía no tiene: un token OAuth hacia un servicio posterior, o el visto bueno de una persona antes de un reembolso por encima de un umbral. La tarea se detiene, quien llama consigue la credencial y el trabajo continúa.
Trata como no fiable cada parte que llega. El texto de un agente que te delega trabajo llega a tu modelo, así que valen las mismas defensas contra la prompt injection que aplicas a la entrada de los usuarios. Las referencias a archivos se validan antes de descargarlas, por el mismo riesgo de request forgery que los webhooks. Los controles que describimos para blindar un servidor MCP para empresas (SSO, registro de auditoría, un gateway delante) sirven casi sin cambios.
Paso 6: separa la versión del protocolo de la versión de la card
En un despliegue A2A conviven dos números de versión. La versión del protocolo es Major.Minor: el cliente la envía en la cabecera A2A-Version y la card la declara para cada interfaz. El campo version de la card, en cambio, es la release de tu agente, y cambia cada vez que cambian las skills.
Una petición con la cabecera A2A-Version vacía se trata como 0.3, y una versión que la interfaz no sirve recibe VersionNotSupportedError. Importa porque la v1.0 rompió la compatibilidad con la 0.3: message/send pasó a ser SendMessage, los valores de los enum pasaron a SCREAMING_SNAKE_CASE y protocolVersion se movió de la card a cada interfaz. Si ya tienes clientes 0.3, sirve las dos versiones como interfaces separadas y retira la 0.3 en una fecha que publiques.
Cómo comprobar que funciona
- Descarga la card con
curl. Esperas un 200, JSON válido,Cache-Controly unETag. - Envía un mensaje sin token. Esperas un error de autenticación, no una tarea.
- Envía un mensaje válido. Esperas una tarea con un id generado por el servidor, en estado submitted o working.
- Lee esa tarea con el token de otro tenant. Esperas un error de tarea no encontrada.
- Cancela la misma tarea dos veces. Las dos llamadas deben dejar el mismo estado.
- Abre un stream y comprueba que se cierra cuando la tarea llega a un estado final.
- Envía
A2A-Version: 9.9. EsperasVersionNotSupportedError. - Registra un webhook en
http://127.0.0.1. Esperas un rechazo.
Errores frecuentes y cómo corregirlos
- Skills con el nombre de funciones internas. Quien llama elige la equivocada, o ninguna. Renómbralas según el resultado y añade ejemplos.
- Salida dentro de los mensajes de estado. Quien lee los artifacts no encuentra nada. Mueve los resultados a los artifacts y deja los mensajes para preguntas y avances.
- Capabilities declaradas antes de que funcionen. Una card con
streaming: truesin unSubscribeToTaskque funcione hace fallar a los clientes que se fían de ella. Activa el flag el día en que la función esté en producción. - Nombres de la 0.3 y la 1.0 mezclados en el mismo endpoint. El cliente negocia una versión por interfaz. Separa las interfaces.
- contextId usado como identidad. Agrupa conversaciones y no dice nada de quien llama. La autorización sale del token.
Para ir más allá
A2A cubre la conversación entre agentes; cada agente sigue necesitando sus propias herramientas y sus propias reglas. Para la gobernanza, lee qué cambió para MCP con la Linux Foundation, y para lo que falla cuando varios agentes se reparten el trabajo, los 12 errores de los equipos en su primer sistema multiagente.
Preguntas frecuentes
Resuelven problemas distintos, así que uno no sustituye al otro. Un servidor MCP deja que un agente de IA llame a las herramientas de tu producto de una en una, y la planificación la hace el modelo de quien llama. Un servidor A2A deja que otro agente le entregue al tuyo un objetivo completo y reciba una tarea con seguimiento y sus resultados, mientras tus prompts y herramientas quedan en privado. Si los agentes de tus clientes sobre todo necesitan leer y escribir datos, con MCP basta. Añade A2A cuando tu agente haga un trabajo que merezca la pena delegar, como una conciliación en varios pasos o una revisión que puede pararse a esperar la aprobación de una persona.
No. Google creó A2A y lo anunció en abril de 2025, y en junio de 2025 lo donó a la Linux Foundation con AWS, Cisco, Microsoft, Salesforce, SAP y ServiceNow como miembros fundadores. Desde agosto de 2026 es un proyecto alojado por la Agentic AI Foundation, que también aloja MCP. La definición normativa es un archivo de Protocol Buffers en un repositorio público con licencia Apache 2.0, y los cambios pasan por la gobernanza abierta del proyecto.
No. Una API REST es determinista: la misma petición devuelve siempre la misma estructura, y de eso dependen las integraciones, los informes y la facturación. Un agente A2A responde a objetivos en lenguaje natural o en datos estructurados, y el camino hasta la respuesta puede cambiar de una versión del modelo a otra. Mantén la API REST como contrato para los sistemas y pon el agente A2A a su lado para el trabajo que pide criterio. Muchos agentes A2A llaman por dentro a esa misma API REST a través de sus herramientas.
Sí. Un servidor A2A puede actuar como cliente de agentes posteriores, y las cadenas de agentes son un patrón habitual. Hay tres cosas que diseñar. Las credenciales: tu agente llama al siguiente con su propio token, no con el de quien hizo la petición original, y registra para quién trabaja. Los tiempos: cada salto añade latencia, así que las cadenas largas deberían usar notificaciones push en lugar de mantener streams abiertos. Los bucles: pon un límite de saltos o un id de traza en los metadatos del mensaje, para que dos agentes no se devuelvan la misma tarea una y otra vez.
Servicios relacionados
Artículos relacionados
IA
IAWebMCP en 2026: la API con la que los agentes usan tu SaaS
Con WebMCP una página registra herramientas que un agente de IA del navegador llama directamente. Chrome 149 lo prueba en origin trial. Qué cambia en tu SaaS.
IA