Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Descubrimiento de agentes A2A

Esta implementación puede publicar sus agentes para que otra implementación, o cualquier cliente HTTP, pueda encontrarlos y llamarlos. A2A es el protocolo para que un agente llegue a otro agente, del mismo modo que una persona se conecta con un bot a través de una aplicación de chat. Esta página muestra exactamente qué escribir y exactamente qué devuelve.

Cada respuesta en esta página es una salida real de un daemon en ejecución. Nada aquí es ilustrativo.

Autenticación

Los dos GET de descubrimiento no están autenticados: la tarjeta de catálogo y la tarjeta del agente por alias se pueden leer sin un token, así que un par puede descubrir tu superficie publicada antes de emparejarse. El POST message/send es diferente. Ejecuta un turno completo del agente con herramientas habilitadas, así que está detrás de la autenticación de emparejamiento de la puerta de enlace, como cualquier otra superficie de escritura. Cuando [gateway] require_pairing está activado (el valor predeterminado), pasa un token portador derivado del emparejamiento en el POST de tarea:

curl -X POST http://localhost:42617/a2a/agent_alpha \
  -H "Authorization: Bearer $ZEROCLAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{...}}'

Un POST de tarea sin autenticación recibe 401, nunca un turno de agente. Los GET de descubrimiento a continuación no necesitan encabezado. Consulta la documentación de emparejamiento del gateway para obtener un token.

Todo en dos solicitudes

Solo necesitas dos solicitudes GET para descubrir un agente.

Primero, pregunta a la implementación qué agentes publica:

curl http://localhost:42617/.well-known/agents-card.json

Segundo, pregunta a uno de esos agentes qué puede hacer:

curl http://localhost:42617/a2a/agent_alpha/.well-known/agent-card.json

La primera solicitud te da una lista de URLs de agentes. La segunda te da las habilidades de un agente y la URL a la que envías el trabajo. Esa es toda la superficie de descubrimiento. El resto de esta página consiste simplemente en leer esas dos respuestas con cuidado.

Solicitar 1: listar los agentes

curl http://localhost:42617/.well-known/agents-card.json

Respuesta:

{
    "nombre": "ZeroClaw agents",
    "descripción": Catálogo de descubrimiento que enumera los agentes A2A publicados en esta instalación de ZeroClaw. No es un agente ejecutable; cada entrada a continuación sirve su propia tarjeta A2A y su propio endpoint. Las habilidades se agregan a partir de los agentes publicados, cada una etiquetada con su alias propietario.,
    "supportedInterfaces": [
        {
            "url": "http://localhost:42617/.well-known/agents-card.json",
            protocolBinding: catálogo,
            "protocolVersion": "1.0"
        },
        {
            "url": "http://localhost:42617/a2a/agent_beta",
            protocolBinding: JSONRPC,
            "protocolVersion": "1.0"
        },
        {
            "url": "http://localhost:42617/a2a/agent_alpha",
            protocolBinding: JSONRPC,
            "protocolVersion": "1.0"
        }
    ],
    versión: "0.8.5",
    capabilities: {
        streaming: false,
        pushNotifications: false,
        extendedAgentCard: false
    },
    "defaultInputModes": ["texto"],
    "defaultOutputModes": ["texto"],
    "skills": [
        {
            "id": "agent_beta/github-issue-triage",
            "nombre": "github-issue-triage",
            "descripción": "Agente de triaje de incidencias y gestión del ciclo de vida para ZeroClaw.",
            "tags": ["github", "issues", triage, "agent_beta"]
        },
        {
            "id": "agent_beta/github-pr-review-session",
            "nombre": "github-pr-review-session",
            "descripción": "Copiloto de revisión humana para las revisiones de PR de ZeroClaw.",
            "tags": ["github", "pull-requests", "review", "agent_beta"]
        },
        {
            "id": "agent_alpha/zeroclaw",
            "nombre": zeroclaw,
            "descripción": "Ayuda a los usuarios a operar e interactuar con su instancia del agente ZeroClaw.",
            "tags": [operaciones, cli, "gateway", "agent_alpha"]
        },
        {
            "id": "agent_alpha/skill-creator",
            "nombre": "skill-creator",
            "descripción": "Crear nuevas habilidades, modificar y mejorar las habilidades existentes, y medir el rendimiento de las habilidades.",
            "tags": ["skills", authoring, evaluación, "agent_alpha"]
        },
        {
            "id": "agent_alpha/changelog-generation",
            "nombre": "changelog-generation",
            "descripción": "Habilidad de generación de changelog para los lanzamientos de ZeroClaw.",
            "tags": [historial de cambios, "release", automatización, "agent_alpha"]
        }
    ]
}

