Visa Trusted Agent Protocol : exploration du repo de référence
Guide complet et sourcé du Trusted Agent Protocol (TAP) de Visa : contexte du commerce agentique, RFC 9421 et Web Bot Auth, lecture de la spec officielle, anatomie du repo de démonstration, comment le lancer et le tester, ce qui manque pour une solution de production.
Conversation ayant produit cet article
Cet article fait suite à Juspay : orchestration de paiement et commerce agentique et à MCP un an après : registries, confiance et commerce agentique. Les articles précédents mentionnaient le Trusted Agent Protocol (TAP) de Visa dans le paysage des protocoles agentiques ; celui-ci descend dans le concret en explorant le repo de référence publié par Visa sur GitHub, cloné localement.
Quand un agent IA fait des achats pour le compte d’un humain, il ressemble à s’y méprendre à un bot malveillant : trafic automatisé, navigation programmatique, remplissage de formulaires à la chaîne. Or les marchands dépensent des fortunes pour bloquer exactement ce type de trafic. Le Trusted Agent Protocol (TAP), annoncé par Visa le 14 octobre 2025 et développé avec Cloudflare, propose une réponse : permettre à un agent de prouver cryptographiquement, à chaque requête HTTP, qu’il est un agent enregistré agissant pour un consommateur — et permettre au marchand de le distinguer d’un scraper. [Source : Visa Newsroom — Visa Unveils Trusted Agent Protocol]
Visa publie sur GitHub un repo d’exemple, visa/trusted-agent-protocol. Cet article l’explore de fond en comble pour répondre à des questions concrètes : à quoi sert ce repo, pour qui, où vit la spec officielle et que couvre-t-elle de plus, comment lancer et tester la démo, que faudrait-il implémenter pour une solution complète, et quel est son rapport exact avec Web Bot Auth.
1. Le contexte : l’agent IA est indistinguable d’un bot
Le problème que TAP attaque est un conflit frontal entre deux tendances :
- Le trafic d’agents explose. Visa cite une croissance de 4 700 % du trafic retail piloté par IA sur un an dans son annonce d’octobre 2025 [Source : Visa Newsroom]. Un article précédent de ce blog documentait cette bascule côté éditeurs de sites : Impact des chatbots IA sur le trafic des sites web.
- Les défenses anti-bot ne savent pas faire le tri. Les méthodes classiques d’identification — allowlists d’adresses IP, chaînes
User-Agent, clés d’API partagées — sont soit falsifiables (n’importe qui peut envoyer leUser-Agentde ChatGPT), soit ingérables à l’échelle (les plages d’IP changent). C’est le constat de départ du draft IETF Web Bot Auth. [Source : draft-meunier-web-bot-auth-architecture]
Résultat : un marchand qui bloque tout le trafic automatisé bloque aussi les agents d’achat légitimes — et perd les ventes correspondantes. Un marchand qui laisse tout passer s’expose au scraping, au carding et à la fraude. Il faut un mécanisme d’identification cryptographique, pas heuristique.
Trois briques s’empilent pour y répondre, et il est important de les distinguer d’emblée :
┌─────────────────────────────────────────────────────────┐
│ TAP (Visa, oct. 2025) │
│ intent d'achat, reconnaissance consommateur, paiement │
├─────────────────────────────────────────────────────────┤
│ Web Bot Auth (draft IETF, Cloudflare) │
│ identification des clients HTTP automatisés │
├─────────────────────────────────────────────────────────┤
│ RFC 9421 — HTTP Message Signatures (IETF, févr. 2024) │
│ signature cryptographique de messages HTTP │
└─────────────────────────────────────────────────────────┘
2. Le socle : RFC 9421, HTTP Message Signatures
La RFC 9421 est une norme IETF (Proposed Standard, février 2024 ; auteurs A. Backman d’Amazon, J. Richer et M. Sporny) qui définit comment signer cryptographiquement des morceaux choisis d’un message HTTP — requête ou réponse — pour en garantir l’intégrité et l’authenticité de bout en bout. [Source : RFC 9421]
Le problème qu’elle résout
TLS (Transport Layer Security) ne protège que le tuyau, connexion par connexion. Dès qu’il y a des intermédiaires — CDN (Content Delivery Network), reverse proxys, gateways d’API — le chemin entre le client et l’application est composé de plusieurs connexions TLS indépendantes, et chaque intermédiaire peut transformer le message (ajouter des en-têtes, changer l’encodage). La RFC 9421 permet au destinataire final de vérifier que c’est bien tel client, détenteur de telle clé, qui a émis telle requête — même à travers ces intermédiaires. C’est exactement la propriété dont un marchand a besoin pour authentifier un agent IA derrière son CDN.
Le mécanisme
L’émetteur choisit les composants couverts par la signature : des en-têtes HTTP (en minuscules) et des composants dérivés préfixés par @ (@method, @authority, @path, @query, @status…). Ces composants sont canonicalisés en une chaîne ASCII appelée signature base (sérialisation « Structured Fields » de la RFC 8941), qui est ensuite signée. Deux en-têtes transportent le résultat :
Signature-Input: la liste des composants couverts, plus des paramètres de signature —created(timestamp UNIX),expires,keyid(identifiant de clé),nonce(valeur à usage unique),alg(algorithme) ettag(identifiant applicatif) ;Signature: la valeur cryptographique elle-même.
Exemple (simplifié) de ce que ça donne sur le fil :
GET /product/1 HTTP/1.1
Host: shop.example
Signature-Input: sig1=("@authority" "@path");created=1755500000;
expires=1755500480;keyid="primary-ed25519";alg="ed25519";
nonce="8b6c...";tag="agent-browser-auth"
Signature: sig1=:vGkV...base64...Qw==:
Le paramètre tag mérite une mention : il identifie l’application qui utilise la signature, et permet à un même serveur de router plusieurs usages de la RFC 9421. C’est ce paramètre que Web Bot Auth et TAP exploitent (respectivement web-bot-auth et les tags d’intent Visa, voir plus bas).
Les algorithmes enregistrés couvrent RSA-PSS/SHA-512, RSASSA-PKCS1-v1_5, ECDSA P-256/P-384, Ed25519 et HMAC-SHA-256. [Source : RFC 9421 §3.3]
La filiation
La RFC 9421 est une refonte complète — et incompatible — du vieux draft draft-cavage-http-signatures, jamais standardisé mais massivement déployé par le Fediverse : ActivityPub/Mastodon signait ses requêtes serveur-à-serveur avec le format Cavage, et a migré vers la RFC 9421 en versions 4.4 (vérification) puis 4.5 (émission par défaut). [Sources : oauth.net — HTTP Signatures, Mastodon PR #34814, SWICG — ActivityPub and HTTP Signatures] L’autre ancêtre spirituel cité par la RFC est AWS Signature Version 4, le mécanisme de signature des API AWS.
3. Web Bot Auth : identifier les clients automatisés
Web Bot Auth est une architecture proposée à l’IETF par Thibault Meunier (Cloudflare) qui applique la RFC 9421 à un problème précis : permettre à un client HTTP automatisé (crawler, agent IA) de s’identifier cryptographiquement auprès de n’importe quel serveur web, en remplacement des User-Agent falsifiables et des allowlists d’IP. [Source : draft-meunier-web-bot-auth-architecture]
Le principe : chaque requête du bot est signée par une clé privée détenue par son opérateur. Trois en-têtes entrent en jeu :
| En-tête | Rôle |
|---|---|
Signature-Input | Composants couverts + paramètres (created, expires, keyid, nonce, tag) |
Signature | La signature elle-même |
Signature-Agent | Optionnel : URL du répertoire de clés de l’opérateur |
Le draft impose de couvrir au minimum @authority (le host cible), exige created, expires, keyid et tag dans les paramètres, et fixe tag: web-bot-auth. Le keyid doit être l’empreinte JWK (JSON Web Key) SHA-256 de la clé publique. Le nonce sert d’anti-rejeu : le client doit garantir son unicité pendant la fenêtre de validité de la signature, le serveur choisit son niveau d’exigence. [Source : draft-meunier-web-bot-auth-architecture-05]
La découverte des clés publiques passe par un draft compagnon : le serveur qui veut vérifier une signature suit l’URL du header Signature-Agent (ou une liste publique connue) vers un endpoint bien connu, /.well-known/http-message-signatures-directory, qui sert un JWKS (JSON Web Key Set, RFC 7517) avec le type MIME application/http-message-signatures-directory+json. Les vérificateurs sont invités à mettre ce répertoire en cache et à le rafraîchir à expiration. [Source : draft-meunier-http-message-signatures-directory]
Point de vigilance sur le statut : Web Bot Auth reste un draft individuel, sans standing formel dans le processus IETF. La version 05 de l’architecture (mars 2026) est d’ailleurs marquée comme remplacée par draft-meunier-webbotauth-httpsig-protocol, et un groupe de travail « Web Bot Auth » discute ces documents. C’est un standard en formation, pas un standard. [Source : datatracker IETF]
Côté déploiement, Cloudflare vérifie ces signatures en périphérie et prévoit des managed rulesets permettant aux marchands d’allowlister les agents vérifiés sans modifier leur infrastructure ; American Express a également annoncé adopter Web Bot Auth. [Source : Cloudflare Blog — Securing agentic commerce]
Précision de vocabulaire, car le terme revient dans toute la communication Cloudflare : un managed ruleset est un ensemble de règles de sécurité (WAF — Web Application Firewall —, bot management) écrit, maintenu et mis à jour par Cloudflare, que le client active en un clic sur sa zone au lieu d’écrire ses propres règles — c’est le même mécanisme que le « Cloudflare Managed Ruleset » ou le ruleset OWASP du WAF, personnalisable par overrides et exceptions. [Source : Cloudflare Docs — WAF Managed Rules] Appliqué aux agents : Cloudflare tient un annuaire d’agents enregistrés (les signed agents, devenus « verified agents » en juillet 2026, vérifiés par Web Bot Auth), et les règles managées permettent au marchand d’exprimer « autoriser les agents vérifiés, bloquer le reste du trafic automatisé » comme une politique déclarative, sans implémenter lui-même la vérification RFC 9421. [Sources : Cloudflare Docs — Signed agents, Cloudflare Blog — Signed agents]
4. TAP : ce que Visa ajoute par-dessus
Web Bot Auth répond à « qui est ce client automatisé ? ». TAP répond à une question plus riche, spécifique au commerce : « cet agent est-il de confiance, que vient-il faire (naviguer ou payer), et pour quel consommateur ? ». Visa présente TAP comme bâti sur HTTP Message Signatures et « aligné avec Web Bot Auth », co-développé avec Cloudflare, avec au lancement plus de dix partenaires paiement : Adyen, Ant International, Checkout.com, Coinbase, CyberSource, Elavon, Fiserv, Microsoft, Nuvei, Shopify, Stripe, Worldpay. [Source : Visa Newsroom, 14 octobre 2025]
TAP structure trois catégories d’information vérifiable transmises de l’agent au marchand :
- Agent Intent : le signal qu’un agent de confiance vient consulter des produits ou effectuer un achat. Concrètement, c’est le paramètre
tagde la RFC 9421 qui le porte :agent-browser-authpour la navigation,agent-payer-authpour le paiement (on retrouve ces valeurs exactes dans le code du repo, voir §8). - Consumer Recognition : des identifiants permettant au marchand de reconnaître un client existant — tokens de fidélité, identifiants d’appareil, e-mails, téléphones, et PAR (Payment Account Reference, l’identifiant EMVCo qui représente un compte de paiement indépendamment de ses tokens) pour les cartes enregistrées.
- Payment Information : optionnellement, des données de paiement pour le mode de checkout préféré.
[Sources : Visa Developer — Trusted Agent Protocol overview, Visa Newsroom]
Les signatures TAP sont décrites comme spécifiques au marchand, liées à un usage (purpose-bound) et limitées dans le temps, pour empêcher rejeu et relais. La spec elle-même est distribuée via le Visa Developer Center — le produit y est marqué « in the process of development and deployment » — et la section suivante la détaille. [Source : Visa Developer]
Côté calendrier : Visa annonçait en décembre 2025 avoir complété des centaines de transactions initiées par des agents avec ses partenaires, positionnant 2026 comme l’année du passage à l’échelle, avec des pilotes en Asie-Pacifique et en Europe début 2026 ; en juillet 2026, Cleverbridge annonçait des transactions agentiques de bout en bout via TAP et l’annuaire d’agents Visa. [Sources : Visa Newsroom, décembre 2025, communiqué Cleverbridge, juillet 2026]
5. La spec officielle : sur le Visa Developer Center, pas sur GitHub
Précision utile, car la confusion est fréquente (et entretenue par des articles tiers qui affirment que « la spec est publiée sur GitHub ») : le repo GitHub ne contient pas la spécification. Il ne contient que l’implémentation d’exemple — aucun document normatif, aucun JSON Schema, six commits d’octobre 2025. La spécification de référence, elle, vit sur le Visa Developer Center : Trusted Agent Protocol Specifications (spécifications marchands, complétées par un guide d’implémentation client pour les agents). Les deux artefacts se complètent : la page Visa Developer dit quoi implémenter, le repo GitHub montre à quoi ça ressemble en code — mais le repo ne couvre qu’une partie de la spec, comme on va le voir.
Ce que la spec marchande définit, concrètement :
La vérification de la signature de message, en sept étapes : contrôle du tag (agent-browser-auth ou agent-payer-auth), présence des champs requis (@authority, @path, created, expires, keyid, alg, nonce, tag), validation des timestamps (fenêtre created/expires de 8 minutes maximum), déduplication du nonce sur les 8 dernières minutes, récupération de la clé publique, reconstruction de la base de signature canonique, vérification cryptographique. Toute modification de la requête (en-tête, chemin) invalide la signature. Algorithmes admis : Ed25519, PS256, ES256.
La distribution des clés publiques : point important que le repo ne montre pas, les clés publiques des agents s’obtiennent en production via un JWKS hébergé par Visa à https://mcp.visa.com/.well-known/jwks (avec filtrage optionnel par keyID). C’est donc bien le mécanisme « well-known + JWKS » de la famille Web Bot Auth — mais sur le domaine de Visa, pas sur celui de chaque opérateur d’agent : l’annuaire centralisé subsiste, seul le format de publication est standard.
Deux objets JSON signés dans le corps de requête, qui portent les couches 2 et 3 du protocole :
- L’Agentic Consumer Recognition Object (phases navigation et paiement) :
nonce(identique à celui de la signature de message — c’est le mécanisme de liage entre les objets),idToken,contextualData,kid,alg,signature. L’idTokenest un JWT (RFC 7519, aligné OpenID Connect) émis par le réseau de paiement (Visa typiquement), portant des claims obfusqués (email,phone_number, avec leurs masques) qui permettent au marchand de reconnaître un client existant sans recevoir ses identifiants en clair.contextualDatatransportecountryCode,zip,ipAddress,deviceData. - L’Agentic Payment Container (phase checkout) :
nonce,kid,alg,signature, plus un contenu variable selon le mode de paiement — unpaymentCredentialsHash(hash PAN + expiration + cryptogramme, pour le checkout invité), ou unpayloadchiffré avec la clé publique du marchand (token de paiement, adresses, contact), avec métadonnées de carte (lastFour,paymentAccountReference…), ou encore unbrowsingIOU— une reconnaissance de dette signée (invoiceId,amount,uri,sequenceCounter…) utilisée quand le marchand réclame un paiement via un code HTTP 402, ce qui éclaire d’ailleurs les endpoints x402 expérimentaux trouvés dans le backend de la démo (voir §11).
Les trois signatures (message, consumer recognition, payment container) utilisent la même paire de clés, et le nonce partagé les lie cryptographiquement à une même requête. [Source : Visa Developer — TAP Specifications]
À retenir pour la suite de l’exploration : le repo GitHub n’implémente que la première de ces trois couches (la signature de message). Les deux objets JSON — toute la partie reconnaissance consommateur et paiement, cœur de la proposition de valeur de TAP — n’existent que dans la spec.
6. Le repo : à quoi il sert, pour qui
Premier constat, essentiel pour calibrer ses attentes : visa/trusted-agent-protocol n’est ni la spec, ni une bibliothèque. C’est une maquette de démonstration — cinq services qui simulent un écosystème TAP complet en local, pour comprendre le protocole en le voyant tourner. La licence n’est d’ailleurs pas une licence open source classique : le LICENSE.md renvoie aux conditions d’utilisation du Visa Developer Center et aux « Trusted Agent Protocol Product Terms », même si les fichiers sources portent un en-tête de type MIT © 2025 Visa.
Les cinq composants :
| Composant | Dossier | Stack | Rôle |
|---|---|---|---|
| TAP Agent | tap-agent/ | Python, Streamlit, Playwright | Signe les requêtes (RFC 9421) et pilote un vrai Chromium sur le site marchand |
| CDN Proxy | cdn-proxy/ | Node, Express, http-proxy-middleware | « Edge/CDN du marchand » : vérifie les signatures puis proxifie |
| Agent Registry | agent-registry/ | Python, FastAPI, SQLite | Simule l’« annuaire d’agents Visa » : stocke agents et clés publiques |
| Merchant Backend | merchant-backend/ | Python, FastAPI, SQLite | API produits/panier/commandes du marchand |
| Merchant Frontend | merchant-frontend/ | React 19, Vite | Boutique de démonstration (aucun code TAP) |
Pour qui ? Trois profils y trouvent leur compte :
- Les équipes marchands / PSP (Payment Service Provider, prestataire de services de paiement) qui veulent comprendre ce que TAP impliquerait chez eux : le composant à étudier est le
cdn-proxy, qui montre la logique de vérification complète (parsing des en-têtes, récupération de clé, contrôles de fraîcheur et de rejeu, vérification Ed25519/RSA-PSS). - Les développeurs d’agents qui doivent produire des signatures conformes :
tap-agent/agent_app.pymontre la construction exacte de la signature base et des en-têtes. - Les curieux du commerce agentique qui veulent une vue d’ensemble exécutable du protocole avant de lire les guides d’implémentation du Visa Developer Center.
Dans quels cas l’utiliser ? Comme matériel pédagogique et banc d’essai : vérifier sa compréhension du protocole, prototyper une intégration, tester son propre code de signature contre le vérificateur de référence (ou l’inverse). Pas comme base de code de production — la section 11 détaille pourquoi.
7. Le flux de bout en bout
Voici le flux implémenté par la démo :
┌───────────────┐ 1. requête signée ┌──────────────┐
│ TAP Agent │ Signature-Input + Signature │ CDN Proxy │
│ (Streamlit + │──────────────────────────────▶│ (Express, │
│ Playwright) │ │ port 3001) │
└───────────────┘ └──────┬───────┘
│ 2. GET /keys/{keyId}
▼
┌──────────────┐
│ Agent │
│ Registry │
│ (port 9002) │
└──────┬───────┘
│ 3. clé publique
▼
4. vérifie : clé active, created/expires,
nonce jamais vu, signature Ed25519/RSA-PSS
│
OK ────────┼──────── KO
▼ ▼
┌──────────────┐ page HTML 403
│ Frontend │ « Bot Traffic
│ (3000) / │ Detected »
│ Backend │
│ (8000) │
└──────────────┘
- L’agent construit la signature base sur
@authorityet@path, la signe, et injecteSignature-InputetSignaturecomme en-têtes supplémentaires du contexte Playwright — chaque requête du navigateur piloté les porte donc. - Le proxy extrait le
keyIddeSignature-Inputet interroge le registre (GET /keys/{keyId}), qui renvoie la clé publique, l’algorithme et le statut d’activation. - Le proxy contrôle : clé active,
createdpas plus de 60 s dans le futur,expiresnon dépassé,nonceprésent et jamais vu (cache anti-rejeu en mémoire, TTL 1 h), puis reconstruit la base de signature à partir de la requête reçue et vérifie la signature. - En cas de succès, la requête est transmise telle quelle au frontend ou au backend ; en cas d’échec, une page HTML 403 explicite l’erreur (« 🤖 Bot Traffic Detected », « 🚫 Replay Attack Detected », « Signature Expired »…).
Un détail révélateur : le diagramme de flux du README (assets/trusted-agent-protocol-flow.png) décrit une seconde phase — la soumission du checkout avec Payment Signature, hash de token et données de formulaire chiffrées, vérifiés par le CDN avant transmission au marchand. Cette moitié « paiement » du protocole n’est implémentée nulle part dans le repo. Le checkout de la démo est un simple formulaire React rempli par Playwright avec une carte de test (4111 1111 1111 1111), validé par un contrôle de Luhn côté backend. La partie Consumer Recognition (PAR, tokens de fidélité) n’existe elle aussi que dans une phrase du README — les deux étant pourtant spécifiées en détail côté Visa Developer (voir §5).
8. La crypto en détail
La base de signature
Les deux côtés (agent et proxy) construisent la même chaîne, conforme à l’esprit RFC 9421 :
"@authority": localhost:3001
"@path": /product/1
"@signature-params": ("@authority" "@path");created=1755500000;expires=1755500480;keyId="primary-ed25519";alg="ed25519";nonce="<uuid4>";tag="agent-browser-auth"
Seuls @authority et @path sont couverts : ni la méthode, ni la query string, ni le corps (pas de Content-Digest). C’est le minimum exigé par Web Bot Auth (@authority), mais un vérificateur de production voudrait en couvrir davantage.
Deux écarts avec la RFC 9421 stricte sont à noter si on veut interopérer avec ce code : le label de signature est codé en dur sig2 (le proxy exige littéralement sig2=( dans Signature-Input), et le paramètre s’écrit keyId en camelCase là où la RFC définit keyid en minuscules. Un client conforme à la lettre de la RFC ne passerait donc pas la vérification de cette démo telle quelle.
Algorithmes et formats de clés
| Aspect | Ed25519 (défaut) | RSA-PSS-SHA256 |
|---|---|---|
| Clé privée (agent) | 32 octets bruts, en base64, via variable d’env | PEM PKCS#8 |
| Clé publique (registre) | 32 octets bruts en base64 ; le proxy la ré-encapsule en DER SPKI | PEM SPKI |
| Signature | 64 octets exigés | PSS, salt maximal |
Pas de JWKS, pas d’ECDSA : les clés sont des chaînes stockées telles quelles dans SQLite, validées à l’enregistrement (32 octets exacts pour Ed25519, en-têtes -----BEGIN/END PUBLIC KEY----- pour RSA).
Anti-rejeu et fraîcheur
L’agent fixe expires = created + 8 minutes et tire un nonce UUID v4 par signature. Le proxy rejette : created à plus de 60 s dans le futur, signature expirée, nonce absent, nonce déjà vu (cache mémoire, TTL 1 h, purge toutes les 60 s). Rejouer une requête capturée produit la page « 🚫 Replay Attack Detected » — c’est un des tests les plus parlants de la démo.
Les tags d’intent
Le sélecteur d’action de l’agent bascule le tag : agent-browser-auth pour consulter une fiche produit, agent-payer-auth pour dérouler le checkout complet (un commentaire du proxy mentionne aussi un troisième tag agent-payment-auth, non utilisé). Limite notable de la démo : le proxy parse le tag mais ne l’applique pas — il le logge, sans politique différenciée entre navigation et paiement. L’« Agent Intent » du marketing est donc présent dans les octets, mais aucune décision n’en découle dans ce code.
9. Le registre d’agents
Le composant agent-registry simule l’annuaire central que Visa opère en production (le « Visa Agent Directory »). Son modèle de données : des agents (nom, domaine unique, contact, statut d’activation) possédant chacun plusieurs agent_keys (key_id, clé publique, algorithme, statut) — ce qui permet rotation de clés et multi-algorithmes par agent.
Les endpoints utiles :
# Enregistrer un agent avec ses clés (upsert par domaine)
curl -X POST http://localhost:9002/agents/register -H 'Content-Type: application/json' -d '{
"name": "Mon agent", "domain": "agent.example.com",
"keys": [{"key_id": "primary-ed25519", "algorithm": "ed25519",
"public_key": "<base64 32 octets>"}]
}'
# Ce que le CDN proxy appelle à chaque vérification
curl http://localhost:9002/keys/primary-ed25519
Le seul consommateur du registre est le cdn-proxy ; le backend marchand ne l’appelle jamais. Et deux caractéristiques rappellent qu’on est dans une démo : l’enregistrement est totalement ouvert (aucune authentification, CORS *, aucune preuve de possession de la clé privée au moment d’enregistrer une clé publique), et le port réel est 9002 — codé en dur dans main.py — alors que les README parlent selon les pages de 8001, 8080 ou 9000. En production, ce composant est remplacé par l’annuaire opéré par Visa, où l’enregistrement passe par un onboarding avec vérification d’identité de l’opérateur d’agent. [Source : Visa Developer]
10. Lancer et tester la démo
Prérequis et pièges de ports
Python ≥ 3.8, Node, et ~1 Go pour le Chromium de Playwright. Attention : les README du repo se contredisent sur les ports. Voici ce que le code fait réellement :
| Service | Commande | Port réel |
|---|---|---|
| Agent Registry | cd agent-registry && pip install -r requirements.txt && python main.py | 9002 |
| Merchant Backend | cd merchant-backend && pip install -r requirements.txt && python -m uvicorn app.main:app --reload --port 8000 | 8000 |
| Merchant Frontend | cd merchant-frontend && npm install && npm run dev | 3000 |
| CDN Proxy | cd cdn-proxy && npm install && npm start | 3001 |
| TAP Agent | cd tap-agent && pip install -r requirements.txt && playwright install && streamlit run agent_app.py | 8501 |
Ordre de démarrage recommandé : registre → données d’exemple → backend → frontend → proxy → agent.
Générer et enregistrer les clés
Le tap-agent exige quatre variables dans son .env (copier .env.example) : RSA_PRIVATE_KEY, RSA_PUBLIC_KEY, ED25519_PRIVATE_KEY, ED25519_PUBLIC_KEY — l’app refuse de démarrer sans les clés RSA. Génération :
# RSA
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# Ed25519 : clés brutes de 32 octets en base64 (pas du PEM)
python - <<'EOF'
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
import base64
priv = ed25519.Ed25519PrivateKey.generate()
raw_priv = priv.private_bytes(serialization.Encoding.Raw,
serialization.PrivateFormat.Raw, serialization.NoEncryption())
raw_pub = priv.public_key().public_bytes(serialization.Encoding.Raw,
serialization.PublicFormat.Raw)
print("ED25519_PRIVATE_KEY=", base64.b64encode(raw_priv).decode())
print("ED25519_PUBLIC_KEY=", base64.b64encode(raw_pub).decode())
EOF
Ensuite, deux options : soit lancer python populate_sample_data.py dans agent-registry/ (qui enregistre deux agents d’exemple) puis remplacer les clés publiques d’exemple par les vôtres via l’API, soit enregistrer directement votre agent avec vos clés via POST /agents/register. Le point critique : la clé publique stockée dans le registre sous le key_id utilisé par l’agent (primary-ed25519 ou primary) doit correspondre à votre clé privée, sinon toute vérification échoue. Les bases SQLite committées dans le repo contiennent déjà des données d’exemple — avec les clés publiques des exemples, donc inutilisables avec vos clés privées.
Le scénario de test
Dans l’interface Streamlit de l’agent (http://localhost:8501) :
- Agent Id
1, Merchant URLhttp://localhost:3001/product/1— le port du proxy, pas celui de Vite : c’est le proxy qui vérifie, aller sur le port 3000 court-circuiterait TAP. - Choisir l’algorithme (
ed25519→ keyIdprimary-ed25519, oursa-pss-sha256→ keyIdprimary). - Choisir l’action : Product Details (tag
agent-browser-auth, scrape le titre et le prix) ou Checkout (tagagent-payer-auth, déroule produit → panier → checkout → remplit ~25 champs → soumet → extrait le numéro de commande). - Lancer : un Chromium s’ouvre et exécute le parcours sous vos yeux.
Et les tests négatifs, les plus instructifs :
- Navigateur normal sur
http://localhost:3001/product/1→ page « Signature Required » / « 🤖 Bot Traffic Detected » : sans signature, pas d’accès aux fiches produit. - Rejeu de la même requête signée (curl avec les mêmes en-têtes) → « 🚫 Replay Attack Detected ».
- Signature expirée (attendre 8 minutes et rejouer avec un nonce neuf) → « Signature Expired ».
Les API exposent leur documentation interactive : http://localhost:8000/docs (marchand) et http://localhost:9002/docs (registre).
11. Ce qui manque pour une solution complète
C’est la question la plus importante pour qui envisage TAP sérieusement. L’exploration du code révèle l’écart entre la démo et un déploiement réel — liste des chantiers, du plus structurel au plus anecdotique.
Côté protocole
- Toute la couche paiement du protocole est absente. Le diagramme du README promet Payment Signature, hash de token et données chiffrées au moment du checkout ; rien de tout cela n’est codé. De même pour la Consumer Recognition (PAR, identifiants de fidélité). Ces parties sont spécifiées — l’Agentic Consumer Recognition Object et l’Agentic Payment Container de la spec Visa Developer, voir §5 — mais le repo GitHub ne montre que la couche « identification d’agent » ; il faut implémenter les deux objets JSON soi-même à partir de la spec.
- L’intent n’est pas appliqué. Le proxy logge le
tagsans en tirer de politique. Une vraie intégration doit décider ce qu’unagent-browser-autha le droit de faire (lire le catalogue) versus unagent-payer-auth(atteindre le checkout). - Le périmètre protégé est minuscule : seules les routes
/product/*exigent une signature ; panier, checkout, commandes et toute l’API passent sans vérification. En l’état, le tag « payer » ne débloque littéralement rien de plus.
Côté infrastructure de vérification
- Le cache anti-rejeu est en mémoire locale : sur un vrai CDN multi-nœuds, un nonce accepté par un nœud serait accepté par tous les autres. Il faut un stockage partagé (Redis…) ou un partitionnement par fenêtre temporelle.
- Le cache de clés a un TTL de… 5 millisecondes (le commentaire du code dit bien « 5 ms »), soit un aller-retour au registre par requête. Un déploiement réel cache les clés minutes ou heures, avec invalidation à la rotation.
- Le rate limiting est écrit mais désactivé (« TEMPORARILY DISABLED FOR DEBUGGING »).
- Rien n’est transmis en aval : le proxy ne propage aucun résultat de vérification au backend, alors même que ce backend contient du code qui fait confiance à des en-têtes
x-signature-verified/x-agent-data… que n’importe quel client pourrait forger s’il atteint le backend directement. Une intégration réelle doit soit propager un jeton signé, soit garantir que le backend n’est joignable que via le proxy.
Côté registre
- Aucune authentification à l’enregistrement, aucune preuve de possession de la clé privée. Le modèle de production TAP repose sur l’onboarding Visa (vérification d’identité de l’opérateur) — c’est le cœur du modèle de confiance, et il est entièrement hors du repo.
- Pas de JWKS ni de
/.well-known/http-message-signatures-directory: la découverte de clés est un REST maison, non interopérable avec l’écosystème Web Bot Auth.
Côté qualité de code (si on voulait s’en servir de base — à ne pas faire)
Deux dialectes de signature incompatibles coexistent (le couple agent/proxy en sig2/keyId, un vérificateur mort dans le backend en sig1/keyid avec Signature-Agent), des URL de services codées en dur ignorent les .env.example, un JWT est décodé sans vérification de signature, les bases SQLite sont committées avec leurs données, aucun test automatisé, pas de CI, pas de Dockerfile. Le repo contient même des endpoints x402 (paiement HTTP 402) qui dépendent d’un « Payment Facilitator » sur le port 8001… qui n’existe pas dans le repo.
12. Les dépendances externes : quasiment aucune
Réponse courte à la question « y a-t-il des dépendances à des composants externes ? » : non, et c’est une des surprises de l’exploration.
- Aucun LLM (Large Language Model). Le « TAP Agent » n’a rien d’un agent IA : c’est un générateur de signatures plus une automatisation Playwright scriptée (sélecteurs CSS et regex codés en dur pour scraper la boutique de démo). Aucune clé OpenAI/Anthropic, aucun serveur MCP (Model Context Protocol).
- Aucun service Visa. L’« annuaire Visa » est émulé localement par le composant
agent-registry. La démo tourne intégralement hors ligne, aux deux exceptions près : le téléchargement de Chromium par Playwright, et des URL d’images Unsplash dans les données produits d’exemple. - Dépendances logicielles classiques uniquement :
cryptography, Streamlit et Playwright côté Python ; Express,http-proxy-middlewareet le modulecryptonatif de Node côté proxy ; FastAPI/SQLAlchemy pour les API ; React 19/Vite pour le front.
En production, en revanche, la dépendance externe est structurelle : l’annuaire d’agents est opéré par Visa, et l’enregistrement d’un agent passe par les processus d’onboarding de Visa. C’est un choix assumé — rotation et révocation de clés rapides, entrée contrôlée — mais qui place Visa en tiers de confiance central du dispositif (voir §14).
13. TAP et Web Bot Auth : le rapport exact
C’est la question la plus subtile, car la communication officielle (« aligné avec Web Bot Auth ») et le code racontent deux histoires légèrement différentes.
Ce qui est vrai : TAP et Web Bot Auth appartiennent à la même famille technique. Mêmes fondations (RFC 9421), mêmes en-têtes Signature/Signature-Input, même logique de paramètres (created, expires, keyid, nonce, tag), même idée d’un répertoire de clés publiques consultable par le vérificateur. Cloudflare — auteur de Web Bot Auth — est le partenaire technique de TAP, et présente explicitement TAP (et le Agent Pay de Mastercard) comme bâtis sur Web Bot Auth, avec les clés publiques des agents hébergées dans des annuaires opérés par les réseaux de cartes. [Source : Cloudflare Blog]
Ce que le code nuance : le repo de démonstration ne référence Web Bot Auth nulle part — aucune mention du draft dans le code ni les README — et diverge sur les points d’interopérabilité concrets :
| Aspect | Web Bot Auth (draft IETF) | Repo TAP |
|---|---|---|
tag | web-bot-auth (fixe) | agent-browser-auth / agent-payer-auth (l’intent est dans le tag) |
keyid | Empreinte JWK SHA-256 de la clé | Identifiant arbitraire (primary-ed25519), paramètre écrit keyId |
| Découverte des clés | Signature-Agent → /.well-known/http-message-signatures-directory (JWKS) | Démo : GET /keys/{keyId} sur un registre REST maison ; production : JWKS sur https://mcp.visa.com/.well-known/jwks (voir §5) |
| Modèle de confiance | L’opérateur du bot publie ses clés sur son propre domaine | Annuaire centralisé (Visa en production) |
La lecture juste est donc : Web Bot Auth fournit la couche « identification d’agent », TAP en est une déclinaison commerciale qui remplace la découverte décentralisée des clés par un annuaire opéré par Visa, et enrichit le tag pour porter l’intent d’achat — puis ajoute au-dessus les couches consumer recognition et paiement, absentes de Web Bot Auth (et du repo). Un agent qui implémente Web Bot Auth a fait 80 % du chemin technique vers TAP ; il lui reste l’enregistrement dans l’annuaire Visa et les tags d’intent, et, à terme, les payloads de paiement.
14. Le paysage : où TAP se situe
TAP n’est qu’une pièce de la ruée vers le commerce agentique de 2025-2026. Pour situer (le tableau complet est dans l’article Juspay) :
| Protocole | Porteur | Couche |
|---|---|---|
| TAP | Visa + Cloudflare | Identification de l’agent auprès du marchand (couche transport HTTP) |
| Verifiable Intent / Agent Pay | Mastercard | Équivalent Mastercard, également sur Web Bot Auth [Source : Cloudflare] |
| ACP (Agentic Commerce Protocol) | OpenAI + Stripe | Flux de checkout structuré entre agent et marchand |
| AP2 (Agent Payments Protocol) | Google + 60 partenaires | Mandats vérifiables : preuve que l’humain a autorisé cet achat [Source : Google Cloud] |
| x402 | Coinbase | Règlement machine-à-machine via HTTP 402 (stablecoins) |
Ces couches sont plus complémentaires que concurrentes : ACP décrit comment un agent achète, AP2 prouve que l’humain l’a voulu, TAP prouve qui est l’agent au niveau de chaque requête HTTP. Visa cite d’ailleurs explicitement la complémentarité avec ACP et x402, et promet une coordination avec l’IETF, EMVCo et l’OpenID Foundation. [Source : Visa Newsroom]
Restent deux limites à garder en tête :
- La centralisation. Là où Web Bot Auth laisse chaque opérateur publier ses clés sur son domaine, TAP fait de l’annuaire Visa le point de passage obligé : c’est Visa qui décide qui est un « agent de confiance ». Le gain (révocation rapide, onboarding vérifié) a pour contrepartie un modèle où le réseau de cartes s’installe comme tiers de confiance de tout le trafic agentique, y compris la simple navigation. Si les agents deviennent le canal d’achat dominant, celui qui tient l’annuaire tient le marché — c’est une opinion, mais elle éclaire l’empressement des réseaux.
- L’authentification n’est pas l’anti-fraude. Savoir qui est l’agent ne dit ni si le porteur de carte a autorisé cet achat précis (c’est le rôle des mandats AP2 ou de la SCA — Strong Customer Authentication — européenne, voir l’article Juspay), ni si la transaction est frauduleuse (scoring, vélocité, anomalies restent nécessaires). TAP réduit le problème « bot ou agent ? », pas le problème « fraude ou pas ? ».
15. Conclusion
Le repo visa/trusted-agent-protocol est exactement ce qu’il faut en attendre, ni plus ni moins : une démo pédagogique soignée de la couche « identification d’agent » de TAP, qui se lance en local en six commandes et rend concrets la RFC 9421, les en-têtes Signature/Signature-Input, les tags d’intent et l’anti-rejeu par nonce. Ses tests négatifs (navigateur bloqué, rejeu détecté) valent mieux que bien des slides.
Il faut en revanche savoir ce qu’on n’y trouvera pas : la couche paiement et la reconnaissance consommateur (spécifiées sur le Visa Developer Center uniquement, voir §5), l’annuaire de production (le JWKS opéré par Visa sur mcp.visa.com), l’interopérabilité stricte avec Web Bot Auth (dialecte maison : keyId, label sig2, registre REST au lieu de JWKS bien connu), et la robustesse de production (anti-rejeu mono-nœud, registre ouvert, périmètre protégé réduit aux fiches produit). Pour un marchand ou un PSP, le bon usage est de lire cdn-proxy/server.js comme un cahier des charges de vérification, puis d’attendre les briques industrielles — les managed rulesets Cloudflare notamment — plutôt que de durcir cette maquette.
Sur le fond, la direction est claire : l’identification cryptographique des agents au niveau HTTP est en train de devenir le socle commun (Web Bot Auth à l’IETF, TAP chez Visa, Agent Pay chez Mastercard, Web Bot Auth chez American Express), et la vraie bataille se joue une couche au-dessus — qui tiendra les annuaires de confiance, et comment s’articuleront preuve d’identité de l’agent (TAP) et preuve de mandat de l’humain (AP2).