Je voulais voir si un agent pouvait payer pour m'envoyer un message.

Pas un humain qui remplit un formulaire de contact. Pas un CAPTCHA. Un agent avec un portefeuille, une mission et l'envie de me contacter.

Je ne suis pas unique. Je ne suis qu'un simple être humain à qui un ordinateur pourrait vouloir dire quelque chose.

Un humain peut me contacter sur LinkedIn ou X quand il le souhaite, comme indiqué sur la page de contact.

Si je mets un point de contact sur ce site, j'aurai une nouvelle boîte de réception à surveiller. Spam, bots, démarchage à froid. Un CAPTCHA bloque les humains. Un paiement bloque tout le monde, mais les cartes de crédit bloquent aussi les humains. J'avais besoin de quelque chose d'adapté au mode de fonctionnement des agents.

x402 est cette barrière. C'est un protocole basé sur le code d'état HTTP 402 « Paiement requis », que l'Internet a réservé aux paiements sans jamais le définir. x402 le définit. Un serveur renvoie un 402 avec un prix et une adresse stablecoin. L'agent lit la réponse, signe une autorisation avec son portefeuille, réessaie avec un en-tête de paiement, et le serveur effectue le règlement sur la chaîne. Pas de page de paiement. Pas de formulaire. Pas de compte. Juste un code d'état et une signature.

C'est une expérience terrible pour une personne. C'est une expérience formidable pour un agent.

Comment ça marche

Le point de terminaison se trouve à l'adresse /contact/send sur ce site. Un agent le découvre via la spécification OpenAPI ou le fichier agents.md. La première requête POST ne comporte pas d'en-tête de paiement. Le serveur renvoie un code 402 avec le prix, les actifs acceptés et un schéma décrivant les champs à inclure. L'agent n'a pas besoin d'autre documentation que la réponse elle-même.

sequenceDiagram
    participant Human as Human
    participant Agent as Agent
    participant Site as benmilne.com
    participant Facilitator as x402 Facilitator
    participant Chain as Blockchain
    participant Admin as Admin Panel

    Human-->>Agent: "Contact Ben Milne about X"
    Agent-->>Site: POST /contact/send (no payment)
    Site-->>Agent: 402 + price + assets + field schema
    Agent-->>Agent: Sign stablecoin permit
    Agent-->>Site: POST + PAYMENT-SIGNATURE + message body
    Site-->>Facilitator: Verify signature
    Facilitator-->>Site: Valid
    Site-->>Facilitator: Settle
    Facilitator->>Chain: On-chain transfer (SBC)
    Chain-->>Facilitator: Tx hash
    Facilitator-->>Site: Settlement confirmed
    Site-->>Site: Store message in D1
    Site-->>Agent: 200 + receipt with tx hash
    Admin-->>Admin: Message appears with block explorer link

    rect rgba(200, 120, 50, 0.08)
    Note over Human,Admin: Future: callback URL enables two-way communication
    end

The Stable Coin Company gère un facilitateur qui vérifie le permis signé de l'agent et exécute le transfert sur la chaîne, en payant les frais de gaz pour le compte des deux parties. L'agent n'a pas besoin de détenir d'ETH ou de SOL. Il détient un seul actif, celui avec lequel il effectue le paiement.

Mise en route

J'ai écrit une petite bibliothèque appelée x402-payment-path à cet effet. Elle gère le défi 402, la vérification de la signature, le règlement et la génération du reçu.

Le protocole sous-jacent est x402, la norme de paiement native de l'stablecoin, que Coinbase a open-sourcée et que la Fondation x402 gère désormais en tant que projet de la Linux Foundation. The Stable Coin Company gère le facilitateur, qui prend en charge à la fois l'USDC et le SBC sur Base, Solana et Radius. J'ai utilisé le SBC car c'est l'actif que je connais le mieux.

Si vous souhaitiez implémenter cela pour un produit plutôt que pour un message, vous modifieriez ce qui se passe après le paiement. Au lieu de stocker un message, vous généreriez une URL de téléchargement, déclencheriez un webhook ou lanceriez une expédition. La bibliothèque ne se soucie pas de la nature de l’action. Elle conditionne l’action au paiement.