Léelo así. supportedInterfaces enumera URLs. La marcada catalog es esta misma lista, ignórala. Las dos marcadas JSONRPC son los agentes: agent_alpha y agent_beta. Sus URLs son adonde enviarás el trabajo. skills agrega las habilidades de cada agente publicado, cada id con prefijo y con tags-etiquetado con el alias propietario, así que una sola lectura muestra toda la superficie de capacidades de la instalación y quién posee cada parte.

Solicitar 2: inspeccionar un agente

Toma una URL de la lista y añade la ruta de la tarjeta:

curl http://localhost:42617/a2a/agent_alpha/.well-known/agent-card.json

Respuesta:

{
    "nombre": "agent_alpha",
    "descripción": "ZeroClaw agente 'agent_alpha'.",
    "supportedInterfaces": [
        {
            "url": "http://localhost:42617/a2a/agent_alpha",
            protocolBinding: JSONRPC,
            "protocolVersion": "1.0"
        }
    ],
    versión: "0.8.5",
    capabilities: {
        streaming: false,
        pushNotifications: false,
        extendedAgentCard: false
    },
    "defaultInputModes": ["texto"],
    "defaultOutputModes": ["texto"],
    "skills": [
        {
            "id": zeroclaw,
            "nombre": zeroclaw,
            "descripción": "Ayuda a los usuarios a operar e interactuar con su instancia del agente ZeroClaw.",
            "tags": [operaciones, cli, "gateway"]
        },
        {
            "id": "skill-creator",
            "nombre": "skill-creator",
            "descripción": "Crear nuevas habilidades, modificar y mejorar las habilidades existentes, y medir el rendimiento de las habilidades.",
            "tags": ["skills", authoring, evaluación]
        },
        {
            "id": "changelog-generation",
            "nombre": "changelog-generation",
            "descripción": "Habilidad de generación de changelog para los lanzamientos de ZeroClaw.",
            "tags": [historial de cambios, "release", automatización]
        }
    ]
}

Ahora ya sabes tres cosas. El agente se llama agent_alpha. Tiene tres habilidades, zeroclaw, skill-creator y changelog-generation, con descripciones sencillas de lo que hace cada una. Y la única URL de interfaz JSONRPC, http://localhost:42617/a2a/agent_alpha, es la dirección a la que haces POST de una tarea.

La description de la tarjeta proviene del documento de identidad del alias cuando hay uno configurado: la biografía de una identidad de AIEOS aporta la línea, y si no, se usa el nombre de esa identidad. Cuando no hay identidad configurada, la tarjeta usa el valor neutro predeterminado ZeroClaw agent '<alias>'. mostrado arriba.

Lo que un agente elige mostrar

Un agente no tiene que publicar todas las habilidades que tiene. El agente agent_beta en esta misma implementación publica su propio conjunto seleccionado:

curl http://localhost:42617/a2a/agent_beta/.well-known/agent-card.json
{
    "nombre": "agent_beta",
    "descripción": "ZeroClaw agent 'agent_beta'.",
    "supportedInterfaces": [
        {
            "url": "http://localhost:42617/a2a/agent_beta",
            protocolBinding: JSONRPC,
            "protocolVersion": "1.0"
        }
    ],
    versión: "0.8.5",
    capabilities: {
        streaming: false,
        pushNotifications: false,
        extendedAgentCard: false
    },
    "defaultInputModes": ["texto"],
    "defaultOutputModes": ["texto"],
    "skills": [
        {
            "id": "github-issue-triage",
            "nombre": "github-issue-triage",
            "descripción": "Agente de triaje de incidencias y gestión del ciclo de vida para ZeroClaw."
        },
        {
            "id": "github-pr-review-session",
            "nombre": "github-pr-review-session",
            "descripción": "Copiloto de revisión humana para las revisiones de PR de ZeroClaw."
        }
    ]
}

La implementación eligió qué agentes publicar y qué habilidades expone cada uno. Ese es el propósito de publicar: decides por cada agente qué habilidades puede ver el mundo exterior.

Enviando una tarea

Una vez que tengas la URL de la interfaz de un agente y una habilidad, envías el trabajo como un POST JSON-RPC message/send a esa URL:

curl -X POST http://localhost:42617/a2a/agent_alpha \
  -H "Authorization: Bearer $ZEROCLAW_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "role": "user",
        "parts": [{ "kind": "text", "text": "Responder con PONG" }]
      }
    }
  }'

