Agents
Un agent d'IA qui a besoin d'une adresse canadienne, d'une coordonnée ou d'un itinéraire se heurte au même problème qu'une personne développeuse à son premier jour : il doit apprendre qu'unmap existe, découvrir ce qu'unmap sait faire, obtenir une clé, puis effectuer un appel. Une personne règle cela en lisant. Un agent ne peut pas lire, alors unmap publie ces mêmes réponses sous forme de documents conçus pour les machines, et expose un point de terminaison qu'un agent peut appeler directement.
Cette page couvre (1) les documents qu'un agent lit pour découvrir unmap, (2) la carte d'agent A2A et ce qu'elle promet, (3) les huit compétences que la carte annonce et la façon d'invoquer chacune, (4) les erreurs que le point de terminaison renvoie et leur signification, et (5) les outils que le site enregistre pour un agent qui travaille dans un navigateur. Si vous écrivez du code applicatif ordinaire plutôt qu'un agent, Appeler l'API directement est la page qu'il vous faut ; tout ce qui suit s'appuie sur les points de terminaison qui y sont décrits.
Découverte
Six documents non authentifiés décrivent unmap à une machine. La plupart sont servis depuis
https://unmap.dev et depuis https://api.unmap.dev, de sorte qu'un agent partant de l'un ou
l'autre hôte trouve le reste.
/.well-known/agent-card.jsonest la carte d'agent A2A : l'identité d'unmap, ses compétences, ses schémas de sécurité et l'adresse du point de terminaison qui les exécute. C'est le point d'entrée pour un cadriciel d'agents. Les deux hôtes en servent les mêmes octets./openapi.jsonest une description OpenAPI 3.1 de chaque point de terminaison REST, surapi.unmap.devuniquement. C'est le point d'entrée pour un générateur de code ou un agent qui préfère du HTTP ordinaire./.well-known/api-catalogest un jeu de liens RFC 9727 qui nomme l'API et pointe vers les deux documents ci-dessus./.well-known/oauth-protected-resourceest la métadonnée RFC 9728 : ce qu'est cette ressource et comment un identifiant porteur se présente. Elle ne nomme aucun serveur d'autorisation, puisqu'unmap n'en exploite aucun, et chaque401y renvoie./auth.mdexplique en prose d'où vient une clé. unmap n'exploite aucun serveur d'autorisation OAuth et n'offre pas d'auto-inscription aux agents : une clé est créée par une personne dans le tableau de bord, puis confiée à l'agent. Il est servi depuisapi.unmap.dev, etunmap.dev/auth.mdy redirige. Voir Authentification./.well-known/agent-skills/index.json, surunmap.dev, recense quatre compétences en Markdown qui apprennent à un agent à appeler l'API HTTPS ordinaire, y compris la moitié cartographique que le point de terminaison ci-dessous ne couvre pas.
Le serveur MCP en publie trois autres qui lui sont propres, décrits sur Serveur MCP.
Chaque page de cette documentation est aussi disponible en Markdown. Demandez-la avec un en-tête
Accept et vous obtenez la source plutôt que la page rendue :
curl -H "Accept: text/markdown" https://unmap.dev/fr/docs/agents/a2aLa carte d'agent
La carte suit A2A v1.0 et se trouve au chemin bien connu que la spécification nomme :
curl https://unmap.dev/.well-known/agent-card.json{
"name": "unmap",
"description": "Canadian geocoding and routing as an agent-callable service. …",
"supportedInterfaces": [
{ "url": "https://api.unmap.dev/a2a", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" }
],
"version": "2.0.0",
"capabilities": { "streaming": false, "pushNotifications": false, "extendedAgentCard": false },
"skills": [ /* cinq, décrites plus bas */ ]
}La carte déclare une seule interface, et cette interface est un véritable point de terminaison.
supportedInterfaces[0].url est l'adresse à laquelle un client A2A envoie SendMessage, et
https://api.unmap.dev/a2a y répond. Cela mérite d'être dit clairement, car une carte est une
promesse plutôt qu'une description : en publier une qui pointe vers une machinerie inexistante
ferait perdre son temps à chaque client qui l'aurait crue.
Trois capacités valent false, chacune pour une raison :
streaming: un géocodage ou un itinéraire est un aller-retour qui se termine en quelques millisecondes. Il n'y a rien à diffuser en continu.pushNotifications: unmap ne crée aucuneTaskA2A. Chaque compétence répond de façon synchrone par unMessage, il n'y a donc aucun état asynchrone à signaler par un webhook. Les méthodes de tâches (GetTask,CancelTask) répondent-32001 Task not found, ce qui est exact : il n'y a pas de tâches.extendedAgentCard: un client authentifié voit exactement cette carte. Le document OpenAPI, cette documentation et la tarification sont tous publics, une seconde carte plus riche n'aurait donc rien de plus à contenir.
Authentification
Le point de terminaison accepte la même clé d'API que le reste de l'API, dans un en-tête :
Authorization: Bearer um_live_...
X-API-Key: um_live_... fonctionne également ; la carte présente les deux comme des solutions de
rechange l'une de l'autre. La troisième forme acceptée par l'API REST, ?key=, est délibérément
absente de la carte. Elle existe parce que MapLibre ne peut pas joindre d'en-têtes aux requêtes
qu'il déclenche pour les tuiles, et un client A2A n'a pas cette contrainte. Une clé active dans
une URL finit dans les journaux et les référents.
Un appel sans clé reçoit un HTTP 401 accompagné d'un défi WWW-Authenticate, et non un corps
d'erreur JSON-RPC, afin que le défi parvienne au client qui en a besoin. Il en va de même pour le
429 (limite de débit ou quota, avec Retry-After) et le 503 (un service encore en démarrage).
Obtenez une clé sur unmap.dev/dashboard/keys.
Appeler une compétence
La liaison est JSON-RPC 2.0 sur HTTPS, et le nom de méthode est SendMessage. Une compétence est
choisie par une partie de données, un objet dans message.parts portant un champ skill et
les paramètres de cette compétence :
curl -X POST https://api.unmap.dev/a2a \
-H "Authorization: Bearer $UNMAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "SendMessage",
"params": {
"message": {
"messageId": "1f0c…",
"role": "ROLE_USER",
"parts": [{ "data": { "skill": "geocode_search", "query": "rue Sainte-Catherine, Montréal", "limit": 3 } }]
}
}
}'La réponse est un Message à deux parties : une partie texte qui résume la réponse sous une forme
qu'un modèle peut lire sans rien analyser, et une partie de données contenant le JSON de l'API, tel
quel. Le résumé est rédigé en anglais quelle que soit la langue demandée ; seuls les noms de lieux
suivent language.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"message": {
"messageId": "…",
"contextId": "…",
"role": "ROLE_AGENT",
"parts": [
{ "text": "3 results:\nrue Sainte-Catherine [street] at -73.57…", "mediaType": "text/plain" },
{ "data": [ /* le tableau que /geocode/search renvoie */ ], "mediaType": "application/json" }
]
}
}
}Les coordonnées s'écrivent toujours [longitude, latitude] en degrés WGS84, dans cet ordre. La
forme chaîne "lng,lat" est également acceptée : [-114.0625, 51.0447] et "-114.0625,51.0447"
signifient la même chose.
Les mêmes compétences en MCP
Ce sont les cinq mêmes compétences que le serveur MCP
expose comme outils, exécutant le même code : une seule table dans la passerelle alimente cette
carte, la réponse tools/list de MCP et la description OpenAPI. Une compétence se comporte de
façon identique quelle que soit l'enveloppe empruntée, messages d'erreur compris, et les deux
surfaces ne peuvent pas diverger. Si votre cadriciel parle MCP, préférez-le ; A2A est là pour ceux
qui parlent A2A. Aucune capacité n'existe sur l'une sans exister sur l'autre.
Un message uniquement textuel
Si un message ne porte aucune partie de données, son texte est lu comme une requête de géocodage, et rien d'autre :
{ "role": "ROLE_USER", "parts": [{ "text": "Iqaluit" }] }C'est la seule inférence qu'unmap fait, et elle se défend parce que du texte libre est littéralement ce que prend le géocodeur plein texte. Ce n'est pas une compréhension de la phrase. unmap n'exploite aucun modèle de langue : « comment aller à Banff » est donc cherché comme un nom de lieu plutôt que calculé comme un itinéraire, et la réponse le dit dans sa partie texte. Pour atteindre les sept autres compétences, envoyez une partie de données.
Les huit compétences
| Compétence | Obligatoires | Facultatifs |
|---|---|---|
geocode_search | query | language, limit, bbox |
geocode_reverse | coordinate | language, limit |
geocode_nearby | categories, near | radius, limit, language |
route | from, to | mode, gabarits de camion |
isochrone | center, minutes | mode, gabarits de camion |
identify | coordinate | layers, geometry |
data_query | layer, bbox | limit, geometry |
list_layers | addon |
identify répond quels polygones du catalogue contiennent un point, une question différente des
lieux nommés les plus proches que donne geocode_reverse. data_query prend une couche à la
fois. list_layers n'exige aucun argument et lit le catalogue, licence et lacunes connues
comprises : à appeler avant d'affirmer à un utilisateur qu'une couche le couvre, puisque
plusieurs ne couvrent qu'une province.
coordinate, near, from, to et center sont tous des paires [longitude, latitude].
categories et minutes sont des tableaux. mode vaut auto, car, bicycle, pedestrian ou
truck, et les gabarits de camion (height, width, length, weight, axle_load,
axle_count, hazmat, use_truck_route) ne s'appliquent que si mode vaut truck. Le schéma
JSON complet de chaque compétence est renvoyé par le tools/list du serveur MCP, sur une
connexion vivante ; /openapi.json nomme les compétences et
l'enveloppe qui les entoure. Le comportement sous-jacent est documenté sur les pages
API de géocodage et API d'itinéraires.
Quelques remarques sur ce qui figure ici et ce qui n'y figure pas :
- L'autocomplétion n'est pas une compétence. Elle sert à classer un préfixe à demi saisi pour
une personne qui regarde une liste déroulante. Un agent dispose déjà de la chaîne complète, et
geocode_searchest le point de terminaison réglé pour en tirer la meilleure réponse. - Les tuiles et les styles ne sont pas des compétences. Une tuile vectorielle et un document de style MapLibre sont destinés à un moteur de rendu, et ni l'un ni l'autre ne survit au passage dans un message A2A. La seule chose utile à renvoyer serait une URL de style contenant votre clé d'API, c'est-à-dire un identifiant à faire fuiter plutôt qu'une compétence à appeler. Si votre agent doit afficher une carte, construisez l'URL à partir de l'API de cartes.
Un appel A2A est facturé comme une requête, imputée au service que la compétence a réellement
utilisé : un geocode_search compte comme un géocodage, exactement comme GET /geocode/search et
exactement comme l'outil MCP. Un appel qui n'exécute aucune compétence coûte tout de même une
requête. Voir Forfaits et limites.
Erreurs
Il y a deux sortes d'échec, et elles arrivent différemment, à dessein.
Une compétence qui échoue revient comme un résultat réussi. Le Message porte l'échec dans sa
partie texte et positionne metadata.isError. C'est délibéré : une erreur JSON-RPC est invisible
pour un modèle, qui ne peut donc pas la lire et tenter autre chose, tandis qu'un résultat lisible
est quelque chose sur quoi il peut agir. « Aucun itinéraire entre ces points », « catégorie
inconnue » et « to must be [longitude, latitude] » arrivent tous ainsi, avec la formulation qu'ils
ont en MCP.
{
"jsonrpc": "2.0", "id": 1,
"result": { "message": {
"role": "ROLE_AGENT",
"parts": [{ "text": "to must be [longitude, latitude]", "mediaType": "text/plain" }],
"metadata": { "isError": true }
}}
}Une requête malformée est une erreur JSON-RPC, avec un HTTP 200, comme l'exige la
spécification. Les échecs de transport arrivent tels quels.
| Code | Signification |
|---|---|
-32700 | Le corps n'était pas du JSON valide. |
-32600 | Ce n'est pas un objet de requête JSON-RPC 2.0 unique. Les lots sont refusés. |
-32601 | Méthode inconnue. unmap met en œuvre SendMessage. |
-32602 | L'enveloppe n'a pas pu être lue comme un appel de compétence : aucun skill nommé, compétence inconnue, ou aucune partie exploitable. |
-32001 | Tâche introuvable. unmap ne crée aucune tâche. |
-32003 | Les notifications poussées ne sont pas prises en charge. |
-32004 | La diffusion en continu n'est pas prise en charge. |
-32007 | Aucune carte d'agent étendue n'est configurée. |
HTTP 401 | Clé absente ou refusée, avec un défi WWW-Authenticate. |
HTTP 429 | Limite de débit, quota ou plafond de dépenses, avec Retry-After lorsqu'attendre sert à quelque chose. |
HTTP 503 | Un service est encore en démarrage. Réessayable. |
L'authentification, la limitation de débit et les quotas sont traités au niveau du transport
plutôt qu'à l'intérieur d'un 200, car un défi enfoui dans un corps JSON-RPC est un défi sur
lequel votre client ne peut pas agir.
Dans le navigateur
Tout ce qui précède suppose un agent qui fait ses propres requêtes HTTP. Un agent qui pilote un navigateur (une extension, ou un assistant qui travaille dans l'onglet qu'une personne a sous les yeux) dispose d'une seconde possibilité : unmap.dev enregistre des outils WebMCP auprès du contexte de modèle du navigateur sur chaque page, afin que le site puisse être utilisé plutôt que moissonné.
| outil | ce qu'il fait |
|---|---|
search_unmap_docs | Recherche plein texte dans cette documentation. Retourne les sections classées avec leur URL et un extrait. |
read_unmap_page | N'importe quelle page d'unmap.dev en Markdown, les octets que retourne l'en-tête Accept ci-dessus. |
navigate_unmap_site | Ouvre une page du site dans l'onglet courant. |
list_unmap_map_styles | Les douze styles de fond de carte en clair et en sombre, avec la valeur flavor qui demande chacun. |
Aucun ne requiert de clé et aucun n'appelle l'API : la recherche s'exécute sur un index statique dans le navigateur, et les trois autres lisent des pages que le site sert déjà. Tout ce qui coûte un appel (un géocodage, un itinéraire, une tuile) en est délibérément absent ; c'est le rôle de la carte d'agent et des points de terminaison REST ci-dessus.
WebMCP est un brouillon, et l'API a occupé deux emplacements : l'aperçu anticipé de Chrome
l'expose sur navigator, tandis que la spécification la définit désormais sur Document. unmap
s'enregistre sur celui dont dispose le navigateur. Un navigateur qui n'a ni l'un ni l'autre n'est
pas affecté : rien n'est polyfillé et aucun global n'est modifié.
WebMCP est la référence de ces quatre outils : les arguments de chacun, ce qu'il renvoie et ce qu'il refuse.
Couverture
unmap couvre le Canada. Le corpus de géocodage regroupe des adresses et des lieux canadiens, et le graphe d'itinéraires s'arrête à la frontière : un trajet qui passe aux États-Unis n'a donc pas de réponse plutôt qu'une réponse partielle. Les noms sont portés en anglais, en français et, lorsque les données sources les contiennent, en langues autochtones sur la même fiche, et une requête écrite en syllabique trouve sa correspondance. La couverture des noms autochtones est une lacune d'approvisionnement en données et non du moteur : le corpus ne porte un nom en inuktitut que pour un nombre restreint de communautés.
Prochaines étapes
- Le serveur MCP expose les mêmes capacités via le Model Context Protocol.
- La référence des API pour chaque point de terminaison accessible à un agent.
- Erreurs pour ce que renvoie un appel d'outil en échec.