Reproductibilité

docs.stripe.com · audité le 2026-07-27 · AgentFit v3.4.0 · rubrique v4 · Claude Opus 5

Une note que l'on ne peut pas reproduire n'est pas une mesure. Voici donc le test que nous vous devons : nous avons audité le même site six fois en une journée — trois fois en demandant à un modèle de langage d'appliquer une grille de documentation, trois fois en lançant AgentFit — et nous publions ce que nous avons enregistré, y compris ce qui nous dérange.

Demander à un modèle · 3 exécutions

78 · 80 · 65 15 points d'écart

Trois agents indépendants, le même prompt public, le même modèle, le même jour. Aucun ne savait rien des autres, ni de la raison pour laquelle on l'interrogeait.

Lancer AgentFit · 3 exécutions

57 · 57 · 57 0 points d'écart eabbb2f6abcdea473b600dc4ee8e25282fd002344f1e8425519caa32ff858b01 un seul sha256, trois fichiers

Trois audits en direct à la suite, trois fichiers JSON, une seule somme de contrôle. Pas de cache : chaque exécution est repartie interroger le site.

Lisez les colonnes de haut en bas, pas en travers. La grille de gauche compte 26 critères, AgentFit en compte 28, et les pondérations diffèrent : une spécification lisible par une machine vaut 25 points à gauche et 17 ici. 57 n'est pas « la bonne réponse » et 78 n'est pas « faux ». L'affirmation de cette page est plus étroite, et c'est la seule que les données soutiennent : l'une de ces deux procédures rend le même nombre à chaque fois, l'autre non.


Là où les exécutions ont divergé

Les trois exécutions du modèle ont fait le travail sérieusement : elles ont récupéré des URL en direct, parcouru les critères un par un et rapporté ce qu'elles trouvaient. D'après notre propre décompte dans les transcriptions — que nous ne publions pas — chaque exécution a effectué entre 36 et 47 appels d'outils, et aucune n'a inventé de fait. Prenez ces deux affirmations comme notre lecture des exécutions, pas comme quelque chose que les fichiers ci-dessous vous permettent de vérifier. Elles ont tout de même terminé à 15 points d'écart, dont onze dans une seule catégorie.

Totaux par catégorie des trois exécutions du modèle. Même site, même prompt, même jour.
Catégorie Max A B C Écart
A — Découverte181313121
B — Artefacts de page221213121
C — Spécification lisible par une machine2520211011
D — Contenu201819181
E — Rendu et hygiène151514132
Total10078806515

Deux sortes de désaccords sont mélangées ici. Les petits — A5, B3, B5, B6, D1, D3, D6, un point par-ci par-là, dans les deux sens — sont ce que l'on attendrait de trois lecteurs attentifs de la même page : l'un a trouvé les onglets SDK dans le DOM, les deux autres ont conclu qu'ils n'existent qu'à l'intérieur d'une charge JavaScript. S'agit-il d'un bruit de mesure ordinaire ? Trois exécutions ne peuvent pas le dire ; sur ce point nous supposons. Seul le désaccord sur D1 est visible dans les résumés publiés — le reste vient de notre propre comparaison des trois transcriptions. Le grand désaccord est d'une autre nature, et c'est la raison d'être de cette page.

Les autres critères de la catégorie C ont obtenu exactement 10 points dans chacune des trois exécutions. Tout l'écart de onze points tient à deux critères.

C1a : les mêmes faits, trois notes différentes

Le critère C1a — issu de la grille à 26 critères du modèle ; AgentFit fusionne découverte et validité en un seul C1 — demande si l'API dispose d'une spécification lisible par machine qu'un agent peut atteindre. Les trois exécutions ont établi exactement les deux mêmes faits à propos de docs.stripe.com :

Personne n'a eu tort. Personne n'a halluciné. Les notes : 0 sur 8, 3 sur 8 et 4 sur 8.

Les trois critères sur lesquels les exécutions ont le plus divergé, tels que chacune les a notés.
CritèreABC
C1a · spec discoverable3/84/80/8
C1b · spec valid7/77/70/7
E5 · terms of use3/32/31/3