El agente ejecuta el turno y responde con una tarea completada. La respuesta es la parte de texto dentro del artefacto de la tarea:

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "artifacts": [
            {
                "artifactId": "5346ae32-1b63-40c0-9aaa-345d815c792e",
                "parts": [
                    {
                        "kind": "text",
                        "text": "PONG"
                    }
                ]
            }
        ],
        "contextId": "a2a_agent_alpha_06cb22f5-12bf-4b26-9ebc-9c063ab520a4",
        "id": "0ef19fcb-b5e4-4c26-afce-d80451c8861e",
        "kind": "task",
        "status": {
            "state": "completed"
        }
    }
}

La URL de la interfaz es la misma para la detección y para las tareas; solo cambia la solicitud. El endpoint solo acepta message/send; cualquier otro method devuelve un JSON-RPC -32601, un mensaje vacío devuelve -32602, y un cuerpo que no sea JSON-RPC devuelve HTTP 400.

Exposición y el único filo afilado

El endpoint de tareas comparte los controles de habilitación y publicación de las tarjetas: solo responde cuando se establece [a2a.server] enabled y el alias está habilitado y publicado. Un POST de tarea a un alias no publicado o desconocido devuelve 404, igual que su tarjeta. Sin embargo, no comparte la postura de autenticación de las tarjetas: las tarjetas de descubrimiento siguen siendo públicas, mientras que la invocación de tareas requiere el token bearer de la puerta de enlace y devuelve 401 sin él.

Un detalle a tener en cuenta: la URL de la interfaz responde a un GET simple con el panel web, no con un agente, porque el gateway recurre a servir el panel para cualquier ruta que no reconoce:

curl -i http://localhost:42617/a2a/translator
HTTP/1.1 200 OK
content-type: text/html

Discovery (las rutas .well-known) y el POST message/send son la superficie admitida. Un GET simple en la URL de la interfaz no forma parte del protocolo; en su lugar, lee la tarjeta en la ruta .well-known.

Desde dónde sirven los agentes

Las tarjetas son servidas por la puerta de enlace web, en la misma dirección y puerto que todo lo demás. Si tu puerta de enlace está en localhost:42617, ahí es donde viven el catálogo y cada tarjeta de agente. No ejecutas un segundo servidor y no abres un segundo puerto.

Si colocas este despliegue detrás de un proxy inverso o un nombre de host público, las URL dentro de las tarjetas deben coincidir con la dirección que los clientes realmente alcanzan. La URL publicada se resuelve en este orden: una URL base pública explícita si estableces una, luego una anulación específica de host y puerto de A2A si la estableces, y después la propia dirección del gateway. La anulación existe para el caso de proxy; si no estás detrás de un proxy, no la tocas nunca y las tarjetas anuncian directamente la dirección del gateway.

Activándolo

Discovery está desactivado hasta que lo activas, y está desactivado de tres formas independientes para que nada se filtre por accidente:

  • El servidor A2A está deshabilitado para todo el despliegue de forma predeterminada.
  • Cada agente no está publicado de forma predeterminada, incluso con el servidor en marcha.
  • Un agente publicado expone solo las habilidades que nombras, nada más.

Habilitas el servidor una vez, marcas los agentes específicos que quieres que sean accesibles como publicados y enumeras las habilidades que expone cada uno. Un agente que está deshabilitado, o que no está publicado, no aparece en el catálogo y la ruta de su tarjeta devuelve 404. Un nombre de agente desconocido devuelve 404 también.

Una habilidad con nombre aparece en la tarjeta solo cuando se resuelve en una habilidad real que el agente realmente lleva: debe residir en uno de los paquetes de habilidades del agente y su SKILL.md debe tener frontmatter YAML válido. Un nombre que no se resuelve, o una habilidad en un paquete que el agente no declara, se omite silenciosamente en lugar de anunciarse.

La causa más común de un array vacío skills: [] es configurar a2a.exposed_skills en un agente que no declara ningún skill_bundles. exposed_skills solo restringe el conjunto de habilidades resuelto del agente; no carga habilidades por sí solo. Si no se declara ningún paquete, no hay nada que el filtro pueda conservar, así que todos los nombres se descartan y la tarjeta no anuncia nada. Añade el o los paquetes propietarios a agents.<alias>.skill_bundles. La validación de configuración expone este caso como una advertencia de inicio (a2a_exposed_skills_without_bundles).

Lo que realmente expone la publicación

Lea esto antes de publicar. Una vez que el servidor esté habilitado y se publique un alias, POST /a2a/{alias} ejecuta un turno completo del agente para ese alias: lo invoca a través de la misma ruta que usan las superficies de chat, con todo el conjunto de herramientas configurado del agente (shell, archivos, navegador y cualquier otra cosa que lleve ese alias).