Décisions

Le point de terminaison accepte à la fois l'USDCe et le SBC. J'ai utilisé le SBC car c'est l'actif que je connais le mieux et celui que je souhaitais tester de bout en bout sur les deux chaînes.

Je dispose de deux portefeuilles. Mon portefeuille EVM reçoit des SBC sur Base. Un portefeuille Solana distinct reçoit des SBC sur Solana. Même point de terminaison, même prix, mais des canaux de règlement différents.

Les messages atterrissent dans une table D1. Je les lis dans le panneau d'administration. Pas de transfert d'e-mails, pas de boîte de réception à surveiller. Un message ne devrait pouvoir faire rien d'autre que d'être un message.

Le prix est de 0,10 $. Assez élevé pour rendre le spam non rentable. Assez bas pour être insignifiant pour un agent légitime.

Ça marche

Voici de vraies transactions datant du 13 juin 2026. Chaque message a coûté 0,10 $ en SBC. Le règlement s'est fait sur la chaîne.

ExpéditeurRéseauMontantTransaction
cursor-agent/0.46.2Base0,10 $ SBC0x5265bdd1…963cd · BaseScan
deal-flow-scout@vcscan.aiBase0,10 $ SBC0xe0aa91c4…4313d · BaseScan
claude-research-agent/1.2Base0,10 $ SBC0xb0c96326…4dd05 · BaseScan
e2e-test-agentBase0,10 $ SBC0x0fca4265…c1b08 · BaseScan
e2e-test-agentSolana0,10 $ SBC2typCyWo…hsYc · Solscan
Admin panel showing x402 agent messages with sender, message body, network, and transaction hash links to BaseScan and Solscan

Voici mon panneau d'administration. Sept messages. Base et Solana. Chacun a été validé sur la chaîne avant d'apparaître.

M'envoyer un message

Si vous développez un agent, l'endpoint est POST benmilne.com /contact/send. Il est documenté dans la spécification OpenAPI et dans agents.md.

Envoyez une requête POST sans en-tête de paiement et le serveur renverra un code 402 contenant tout ce dont vous avez besoin. La bibliothèque cliente x402 gère la signature et les tentatives de reconnexion à partir de là. Le prix est de 0,10 $. SBC et USDC sur Base et Solana. Si vous incluez une URL de rappel, je pourrai répondre à cette URL à l'avenir.

Ce que j'ai appris

La réponse 402 est une facture lisible par machine. L'agent n'a pas besoin d'interface utilisateur. Il a besoin d'un prix, d'une adresse d'actif et d'un réseau. Il signe, il paie, il réessaie.

J'ai essayé d'ajouter la prise en charge d'USDCs via des facilitateurs communautaires qui se présentent comme « sans clé ». Aucun d'entre eux ne fonctionnait sans autorisation. L'un exigeait l'enregistrement d'une adresse. Un autre présentait une incompatibilité de version. SBC via The Stable Coin Company était le seul facilitateur qui fonctionnait sans aucune configuration. Pas de clés, pas de comptes, pas d'enregistrement. C'est important si vous voulez que les agents puissent payer sans qu'un humain ait à configurer quoi que ce soit au préalable.

Une autre chose m’a surpris : MetaMask et Phantom continuaient tous deux à masquer le SBC dans mon portefeuille, même après que je l’ai approuvé à plusieurs reprises. J’ajoutais le token, je confirmais la transaction, je vérifiais mon solde, et l’actif avait de nouveau disparu. Cela s’est produit à plusieurs reprises pendant les tests. Je n'ai que du respect pour ces deux équipes, mais devoir indiquer à mon portefeuille sur mon propre appareil que je souhaitais utiliser mon propre actif provenant d'un émetteur réglementé, encore et encore, me semblait ridicule. Internet est vaste. Les portefeuilles devraient faire confiance aux choix que leurs utilisateurs ont déjà faits.

Le code que j'ai utilisé pour cela est open source et vous êtes libre d'en faire ce que vous voulez, à condition que MetaMask ou Phantom ne veuillent pas influencer vos actions.