Le désaccord ne porte pas sur le site. Il porte sur une question que la grille n'a jamais posée : une spécification compte-t-elle comme publiée si elle réside sur le domaine de quelqu'un d'autre et demande un saut de plus ? C'est un véritable embranchement sans réponse évidente, et chaque exécution s'y est présentée seule, au milieu d'une longue tâche, sans règle à consulter. Trois exécutions, trois politiques.

À partir de là, la divergence se propage. C1b note la qualité de la spécification trouvée. L'exécution qui a décidé que GitHub ne comptait pas n'avait rien à valider et a mis 0 sur 7. Les deux qui l'ont récupérée ont mis 7 sur 7 — puis ont annoncé un nombre de chemins différent, 414 et 136, parce que le dépôt de Stripe contient plus d'un fichier de spécification et qu'elles n'ont pas pris le même (spec3.json et spec3.yaml). Deux exécutions d'accord sur la note pour des raisons opposées.

E5 — « les conditions d'utilisation sont-elles indiquées ? » — a donné 3/3, 2/3 et 1/3. Une exécution a trouvé en pied de page un lien vers stripe.com/legal/ssa. Une autre a rejeté ce lien et a plutôt validé la directive Content-Signal du robots.txt. La troisième a cherché /terms, /legal et /privacy sur l'hôte de la documentation, a obtenu trois 404 et a noté ce qu'elle voyait. Trois lectures défendables d'une même ligne de grille.

L'autocontrôle a varié lui aussi

Le prompt embarque une ancre de calibration : un tableau de sites déjà mesurés où Stripe figure à 56, mesuré le 13 mai 2026. Il est là précisément pour repérer la dérive. C'est aussi ce tableau qui explique que le site ici soit docs.stripe.com — Stripe figurait déjà dans l'ancre de calibration de quelqu'un d'autre avant que nous ne lancions quoi que ce soit : le site a été choisi pour nous, et choisi avant l'expérience.

Les trois exécutions s'en sont servies. Les trois ont remarqué leur propre écart — +22, +24, +9. Les trois ont ensuite réexaminé leurs critères, raisonné sur ce qui avait pu changer depuis mai, et conclu que l'ancrage était périmé et que leur propre nombre valait mieux. Trois fois, indépendamment, dans le même sens, avec trois nombres différents.

C'est le passage que nous trouvons le plus instructif. Ce n'est pas de la négligence : c'est à quoi ressemble un travail consciencieux quand la procédure comporte encore un paramètre libre. Un autocontrôle dont le verdict change d'une exécution à l'autre n'est pas un autocontrôle.

L'ancrage se trouve à un point du 57 d'AgentFit. N'y lisez rien : c'est une mesure manuelle, sur une autre grille, d'un autre mois, et ce n'est pas une preuve que 57 est la note véritable.


Pourquoi le code répond la même chose

Rien d'astucieux. Chaque critère est une requête plus une règle, et les deux sont écrites avant que l'audit ne commence.

Quatre lignes du rapport AgentFit — identiques octet pour octet dans les trois exécutions.
Critère Résultat Requête Enregistré
A1 · index llms.txt présent 3/3 GET /llms.txt → 200 Stripe Documentation
C1 · découverte de la spécification absent 0/8 liste d'URL fixe, aucune réponse
D2 · réalisme des exemples présent 5/5 page d'endpoint échantillonnée → 200 placeholder_ratio = 0.00, 0/3 blocks
E6 · accessibilité partiel 1/4 page d'accueil → 200 a11y: 3 violations (e.g. button-name)

D2 est celui qui fait appel à l'apprentissage automatique. Deux petits classifieurs tournent à l'intérieur de l'audit : l'un note le réalisme d'un exemple de code, l'autre juge la complétude d'une page d'endpoint. Ce sont des graphes ONNX à poids figés, compilés dans le binaire. La même entrée donne le même tenseur et le même flottant, à chaque fois. Le déterminisme n'exige pas de renoncer aux modèles ; il exige de renoncer aux modèles dont on ne peut pas figer la sortie.