Ese endpoint de tarea está detrás de la autenticación bearer/pairing de la pasarela, como cualquier otra superficie de escritura. Un llamador necesita un token bearer derivado del pairing para invocar un agente publicado; una solicitud no autenticada obtiene 401, nunca un turno del agente.

Las tarjetas de descubrimiento no están detrás de esa autenticación. El catálogo y las tarjetas por alias se pueden leer sin un token, así que una superficie publicada anuncia los nombres de sus agentes y las habilidades expuestas a cualquier cliente que pueda الوصولar al listener. Ese es el propósito del descubrimiento: un par lee la tarjeta antes incluso de emparejarse. También significa que publicar expone esos metadatos a cualquiera que pueda acceder al gateway, aunque invocar al agente siga requiriendo un token.

La publicación es una decisión de exposición en ambos ejes: los metadatos de la tarjeta son públicos, y cualquier poseedor de un token válido puede invocar un alias publicado con su conjunto completo de herramientas. Antes de activar los interruptores:

  • Delimite la postura de enlace. Enlace la puerta de enlace a una interfaz privada, o colóquela detrás de un proxy inverso, en lugar de exponer directamente el listener a una red no confiable. Esto también limita quién puede leer las tarjetas no autenticadas.
  • Publique solo los alias cuyo conjunto completo de herramientas esté dispuesto a permitir que invoque cualquier titular de tokens, y cuyos nombres y habilidades esté dispuesto a anunciar sin autenticación. Reduzca exposed_skills al mínimo que necesita la interoperabilidad.
  • Trata un alias publicado como una superficie de ejecución invocable de forma remota cuando decidas qué herramientas y paquetes de habilidades lleva ese alias.
  • La interoperabilidad entre despliegues comparte un token con el par que te llama; limita el ámbito y rota esa credencial como cualquier otra.

Cómo se conectan varias implementaciones

Discovery se compone a través de cualquier número de despliegues. Cada despliegue publica su propio catálogo en su propia dirección. Un cliente que conoce varias direcciones de despliegue recupera cada catálogo, lee los agentes y ahora tiene un mapa combinado de cada agente alcanzable en todos ellos. No hay registro ni servidor central: el cliente es lo único que necesita conocer las direcciones, y se comunica directamente con cada despliegue.

Una imagen ilustrativa. Ejecutas una implementación personal. Tu equipo ejecuta una compartida. Un equipo de datos ejecuta una tercera. Tu cliente recupera los tres catálogos:

curl http://personal.example:42617/.well-known/agents-card.json
curl http://team.example:42617/.well-known/agents-card.json
curl http://data.example:42617/.well-known/agents-card.json

Cada uno devuelve su propia lista de agentes. Tu cliente ahora ve, por ejemplo, un agente notes en personal, un agente deploy en team y un agente query en data. Para usar cualquiera de ellos, obtiene la tarjeta de ese agente y envía una tarea a la URL de ese agente, exactamente como se muestra arriba. No cambia nada por despliegue; son las mismas dos lecturas y un POST, apuntando a un host diferente.

Casos de uso

Algunas razones concretas para vincular implementaciones entre sí.

Una implementación de investigación delega la búsqueda bibliográfica a una implementación de datos especializada. El agente de investigación descubre el agente search de la implementación de datos, le envía una consulta como una tarea y incorpora el resultado en su propio trabajo. El lado de investigación nunca posee las credenciales ni los índices del lado de datos; solo conoce la URL del agente.

Una implementación de guardia distribuye un incidente a implementaciones propiedad de cada equipo. Descubre un agente triage en la implementación de cada equipo y envía a cada uno el mismo incidente como una tarea, recopilando sus respuestas. Cada equipo controla lo que expone su agente de triage; del lado de guardia solo se leen tarjetas y se envían tareas.

Una implementación personal llama a los agentes verificados de una implementación de empresa sin compartir credenciales. Descubres el agente invoice de la empresa, le envías una solicitud preliminar y recibes un resultado. La empresa decide qué agentes y habilidades se publican; nunca obtienes una cuenta dentro de su implementación, solo el endpoint del agente.

A2A no es MCP

Estos resuelven problemas distintos y se complementan. MCP conecta un agente con sus herramientas y contexto: responde a qué puede llamar un único agente. A2A conecta un agente con otros agentes como pares: responde a qué otros agentes puede pasarles trabajo. Un agente al que accedes a través de A2A puede usar herramientas de MCP internamente para hacer el trabajo, y tú no lo ves ni te importa; la tarjeta muestra habilidades, no las herramientas detrás de ellas. Usa MCP para dotar a un agente de capacidades, usa A2A para permitir que los agentes deleguen entre sí.