Agent Card dans A2A: exemple JSON complet et analyse des champs
Une Agent Card est un document JSON qui indique à un agent client qui appeler, où envoyer une tâche et quelles compétences sont disponibles. Dans le protocole A2A (Agent2Agent), la carte est généralement publiée à /.well-known/agent-card.json: sans elle, l'agent est difficile à découvrir; avec une description vague, difficile à router correctement.
- Agent Card - contrat public des capacités de l'agent
- Discovery - recherche de la carte via URL well-known ou registry
- skills - compétences concrètes, pas un générique «je sais tout faire»
- capabilities - streaming, push, carte étendue
- security - schémas d'authentification de style OpenAPI
À quoi sert l'Agent Card
A2A relie des agents indépendants: l'un agit comme client, l'autre comme exécuteur. Avant d'envoyer une tâche, le client lit la carte et répond:
- Cet agent correspond-il à l'intention de l'utilisateur?
- Quel endpoint accepte les tâches?
- Quels types MIME sont supportés en entrée et en sortie?
- Une authentification est-elle requise, et laquelle?
- Le streaming d'événements et les webhooks sont-ils supportés?
La carte n'est pas un texte marketing. Les orchestrateurs et les routeurs LLM la parse. Plus description, skills et examples sont précis, plus le choix de l'exécuteur est stable.
Exemple JSON complet
Voici un exemple fonctionnel pour un agent qui cherche des produits sur un site, calcule le prix et crée une demande après confirmation de l'utilisateur. Les champs sont en camelCase, comme dans les cartes JSON A2A typiques.
{
"name": "Site Commerce Agent",
"description": "Recherche dans le catalogue du site, calcule le prix et le délai de livraison, et crée une demande après confirmation de l'utilisateur. Travaille avec le catalogue, le panier brouillon et les statuts de commande. Ne traite pas les paiements et ne modifie pas les prix.",
"version": "1.2.0",
"protocolVersion": "0.3.0",
"url": "https://api.example.com/a2a",
"documentationUrl": "https://docs.example.com/a2a/commerce-agent",
"iconUrl": "https://example.com/icons/commerce-agent.svg",
"provider": {
"organization": "Example Shop",
"url": "https://example.com"
},
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true,
"extendedAgentCard": false
},
"defaultInputModes": [
"text/plain",
"application/json"
],
"defaultOutputModes": [
"text/plain",
"application/json"
],
"skills": [
{
"id": "search-products",
"name": "Recherche de produits",
"description": "Recherche des produits par requête, catégorie, prix et disponibilité. Renvoie des candidats avec id, nom, prix et courte description.",
"tags": ["catalog", "search", "products"],
"examples": [
"Trouve des ordinateurs portables à moins de 800 euros avec livraison cette semaine",
"Montre les forfaits disponibles pour une équipe de 20 personnes"
],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json", "text/plain"]
},
{
"id": "calculate-quote",
"name": "Calcul de devis",
"description": "Calcule le prix, les taxes, la livraison et le délai pour les articles et quantités sélectionnés. Ne crée pas de commande.",
"tags": ["pricing", "quote", "shipping"],
"examples": [
"Calcule le coût de 3 unités de product_id=sku-1042 avec livraison à Berlin",
"Compare les forfaits Basic et Pro pour 50 utilisateurs"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": ["application/json"]
},
{
"id": "create-lead",
"name": "Création de demande",
"description": "Crée un brouillon de lead ou de demande après confirmation explicite de l'utilisateur. Nécessite un contact et un consentement au traitement des données.",
"tags": ["lead", "order-draft", "crm"],
"examples": [
"Crée une demande Pro pour ACME, contact: ops@acme.example",
"Prépare un brouillon de commande à partir de quote_id=q-7781"
],
"inputModes": ["application/json"],
"outputModes": ["application/json", "text/plain"]
},
{
"id": "get-order-status",
"name": "Statut de commande",
"description": "Renvoie le statut de paiement et de livraison par order_id pour un utilisateur authentifié ou un numéro de suivi public.",
"tags": ["orders", "status", "tracking"],
"examples": [
"Quel est le statut de la commande ORD-20441?",
"Où est le colis avec le tracking TRK-998877?"
]
}
],
"securitySchemes": {
"bearer": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
},
"oauth2": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://auth.example.com/oauth/token",
"scopes": {
"catalog:read": "Lecture du catalogue et des devis",
"leads:write": "Création de demandes",
"orders:read": "Lecture des statuts de commande"
}
}
}
}
},
"security": [
{
"oauth2": ["catalog:read"]
},
{
"bearer": []
}
]
}
En A2A v1.0, l'endpoint est souvent décrit via le tableau supportedInterfaces plutôt qu'un seul url de premier niveau. L'idée est la même: indiquer où envoyer les tâches et quel binding utiliser (JSONRPC, HTTP+JSON, GRPC, etc.).
Exemple de fragment pour v1.0:
{
"supportedInterfaces": [
{
"url": "https://api.example.com/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
]
}
Analyse des champs de premier niveau
| Champ | Obligatoire | Rôle |
|---|---|---|
name |
Oui | Nom lisible de l'agent |
description |
Oui | Résumé concret: ce qu'il fait et ne fait pas |
version |
Oui | Version de l'implémentation (semver préféré) |
url / supportedInterfaces |
Oui* | Endpoint(s) de tâches, pas l'URL de la carte |
skills |
Oui | Au moins un skill |
capabilities |
Recommandé | Flags honnêtes de capacités |
defaultInputModes / defaultOutputModes |
Recommandé | MIME par défaut |
provider |
Non | Organisation propriétaire |
documentationUrl / iconUrl |
Non | Documentation et icône UI |
protocolVersion |
Selon le schéma | Version du protocole (souvent en haut en v0.3) |
securitySchemes / security |
Non | Comment le client doit s'authentifier |
* Dans les schémas v0.3, url est généralement obligatoire. En v1.0, supportedInterfaces prend le rôle d'endpoint.
name et description
name sert aux humains et aux logs. description est lue par les routeurs. Mauvais: «Un agent utile pour le site». Bon: lister opérations, limites et forme du résultat.
version
C'est la version de l'implémentation de l'agent, pas forcément celle du protocole. Augmentez major en cas de breaking changes sur les skills ou le contrat de réponse. Les clients peuvent mettre la carte en cache et la rafraîchir au changement de version.
url - erreur fréquente
url est l'adresse vers laquelle partent message/send / les tâches. Ce n'est pas le chemin vers /.well-known/agent-card.json.
Incorrect:
"url": "https://example.com/.well-known/agent-card.json"
Correct:
"url": "https://api.example.com/a2a"
capabilities
| Flag | Signification |
|---|---|
streaming |
Supporte les réponses en streaming (SSE / stream) |
pushNotifications |
Webhooks pour les tâches longues |
stateTransitionHistory |
Historique des transitions d'état de la tâche |
extendedAgentCard |
Après auth, une carte étendue/privée est disponible |
Mettez true seulement si le comportement est réellement implémenté. Un client qui ouvre un stream vers un agent sans streaming recevra une erreur.
defaultInputModes et defaultOutputModes
MIME par défaut pour tout l'agent. Un skill peut les surcharger. Valeurs typiques: text/plain, application/json, application/pdf, image/png.
Analyse de skills
Un skill est une unité de routage. Un skill = une capacité claire.
| Champ | Obligatoire | Commentaire |
|---|---|---|
id |
Oui | Unique dans l'agent; kebab-case convient bien |
name |
Oui | Nom court pour l'UI |
description |
Oui | Ce qu'il accepte, renvoie, et quelles limites |
tags |
Non | Mots-clés pour recherche et filtrage |
examples |
Non, mais fortement recommandé | 2-3 prompts réels pour l'orchestrateur |
inputModes / outputModes |
Non | Override MIME pour ce skill |
Les examples ne sont pas de la décoration. Sans eux, l'orchestrateur devine les entrées à partir de la seule description et se trompe plus souvent.
Mauvais skill:
{
"id": "website",
"name": "Website",
"description": "Travaille avec le site"
}
Un bon skill ressemble à ceux de l'exemple complet: id concret, limites claires, tags et examples.
Authentification: securitySchemes et security
Les schémas suivent généralement l'approche OpenAPI:
apiKeyhttp(Basic / Bearer)oauth2openIdConnectmutualTLS
securitySchemes décrit les méthodes disponibles. security définit l'exigence par défaut:
- plusieurs objets dans le tableau
security= alternatives (OR); - plusieurs clés dans un même objet = tout est requis (AND).
Publiez comment s'authentifier, pas les secrets. Ne mettez pas d'API keys, refresh tokens ou hostnames internes dans le JSON.
Discovery: comment la carte est trouvée
Flux typique:
- Le client connaît le domaine de base de l'agent.
- Il demande
https://agent.example.com/.well-known/agent-card.json. - Il valide les champs obligatoires.
- Il choisit un skill selon description, tags et examples.
- Il s'authentifie selon
security. - Il envoie la tâche à
url/supportedInterfaces.
La carte est aussi publiée dans des registries ou annuaires. La discovery passe alors par la recherche, tandis que well-known reste la source de vérité du propriétaire.
Vérification locale:
curl -s https://api.example.com/.well-known/agent-card.json
Ce qu'il ne faut pas publier dans l'Agent Card
- API keys, mots de passe, private keys;
- URL internes d'admin ou de staging non protégées;
- opérations indisponibles aux clients externes;
- capabilities gonflées (
streaming: truesans implémentation); - skills vagues du type «fait tout sur le site».
La carte publique est à la fois surface d'attaque et surface de routage. Gardez-la précise et minimalement suffisante.
Erreurs fréquentes
- Confondre
urlet l'URL de la carte. - Tableau
skillsvide. L'agent devient presque impossible à router. - Description sans limites. On ne dit pas ce que l'agent ne fait pas (paiement, suppression, changement de prix).
- Pas d'
examples. L'orchestrateur comprend moins bien l'entrée valide. - localhost dans une carte de production. L'endpoint doit être joignable.
- Un seul skill pour tout le produit. Préférez plusieurs skills étroits avec droits et MIME différents.
Mini checklist avant publication
- La carte est servie en HTTPS avec
Content-Type: application/json. - Elle a
name,description,version, un endpoint et au moins un skill. - Les descriptions sont concrètes.
- Les skills clés ont
examplesettags. capabilitiescorrespondent au serveur réel.- Le JSON ne contient aucun secret.
- L'endpoint de la carte répond à une tâche de test.
- La version augmente en cas de breaking changes.
Conclusion
L'Agent Card est le contrat principal de discovery dans A2A. Un JSON complet avec des skills précis, des capabilities honnêtes et une security explicite donne aux agents clients assez de données pour trouver le bon exécuteur et éviter le mauvais.
Si vous avez besoin d'aide pour concevoir une Agent Card, un serveur A2A ou le lien d'un agent avec l'API d'un site - contactez-moi.
Foire aux questions
Où doit se trouver l'Agent Card?
Le chemin public standard est /.well-known/agent-card.json sur le domaine de l'agent. Vous pouvez aussi l'enregistrer dans un catalogue ou une registry, mais l'URL well-known reste un point de discovery pratique sans index séparé.
En quoi url diffère-t-il de l'adresse de la carte?
L'adresse de la carte sert à la discovery; url (ou supportedInterfaces) à l'exécution des tâches. Le client lit d'abord le JSON, puis envoie messages/tâches à l'endpoint de travail de l'agent.
Combien de skills une carte doit-elle avoir?
Autant que de capacités vraiment distinctes avec des entrées ou des droits différents. En général, 3 à 7 skills étroits valent mieux qu'un générique «fais tout». Pour le routage, les limites claires, tags et examples comptent.
L'authentification est-elle obligatoire dans l'Agent Card?
Pas toujours. Un agent public en lecture seule peut omettre security. Pour l'écriture, les données personnelles et les opérations payantes, déclarez securitySchemes et security, et gardez les secrets hors de la carte.
Faut-il mettre à jour la carte à chaque déploiement?
Mettez-la à jour quand changent skills, endpoint, capabilities, auth ou le sens de l'agent. Un patch technique sans changement de contrat peut se refléter dans version; les breaking changes méritent un major et une documentation explicite.