C1 est précisément la bifurcation que les trois exécutions ont franchie différemment, et AgentFit y met 0 sur 8. Notre règle n'est pas « GitHub ne compte pas » : c'est une liste fixe d'endroits où regarder — dix-sept chemins conventionnels sur l'hôte audité, un lien api-catalog RFC 9727, et tout lien vers une spécification trouvé sur la page d'accueil que nous avons récupérée. Sur docs.stripe.com, aucun de ces chemins n'a renvoyé de spécification et cette page ne portait aucun lien de ce type : rien n'a donc été trouvé. Une règle qui suivrait un saut de plus jusqu'au dépôt d'un éditeur ne serait pas moins correcte. La nôtre est simplement fixée avant le début de l'audit, appliquée à l'identique à chaque site du corpus, et son barème est publié sur la page de la grille. Toute la différence est là : pas une meilleure réponse, une réponse figée. Comment C1 est noté.

Comparez-le à une exécution en direct

Le dépôt est privé et nous ne publions aucun binaire : nous n’allons donc pas vous dire de le compiler — vous ne le pouvez pas. Ce qui reste vérifiable sans nous est plus étroit, et nous préférons le dire exactement. Les fichiers ci-dessus ont été écrits par une compilation en ligne de commande, sur notre machine, le 27 juillet 2026. Le service public est une autre compilation, tournant ailleurs, et il vous remettra son propre rapport pour le même site. Si la procédure est bien celle que nous décrivons, les deux s’accordent sur chaque note. Voici comment faire cette comparaison, et ce qu’elle vaut.

Sans rien exécuter (aucun quota)

Le jeu de données public porte l’identifiant d’exécution du dernier audit valide de chaque hôte. Prenez celui de Stripe, relisez cette exécution depuis l’API, réduisez les deux documents aux champs notés, puis comparez-les :

$ RUN=$(curl -s https://agentfit.dev/dataset.csv \
        | awk -F, '$1=="docs.stripe.com" && $3=="true" {print $7; exit}')

$ curl -s https://agentfit.dev/static/reproducibility/agentfit-run1.json \
  | jq -S '{total_score, max_score, categories,
            criteria: [.criteria[] | {id, status, score, max}]}' > ours.json

$ curl -s https://agentfit.dev/api/public/audit/$RUN \
  | jq -S '.report | {total_score, max_score, categories,
            criteria: [.criteria[] | {id, status, score, max}]}' > theirs.json

$ diff ours.json theirs.json

Le 27 juillet 2026, ce diff n’a rien imprimé : 200 lignes, aucune sortie. Deux compilations différentes, deux machines différentes, les mêmes 28 verdicts.

L’exécuter vous-même (une fois par site et par jour)

Collez https://docs.stripe.com dans le formulaire de la page d’accueil. À la fin, l’adresse affiche /r/<identifiant>. Mettez cet identifiant à la place de $RUN et lancez les deux mêmes commandes. Notez ce que cela ajoute et ce que cela n’ajoute pas : l’audit part toujours de nos serveurs, donc ce qui est à vous, c’est la requête et l’instant, pas le point de sortie.

Un audit du même site par réseau et par 24 heures. Une deuxième tentative renvoie 429 et aucun identifiant d’exécution — délibérément, pour qu’on ne puisse pas braquer le service sur la documentation d’autrui comme un marteau. Si vous butez dessus, la méthode ci-dessus n’exige aucune soumission. Le serveur MCP partage ce quota : demander à un agent de réauditer le même site le même jour se heurte au même mur. Et devant celui-là s’en dresse un second, qui ne vous appartient pas : deux audits du même hôte en dix minutes, par n’importe qui, épuisent une réserve partagée, et l’appelant suivant reçoit 429 avec le code rate_limited plutôt que site_quota. Celui-là se dissipe tout seul en dix minutes.

Sans curl ni jq

Ouvrez agentfit-run1.json dans un onglet et la page de rapport de l’exécution, /r/<identifiant>, dans un autre. Sept nombres tranchent : les six totaux de catégorie et le total général. Ils sont imprimés ici, pour que cette page suffise.

