Découverte d’agents A2A
Ce déploiement peut publier ses agents afin qu’un autre déploiement, ou n’importe quel client HTTP, puisse les trouver et les appeler. A2A est le protocole permettant à un agent d’atteindre un autre agent, de la même façon qu’une personne atteint un bot via une application de chat. Cette page montre exactement ce qu’il faut taper et exactement ce qui revient.
Toutes les réponses sur cette page sont des sorties réelles d’un démon en cours d’exécution. Rien ici n’est illustratif.
Authentification
Les deux GET de découverte sont non authentifiés : la carte catalogue et la carte d’agent par alias sont lisibles sans jeton afin qu’un pair puisse découvrir votre surface publiée avant l’appairage. Le POST message/send est différent. Il exécute un tour d’agent complet avec outils, il est donc protégé par l’authentification d’appairage de la passerelle comme toute autre surface d’écriture. Lorsque [gateway] require_pairing est activé (par défaut), passez un jeton bearer dérivé de l’appairage sur le POST de tâche :
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":{...}}'
Une requête POST de tâche non authentifiée renvoie 401, jamais de tour d’agent. Les requêtes GET de découverte ci-dessous ne nécessitent aucun en-tête. Consultez la documentation d’appairage de la passerelle pour savoir comment obtenir un jeton.
Le tout en deux requêtes
Vous n’avez besoin que de deux requêtes GET pour découvrir un agent.
Tout d’abord, demandez au déploiement quels agents il publie :
curl http://localhost:42617/.well-known/agents-card.jsonDeuxièmement, demandez à l’un de ces agents ce qu’il peut faire :
curl http://localhost:42617/a2a/agent_alpha/.well-known/agent-card.jsonLa première requête vous donne une liste d’URL d’agents. La seconde vous donne les compétences d’un agent et l’URL vers laquelle vous envoyez le travail. C’est toute la surface de découverte. Le reste de cette page consiste simplement à lire attentivement ces deux réponses.
Requête 1 : lister les agents
curl http://localhost:42617/.well-known/agents-card.jsonRéponse :
{
« nom »: Agents ZeroClaw,
"description": Catalogue de découverte répertoriant les agents A2A publiés sur cette installation ZeroClaw. Agent non exécutable ; chaque entrée ci-dessous correspond à sa propre carte A2A et à son point de terminaison. Les compétences sont agrégées à partir des agents publiés, chacune étant étiquetée avec son alias du propriétaire.,
supportedInterfaces: [
{
"url": http://localhost:42617/.well-known/agents-card.json,
protocolBinding: catalogue,
"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
}
],
version: 0.8.5,
capacités: {
diffusion en continu: false,
`"pushNotifications"`: false,
extendedAgentCard: false
},
defaultInputModes: [« texte »],
defaultOutputModes: [« texte »],
compétences: [
{
"id": agent_beta/github-issue-triage,
« nom »: github-issue-triage,
"description": Agent de tri des tickets et de gestion du cycle de vie pour ZeroClaw.,
étiquettes: [github, problèmes, tri, agent_beta]
},
{
"id": agent_beta/github-pr-review-session,
« nom »: github-pr-review-session,
"description": Co-pilote pour les relecteurs humains pour les relectures de PR ZeroClaw.,
étiquettes: [github, demandes de fusion, examen, agent_beta]
},
{
"id": agent_alpha/zeroclaw,
« nom »: zeroclaw,
"description": Aider les utilisateurs à utiliser et interagir avec leur instance d'agent ZeroClaw.,
étiquettes: [opérations, cli, passerelle, agent_alpha]
},
{
"id": agent_alpha/skill-creator,
« nom »: skill-creator,
"description": Créer de nouvelles compétences, modifier et améliorer les compétences existantes, et mesurer les performances des compétences.,
étiquettes: [compétences, authoring, évaluation, agent_alpha]
},
{
"id": agent_alpha/changelog-generation,
« nom »: changelog-generation,
"description": Compétence de génération du changelog pour les versions ZeroClaw.,
étiquettes: [journal des modifications, version, automatisation, agent_alpha]
}
]
}
Lisez-le ainsi. supportedInterfaces liste les URL. Celui étiqueté catalog est cette liste elle-même, ignorez-le. Les deux étiquetés JSONRPC sont les agents : agent_alpha et agent_beta. Leurs URL sont l’endroit où vous enverrez le travail. skills agrège les compétences de chaque agent publié, chaque id préfixé et tags-étiqueté avec l’alias propriétaire, de sorte qu’une seule lecture montre toute la surface de capacités de l’installation et qui possède chaque élément.
Requête 2 : inspecter un agent
Prenez une URL de la liste et ajoutez le chemin de la carte :
curl http://localhost:42617/a2a/agent_alpha/.well-known/agent-card.jsonRéponse :
{
« nom »: agent_alpha,
"description": Agent ZeroClaw 'agent_alpha'.,
supportedInterfaces: [
{
"url": http://localhost:42617/a2a/agent_alpha,
protocolBinding: JSONRPC,
"protocolVersion": 1.0
}
],
version: 0.8.5,
capacités: {
diffusion en continu: false,
`"pushNotifications"`: false,
extendedAgentCard: false
},
defaultInputModes: [« texte »],
defaultOutputModes: [« texte »],
compétences: [
{
"id": zeroclaw,
« nom »: zeroclaw,
"description": Aider les utilisateurs à utiliser et interagir avec leur instance d'agent ZeroClaw.,
étiquettes: [opérations, cli, passerelle]
},
{
"id": skill-creator,
« nom »: skill-creator,
"description": Créer de nouvelles compétences, modifier et améliorer les compétences existantes, et mesurer les performances des compétences.,
étiquettes: [compétences, authoring, évaluation]
},
{
"id": changelog-generation,
« nom »: changelog-generation,
"description": Compétence de génération du changelog pour les versions ZeroClaw.,
étiquettes: [journal des modifications, version, automatisation]
}
]
}
Vous savez maintenant trois choses. L’agent s’appelle agent_alpha. Il possède trois compétences, zeroclaw, skill-creator et changelog-generation, avec des descriptions simples de ce que chacune fait. Et l’unique URL d’interface JSONRPC, http://localhost:42617/a2a/agent_alpha, est l’adresse à laquelle vous POSTEZ une tâche.
La description de la carte provient du document d’identité de l’alias lorsqu’un est configuré : la bio d’une identité AIEOS fournit la ligne, avec repli sur un nom de cette identité. Lorsqu’aucune identité n’est définie, la carte utilise la valeur par défaut neutre ZeroClaw agent '<alias>'. indiquée ci-dessus.
Ce qu’un agent choisit d’afficher
Un agent n’est pas obligé de publier toutes les compétences dont il dispose. L’agent agent_beta de ce même déploiement publie son propre ensemble sélectionné :
curl http://localhost:42617/a2a/agent_beta/.well-known/agent-card.json
{
« nom »: agent_beta,
"description": Agent ZeroClaw 'agent_beta'.,
supportedInterfaces: [
{
"url": http://localhost:42617/a2a/agent_beta,
protocolBinding: JSONRPC,
"protocolVersion": 1.0
}
],
version: 0.8.5,
capacités: {
diffusion en continu: false,
`"pushNotifications"`: false,
extendedAgentCard: false
},
defaultInputModes: [« texte »],
defaultOutputModes: [« texte »],
compétences: [
{
"id": github-issue-triage,
« nom »: github-issue-triage,
"description": Agent de tri des tickets et de gestion du cycle de vie pour ZeroClaw.
},
{
"id": github-pr-review-session,
« nom »: github-pr-review-session,
"description": Co-pilote pour les relecteurs humains pour les relectures de PR ZeroClaw.
}
]
}
Le déploiement a choisi quels agents publier et quelles compétences chacun expose. C’est tout l’intérêt de la publication : vous décidez par agent quelles compétences le monde extérieur peut voir.
Envoi d’une tâche
Une fois que vous avez l’URL d’interface d’un agent et une compétence, vous envoyez le travail sous forme d’un POST JSON-RPC message/send à cette 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": "Reply with PONG" }]
}
}
}'
L’agent exécute le tour et répond avec une tâche terminée. La réponse est la partie texte à l’intérieur de l’artefact de la tâche :
PONGL’URL de l’interface est la même pour la découverte et pour les tâches ; seule la requête change. Le point de terminaison n’accepte que message/send ; toute autre method renvoie un JSON-RPC -32601, un message vide renvoie -32602, et un corps qui n’est pas JSON-RPC renvoie HTTP 400.
Exposition et l’arête vive
L’endpoint de tâche partage les portes enabled et published des cards : il répond uniquement lorsque [a2a.server] enabled est défini et que l’alias est activé et publié. Un POST de tâche vers un alias non publié ou inconnu renvoie 404, comme sa card. Il ne partage toutefois pas la posture d’authentification des cards : les cards de découverte restent publiques, tandis que l’invocation de tâche exige le jeton bearer de la gateway et renvoie 401 sans celui-ci.
Un écueil à connaître : l’URL de l’interface répond à un GET nu avec le tableau de bord web, pas un agent, car la passerelle se rabat sur le service du tableau de bord pour tout chemin qu’elle ne reconnaît pas :
curl -i http://localhost:42617/a2a/translator HTTP/1.1 200 OK content-type: text/htmlLa découverte (les chemins .well-known) et le POST message/send sont la surface supportée. Une simple requête GET sur l’URL de l’interface ne fait pas partie du protocole ; lisez plutôt la carte située au chemin .well-known.
D’où les agents servent
Les cartes sont servies par la passerelle web, sur la même adresse et le même port que tout le reste. Si votre passerelle est sur localhost:42617, c’est là que se trouvent le catalogue et chaque carte d’agent. Vous n’exécutez pas un second serveur et vous n’ouvrez pas un second port.
Si vous placez ce déploiement derrière un proxy inverse ou un nom d’hôte public, les URL contenues dans les cartes doivent correspondre à l’adresse que les clients atteignent réellement. L’URL publiée est résolue dans cet ordre : une URL de base publique explicite si vous en définissez une, puis une surcharge spécifique A2A de l’hôte et du port si vous la configurez, ensuite l’adresse propre à la passerelle. La surcharge existe pour le cas du proxy ; si vous n’êtes pas derrière un proxy, vous n’y touchez jamais et les cartes indiquent directement l’adresse de la passerelle.
Activation
Discovery est désactivé jusqu’à ce que vous l’activiez, et il est désactivé par trois mécanismes indépendants afin d’éviter toute fuite accidentelle :
- Le serveur A2A est désactivé pour l’ensemble du déploiement par défaut.
- Chaque agent est non publié par défaut, même lorsque le serveur est activé.
- Un agent publié n’expose que les compétences que vous spécifiez, rien de plus.
Vous activez le serveur une fois, marquez les agents spécifiques que vous souhaitez rendre accessibles comme publiés, et listez les compétences que chacun expose. Un agent désactivé, ou non publié, n’apparaît pas dans le catalogue et le chemin de sa carte renvoie 404. Un nom d’agent inconnu renvoie également 404.
Une compétence nommée n’apparaît sur la carte que lorsqu’elle se résout en une compétence réelle que l’agent porte effectivement : elle doit résider dans l’un des bundles de compétences de l’agent et son SKILL.md doit comporter un frontmatter YAML valide. Un nom qui ne peut pas être résolu, ou une compétence appartenant à un bundle que l’agent ne déclare pas, est ignoré silencieusement plutôt qu’annoncé.
La cause la plus courante d’un tableau skills: [] vide est de définir a2a.exposed_skills sur un agent qui ne déclare aucun skill_bundles. exposed_skills ne fait que restreindre l’ensemble de compétences résolu de l’agent ; il ne charge pas les compétences à lui seul. Sans bundle déclaré, il n’y a rien à conserver pour le filtre, si bien que chaque nom est écarté et la carte n’annonce rien. Ajoutez le(s) bundle(s) propriétaire(s) à agents.<alias>.skill_bundles. La validation de la configuration signale ce cas comme un avertissement au démarrage (a2a_exposed_skills_without_bundles).
Ce que la publication expose réellement
Lisez ceci avant de publier. Une fois le serveur activé et un alias publié, POST /a2a/{alias} exécute un tour d’agent complet pour cet alias : il invoque l’agent via le même chemin que celui utilisé par les surfaces de chat, avec l’ensemble complet d’outils configurés de l’agent (shell, file, browser, et tout ce que cet alias comporte).
Ce point de terminaison de tâche se trouve derrière l’authentification bearer/appairage de la passerelle, comme toute autre surface d’écriture. Un appelant a besoin d’un jeton bearer dérivé de l’appairage pour invoquer un agent publié ; une requête non authentifiée obtient 401, jamais un tour d’agent.
Les cartes de découverte ne sont pas protégées par cette authentification. Le catalogue et les cartes par alias sont lisibles sans jeton, donc une surface publiée annonce ses noms d’agents et ses compétences exposées à tout appelant qui peut atteindre l’écouteur. C’est le but de la découverte : un pair lit la carte avant même de s’apparier. Cela signifie aussi que la publication expose ces métadonnées à quiconque peut atteindre la passerelle, même si l’invocation de l’agent nécessite toujours un jeton.
La publication est une décision d’exposition sur les deux axes : les métadonnées de la carte sont publiques, et tout détenteur d’un jeton valide peut invoquer un alias publié avec son ensemble d’outils complet. Avant de basculer les interrupteurs :
- Limitez la posture de liaison. Liez la passerelle à une interface privée, ou placez-la derrière un reverse proxy, plutôt que d’exposer le listener directement à un réseau non fiable. Cela limite également qui peut lire les cartes non authentifiées.
- Publiez uniquement les alias dont vous êtes prêt à ce que l’ensemble complet d’outils soit invoqué par tout détenteur de jeton, et dont les noms et compétences vous êtes prêt à annoncer sans authentification. Restreignez
exposed_skillsau minimum nécessaire à l’interopérabilité. - Traitez un alias publié comme une surface d’exécution invocable à distance lorsque vous décidez quels outils et bundles de compétences cet alias porte.
- L’interopérabilité inter-déploiement partage un jeton avec le pair qui vous appelle ; définissez la portée et renouvelez ces identifiants comme tout autre.
Comment plusieurs déploiements sont connectés
Discovery compose sur un nombre quelconque de déploiements. Chaque déploiement publie son propre catalogue sur sa propre adresse. Un client qui connaît plusieurs adresses de déploiement récupère chaque catalogue, lit les agents et détient désormais une carte consolidée de tous les agents accessibles sur l’ensemble des déploiements. Il n’existe ni registre ni serveur central : le client est le seul à devoir connaître les adresses et communique directement avec chaque déploiement.
Voici un exemple concret. Vous gérez un déploiement personnel. Votre équipe gère un déploiement partagé. Une équipe data en gère un troisième. Votre client récupère les trois catalogues :
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.jsonChacun renvoie sa propre liste d’agents. Votre client voit désormais, par exemple, un agent notes à personal, un agent deploy à team, et un agent query à data. Pour en utiliser un, il récupère la carte de cet agent et lui envoie une tâche à son URL, exactement comme indiqué ci-dessus. Rien ne change selon le déploiement ; il s’agit des mêmes deux lectures et d’un POST, adressé à un hôte différent.
Cas d’utilisation
Quelques raisons concrètes d’interconnecter les déploiements.
Un déploiement de recherche délègue la recherche documentaire à un déploiement de données spécialisé. L’agent de recherche découvre l’agent search du déploiement de données, lui envoie une requête sous forme de tâche et intègre le résultat dans son propre travail. Le côté recherche ne détient jamais les identifiants ou les index du côté données ; il connaît uniquement l’URL de l’agent.
Un déploiement on-call diffuse un incident vers les déploiements appartenant aux équipes. Il découvre un agent triage dans le déploiement de chaque équipe et envoie à chacun le même incident en tant que tâche, en recueillant leurs réponses. Chaque équipe contrôle ce que son agent triage expose ; le côté on-call se contente de lire les cartes et d’envoyer des tâches.
Un déploiement personnel appelle des agents vérifiés d’un déploiement d’entreprise sans partager d’identifiants. Vous découvrez l’agent invoice de l’entreprise, lui envoyez une requête brouillon et recevez un résultat en retour. L’entreprise décide quels agents et compétences sont publiés ; vous n’obtenez jamais d’accès à leur déploiement, uniquement au point de terminaison de l’agent.
A2A n’est pas MCP
Ceux-ci résolvent des problèmes différents et se composent. MCP connecte un agent à ses outils et à son contexte : il répond à ce qu’un seul agent peut appeler. A2A connecte un agent à d’autres agents en tant que pairs : il répond à quels autres agents il peut confier du travail. Un agent que vous atteignez via A2A peut utiliser des outils MCP en interne pour faire le travail, et vous ne voyez ni ne vous en souciez ; la carte montre les compétences, pas les outils derrière elles. Utilisez MCP pour donner des capacités à un agent, utilisez A2A pour permettre aux agents de se déléguer les uns aux autres.