AgentFit sur docs.stripe.com, 27 juillet 2026 — identique dans les trois fichiers
Catégorie Note Max
A — Découverte1114
B — Éléments de page1121
C — Contrat d'API417
D — Contenu1623
E — Rendu et hygiène1521
F — Capacités d'agent04
Total57100

Trois choses différeront, et c’est normal

Une correspondance signifie une seule chose : la même procédure, sur le même site, a rendu le même verdict depuis une autre compilation, sur une autre machine. Elle ne signifie pas que 57 est la bonne note — rien sur cette page ne le prétend. Et elle dépend du site : si docs.stripe.com a changé depuis le 27 juillet 2026, les nombres bougent, et c’est l’instrument qui fonctionne, pas qui casse. Regardez la date audited_on dans la ligne du jeu de données avant de conclure quoi que ce soit d’un écart.

Ces fichiers sont gelés et nous ne les régénérons pas à chaque version. Deux raisons : la somme de contrôle affichée sur cette page est prise sur ces octets précis, et chaque nombre de la prose ci-dessus en a été extrait — une pièce à conviction qui se rafraîchit toute seule ne pourrait porter ni l’un ni l’autre. Le fil d’alarme est du côté vivant, pas dans le fichier gelé : la colonne 9 de la ligne du jeu de données que vous venez de lire est rubric_version, et tant que cette page tient, elle doit valoir 4. La pièce à conviction est antérieure à cette colonne et ne la porte pas ; le nombre auquel la comparer est donc celui imprimé dans cette phrase — nous l’affirmons au lieu de vous le faire trouver, c’est une garantie plus faible, et c’est pourquoi elle est écrite noir sur blanc. Si cette colonne affiche un jour autre chose, c’est que la règle a changé après l’écriture de cette page : la comparaison champ à champ est nulle, et vous avez sous les yeux un document historique. Nous préférons que la page le dise tout haut plutôt qu’elle se rejoue en silence jusqu’à tomber d’accord.

Deux des 28 critères, D2 et C3, sont tranchés par de petits classifieurs plutôt que par une règle. Ils sont compilés dans le binaire et versionnés avec lui — il n’y a pas de serveur de modèles, et le réentraînement de personne ne déplace une note déjà publiée.


Ce que nous n'affirmons pas

Ce qu'un modèle réussit vraiment ici

Rien de tout cela ne rend les exécutions du modèle inutiles — cela en fait un instrument d'une autre nature. Le diagnostic de chacune des trois exécutions est bon en soi : pourquoi une spécification manquante pénalise un agent, quoi publier à la place, lesquelles des pages de Stripe survivraient à une lecture sans navigateur. C'est de l'explication, et un modèle explique à merveille.

Un modèle de langage excelle à expliquer quoi corriger. Il fait un mauvais instrument pour mesurer si vous l'avez corrigé. Nous, c'est le second. AgentFit est l'instrument ; portez son nombre à un modèle et demandez-lui quoi en faire. C'est la bonne division du travail, et c'est celle que nous pratiquons.

Les données

Les six exécutions sont servies depuis ce site. Les trois rapports AgentFit sont les fichiers écrits par l'outil, octet pour octet — c'est sur eux qu'est calculée la somme de contrôle. Les trois fichiers du modèle sont les nôtres :

Les transcriptions brutes ne sont pas publiées. Pour la colonne du modèle, vous obtenez des résumés structurés que nous avons rédigés après coup à partir de ces transcriptions : la note finale, les totaux par catégorie et les remarques par critère citées plus haut. Les notes et les totaux sont le résultat propre de chaque exécution ; la formulation des remarques est la nôtre.

Rien n'a été écarté — ni une exécution, ni un site. Trois audits du modèle et trois audits de l'outil, sur le seul site que le tableau de calibration du prompt nommait déjà ; nous n'en avons lancé aucun autre et n'avons rien jeté. Si une quatrième exécution était revenue à 57, nous l'aurions publiée aussi et cette page serait plus courte.


Auditer votre documentation →

Gratuit, sans inscription, environ 30 secondes. 28 critères, une preuve HTTP sous chacun, un lien de rapport partageable — et le même nombre demain si rien n'a changé.