Changer le thème

Créer un dataset d'évaluation d'agent : tâches réelles, trajectoires et tests de régression

Easton editorial illustration: production agent control room
4
Couches d'échantillons
Golden set, negative cases, edge cases et regression cases.
5
Dimensions d'évaluation
Choix des outils, format des arguments, ordre d'exécution, qualité de la réponse finale et alignement avec les labels humains.
6
Champs clés de trajectoire
traceId, span_id, tool_calls, state_events, approval records et human labels.
数据来源: Cette checklist d'ingénierie s'appuie sur les documentations officielles d'OpenAI, LangSmith, Phoenix, DeepEval et OpenAI Agents SDK. Les noms d'API, l'état des plateformes et les interfaces produit doivent toujours être vérifiés dans les documentations officielles après publication.

"OpenAI Evaluation best practices recommande de définir les objectifs, collecter un dataset, définir les métriques, exécuter des comparaisons et évaluer en continu. Les données de test peuvent venir de production data, historical data, domain samples et labels humains."

La semaine dernière, l’agent qui générait le rapport quotidien fonctionnait encore. Après une mise à niveau du modèle, il produit toujours un résumé final qui semble correct, mais la trajectoire montre que le contrôle de permission et l’outil de rafraîchissement des données ont été ignorés. Un agent de support donne une réponse finale correcte, mais appelle l’outil de remboursement avec de mauvais arguments ; un benchmark public ne verra pas ce risque. Une rétrospective d’incident contient déjà traceId, tool call, approvalId, state event et jugement humain, mais rien n’a été fixé comme test obligatoire avant le prochain release.

Ce type de régression ne se couvre pas en changeant de modèle ou en relançant une demo. Un dataset d’évaluation d’agent doit venir de la distribution réelle des tâches et des trajectoires d’échec en production : tool calls, formats d’arguments, transitions d’état, approval records et labels humains. Ensuite, il doit entrer dans CI comme gate de régression. Ici, on part de cas d’échec et de scénarios concrets : comment construire un eval dataset durable qui protège la frontière de qualité de chaque release.

1. Pourquoi les benchmarks publics ne suffisent pas

1.1 Les limites des benchmarks publics

Les benchmarks publics mesurent la capacité du modèle, pas la qualité de vos tâches métier. Des jeux d’évaluation comme AgentBench ou WebArena fournissent des tâches standardisées, mais ils ne couvrent ni votre toolchain, ni votre modèle de permissions, ni votre state machine.

Par exemple, votre agent de reporting doit peut-être appeler check_permission, refresh_data et generate_report, dans l’ordre “vérifier → rafraîchir → générer”. Un benchmark public ne testera pas ce flux, car il ne connaît ni vos tool schemas ni vos limites de permission.

Un bon score sur un benchmark public ne signifie donc pas que vos tâches métier ne régresseront pas. Un dataset d’évaluation d’agent doit tester votre vraie distribution de tâches, pas une capacité de raisonnement générale.

1.2 La valeur principale d’un dataset interne

Un eval dataset interne capture des risques que les benchmarks publics ne voient pas. Voici des scénarios typiques :

ScénarioBenchmark publicEval dataset interne
L’agent de reporting oublie le contrôle de permissionInvisible : l’outil et le modèle de permission n’existent pasCapture la contrainte de trajectoire : check_permission doit être appelé
L’agent de support passe un mauvais argument de remboursementAucun outil ni schema de remboursementListe de tool calls attendue + contraintes de format d’arguments
Les transitions d’état régressent après un changement de modèlePas de state machine correspondanteAssertion de trajectoire d’état : vérification → approbation → exécution
La rétrospective d’incident n’est pas transformée en testPas de données d’incidentLe cas d’échec entre dans les negative cases

Utilisez les benchmarks publics pour choisir un modèle ; utilisez votre dataset pour protéger les release gates. Ils se complètent, mais ne se remplacent pas. Si vous avez déjà lu Comparatif des benchmarks d’évaluation d’agents, vous savez quels benchmarks publics aident au choix de modèle. Ici, le sujet est la construction de données d’évaluation depuis votre propre environnement de production.

2. Les champs clés d’un agent eval dataset

2.1 Champs obligatoires

Un agent eval dataset ne se limite pas à stocker l’entrée utilisateur et la réponse attendue. Il doit enregistrer la trajectoire des tool calls, les transitions d’état et les jugements humains. Voici les champs obligatoires :

ChampDescriptionSource
inputDescription de la tâche utilisateurTrace de production / conception manuelle
expected outputRéponse finale attendueAnnotation humaine / golden set
expected tool callsListe de tool calls attendueAnalyse de trajectoire, par exemple ["check_permission", "refresh_data"]
trajectory assertionsContraintes de trajectoire : obligatoire, interdit ou ordreState machine + flux d’approbation
human labelsJugement humain : correct, faux ou partielRétrospective d’incident / file de labellisation

Dans Evaluation concepts, LangSmith recommande de couvrir le choix des outils, le format des arguments et la trajectoire d’exécution pour évaluer un agent, au lieu de juger seulement la réponse finale. OpenAI Agents SDK Tracing fournit des champs comme trace_id, workflow_name et span pour enregistrer les tool calls et les événements d’état, mais ces champs bruts doivent être anonymisés et extraits avant d’entrer dans un dataset.

2.2 Champs optionnels

Ajoutez les champs suivants selon vos besoins métier :

ChampDescriptionUsage
approval recordsEnregistrements d’approbation : approbateur, heure, résultatTool calls nécessitant une approbation dans le modèle de permissions
state transitionsSéquence de transitions d’étatContraintes de state machine, par exemple ["init", "check", "approve"]
metadatatraceId, environnement, version du modèleDiagnostic d’incident et comparaison de versions

Si vous avez lu le modèle de permissions d’agent (N157) et la conception d’approbation humaine (N155), vous savez que approval records doit enregistrer l’étape d’approbation, l’approbateur et le résultat, afin de vérifier qu’une action à haut risque a bien été approuvée.

2.3 Anonymisation et confidentialité

Une trace de production ne doit pas entrer telle quelle dans le set d’évaluation. La documentation OpenAI Agents SDK Tracing rappelle que certains spans peuvent capturer les entrées/sorties du modèle ou les entrées/sorties d’outils fonctionnels ; il faut donc configurer ce qui inclut des données sensibles.

Champs à anonymiser obligatoirement : PII (nom, e-mail, téléphone), secrets (API key, mot de passe de base de données), données client (numéro de commande, montant de transaction).

Champs à conserver : traceId, span_id pour le diagnostic, workflow_name pour la classification, noms d’outils et noms d’états pour les assertions.

Les méthodes d’anonymisation incluent le remplacement par des placeholders comme <user_id>, le hash ou la suppression pure. La documentation Phoenix Running Evals on Traces montre qu’une trace peut devenir une entrée d’évaluation, mais elle a toujours besoin de label, score et rubric. Ne mettez pas une trace brute complète directement dans l’eval dataset.

3. De la trace de production à l’eval example

3.1 Flux de collecte des données

Transformer une trace de production en eval example passe par quatre étapes : anonymisation, labellisation, stratification et stockage. Ce n’est pas un chantier ponctuel, mais une opération continue.

Checklist :

  1. Exporter les traces échouées depuis la plateforme de monitoring (voir Monitoring d’agent et reprise après échec).
  2. Classer par type d’échec : erreur de tool call, erreur de format d’argument, erreur de transition d’état, erreur de réponse finale.
  3. Anonymiser : supprimer PII/secret/données client, conserver traceId, span_id et workflow_name.
  4. Ajouter un label humain : correct/faux/partiellement correct + raison de l’échec.
  5. Stocker par couche : golden set / negative cases / edge cases.

La documentation Phoenix datasets indique que les examples peuvent venir de production, staging, evaluations ou manual. La production donne la vraie distribution des tâches ; le staging permet de compléter les scénarios limites.

3.2 Critères de stratification

CoucheCritèreUsage
golden set100 % correct + tâches fréquentesDoit passer le release gate ; seuil de pass rate
negative casesModes d’échec typiquesAlertes de régression, empêche le même bug de revenir
edge casesScénarios long tail / limitesCouverture complémentaire, à intégrer au cas par cas

Dimensions de labellisation, alignées sur une rubric LLM-as-judge : exactitude du choix d’outil, exactitude du format d’argument, exactitude de l’ordre d’exécution, qualité de la réponse finale, alignement avec les labels humains.

OpenAI Evaluation best practices recommande des données de test couvrant typical, edge et adversarial cases, avec des human expert labellers. La stratification ci-dessus suit cette logique, mais met l’accent sur les tâches fréquentes et les modes d’échec typiques, car le but du set d’évaluation est de protéger le release gate, pas de couvrir tous les scénarios possibles.

4. Écrire des trajectory assertions

4.1 Types de contraintes de trajectoire

Les trajectory assertions définissent les règles de tool call, de format d’argument, de transition d’état et d’approbation que l’agent doit respecter. Voici cinq types courants :

Type de contrainteExempleCondition d’échec
Liste d’outils obligatoires["check_permission", "refresh_data", "generate_report"]Il manque au moins un outil obligatoire
Liste d’outils interdits["delete_user", "drop_table"]Un outil interdit est appelé
Contrainte de format d’argument{"refund_amount": "number", "user_id": "uuid"}Le type d’argument est faux
Ordre des transitions d’état["init", "check", "approve", "execute"]Un état est sauté ou répété
Existence d’une étape d’approbation["need_approval", "approval_granted"]L’événement d’approbation manque

LangSmith Evaluation concepts cite trajectory, tool selection et argument formatting comme axes d’évaluation d’agent. Phoenix Running Evals on Traces utilise span_id pour relier un résultat d’évaluation à un segment d’exécution précis ; les assertions de trajectoire peuvent donc pointer vers le span en échec.

Si vous avez lu l’évaluation de la capacité de planification d’agent (N158) et les limites state machine / prompt, vous savez que les champs de trajectoire d’état viennent de state, event et checkpoint. Ils servent à vérifier que la transition d’état suit l’ordre attendu.

4.2 Exemple de code

Voici un pseudo-code de trajectory assertions pour une évaluation d’agent générique :

# Exemple de trajectory assertions
def assert_trajectory_correct(result):
    # Extraire la liste des tool calls
    tools_called = [call.tool for call in result.tool_calls]

    # Outils obligatoires
    required_tools = ["check_permission", "refresh_data"]
    for tool in required_tools:
        assert tool in tools_called, f"Missing required tool: {tool}"

    # Outils interdits
    forbidden_tools = ["delete_user"]
    for tool in forbidden_tools:
        assert tool not in tools_called, f"Called forbidden tool: {tool}"

    # Contraintes de format d'argument
    for call in result.tool_calls:
        if call.tool == "refund":
            assert isinstance(call.args["refund_amount"], (int, float)), "refund_amount must be number"
            assert len(call.args["user_id"]) == 36, "user_id must be uuid format"

    # Ordre des transitions d'état
    expected_states = ["init", "check", "approve", "execute"]
    actual_states = [event.state for event in result.state_events]
    assert actual_states == expected_states, "State transition order mismatch"

    # Existence de l'étape d'approbation
    approval_events = [e for e in result.state_events if e.type == "approval"]
    assert len(approval_events) >= 1, "Missing approval step"

Ce code montre comment vérifier les outils obligatoires, les outils interdits, les formats d’arguments, l’ordre des transitions d’état et les étapes d’approbation. En pratique, vous pouvez utiliser les trajectory assertions de LangSmith ou les trace eval de Phoenix ; la logique centrale reste la même.

Si vous avez lu Évaluation de la planification d’agent, vous savez que les trajectoires de planification peuvent aussi devenir des échantillons de régression pour vérifier la décomposition de tâches et l’auto-correction.

5. Rubric stratifiée pour LLM-as-judge

5.1 Pourquoi le score global ne suffit pas

Si LLM-as-judge ne renvoie qu’un score global, le résultat est instable et difficile à diagnostiquer. Un score de 80 peut signifier que le choix d’outil est faux mais que la réponse est tombée juste, ou que la réponse est fausse mais bien formatée. Impossible alors de distinguer un problème de prompt, de tool schema, de recherche ou de state machine.

LangSmith Evaluation concepts recommande de définir des critères qualité pour les composants clés de l’agent : correct tool selection, proper argument formatting et trajectory. En notant chaque composant séparément, on localise beaucoup plus vite les régressions après un changement de modèle ou de prompt.

Si vous avez lu Pratiques avancées de prompt engineering, vous savez que DeepEval met aussi l’accent sur des métriques stratifiées comme TaskCompletenessMetric, et pas seulement sur la sortie finale.

5.2 Tableau de scoring stratifié

La rubric suivante découpe l’évaluation d’agent en cinq dimensions, chacune notée de 0 à 2 :

Dimension0 point1 point2 points
Exactitude du choix d’outilMauvais outilPartiellement correctEntièrement correct
Exactitude du format d’argumentErreur de typeCertains champs ont un format erronéEntièrement correct
Exactitude de l’ordre d’exécutionSaut d’étatÉcart d’ordreEntièrement correct
Qualité de la réponse finaleNe répond pas au besoinRépond partiellementRépond entièrement
Alignement avec le label humainContredit le jugement expertPartiellement alignéFortement aligné

Exemple de configuration de rubric pour LangSmith ou Phoenix :

rubric:
  dimensions:
    - name: tool_selection
      weight: 0.3
      criteria:
        0: "Mauvais outil appelé"
        1: "Certains outils corrects appelés"
        2: "Choix d'outil entièrement correct"

    - name: argument_formatting
      weight: 0.2
      criteria:
        0: "Type d'argument incorrect"
        1: "Certains champs ont un format incorrect"
        2: "Format d'argument entièrement correct"

    - name: execution_order
      weight: 0.2
      criteria:
        0: "Transition d'état sautée ou répétée"
        1: "Ordre d'exécution avec écart"
        2: "Ordre d'exécution entièrement correct"

    - name: final_answer_quality
      weight: 0.2
      criteria:
        0: "Ne répond pas à la demande utilisateur"
        1: "Répond partiellement à la demande"
        2: "Répond entièrement à la demande"

    - name: human_alignment
      weight: 0.1
      criteria:
        0: "Contredit le jugement expert"
        1: "Partiellement aligné"
        2: "Fortement aligné"

Le choix d’outil a le poids le plus élevé (0.3), car le cœur d’un agent est d’appeler le bon outil. L’alignement avec le label humain a le poids le plus faible (0.1), car il sert surtout à calibrer l’accord entre LLM-as-judge et jugement expert.

6. Release gates et tests de régression

6.1 Étapes d’intégration CI

La valeur d’un agent eval dataset apparaît quand il est exécuté dans CI comme release gate. Voici les étapes :

Checklist :

  1. Ajouter une étape d’exécution d’eval dans la CI pipeline, par exemple pytest, LangSmith offline eval ou Phoenix experiments.
  2. Configurer un seuil de pass rate, par exemple 90 %.
  3. Exiger que le golden set passe à 100 %.
  4. Configurer des règles d’alerte pour les negative cases : elles peuvent notifier l’équipe sans bloquer.
  5. Configurer une comparaison de versions (improvement/regression) entre la baseline et la version actuelle.
  6. Définir les déclencheurs du gate : PR / merge / canary.

LangSmith Evaluation concepts indique que les offline evaluations peuvent servir au regression testing, unit testing et backtesting sur les examples des datasets. La documentation Phoenix experiments explique que l’on peut comparer des changements de prompt, de LLM ou de logique applicative pour juger improvement/regression. DeepEval annonce des evals pytest-native exécutables en CI/CD ou dans des Python scripts, avec LLMTestCase et TaskCompletenessMetric pour noter les traces d’agent couche par couche.

6.2 Tableau de seuils

IndicateurSeuilAction en cas d’échec
pass rate≥ 90 %Bloquer le merge
golden set100 % de passageBloquer le merge
negative casesAlerte déclenchéeNe pas bloquer, mais notifier le responsable d’équipe
version comparisonAucune regressionBloquer le merge

Exemple de configuration CI :

evaluation:
  triggers:
    - pull_request
    - merge_to_main
    - canary_deployment

  conditions:
    pass_rate: 0.9
    golden_set: 1.0
    no_regression: true

  notifications:
    on_failure: ["team-lead", "on-call"]
    on_negative_alert: ["team-lead"]

Les déclencheurs incluent les PR, pour empêcher un mauvais changement d’entrer dans la branche principale ; le merge, pour vérifier que l’état fusionné satisfait toujours les conditions ; et le canary, pour valider avant le trafic de production. Si vous avez lu le contrôle des coûts et le routage de modèles (N156), vous savez que les seuils de coût peuvent aussi devenir des conditions de gate. Ici, on reste concentré sur les seuils d’évaluation.

7. Retour sur un cas réel

7.1 Description du scénario

L’agent de rapport quotidien fonctionnait correctement la semaine précédente : il appelait check_permission pour vérifier les permissions, refresh_data pour rafraîchir les données, puis generate_report pour produire le rapport. Après une mise à niveau du modèle, l’agent renvoie encore un résumé final qui semble correct, mais la trajectoire ne contient plus check_permission ni refresh_data.

L’utilisateur reçoit donc un rapport sans contrôle de permission et avec des données périmées, sans que cela saute aux yeux. Un benchmark public ne détecte pas ce risque, car il ne possède ni votre tool schema ni votre state machine.

7.2 Localisation du problème

Exportez la trace échouée depuis la plateforme de monitoring (voir Monitoring d’agent et reprise après échec). L’analyse de trajectoire montre que la liste des tool calls ne contient pas check_permission ni refresh_data, que l’état passe directement de init à execute, que check et approve manquent, et que la réponse finale semble correcte alors que la source de données n’a pas été rafraîchie.

Label : erreur de choix d’outil + saut de transition d’état.

7.3 Mise à jour du dataset

Ajoutez ce cas d’échec aux negative cases. Complétez aussi le golden set : retrouvez la tâche de rapport quotidien réussie la semaine précédente, avec la séquence complète de tool calls, et marquez-la comme cas correct.

Mettez à jour les trajectory assertions : ajoutez check_permission et refresh_data à la liste des outils obligatoires, et fixez l’assertion d’ordre des états à ["init", "check", "approve", "execute"].

7.4 Interception par le gate CI

La PR suivante déclenche une exécution d’eval. Le negative case déclenche une alerte : l’appel à check_permission manque. Le golden set passe intégralement, ce qui montre que le cas de succès de référence reste intact.

Le problème vient du prompt. Après la mise à niveau, le modèle interprète “générer un rapport” comme une exécution directe et ignore les étapes préalables de vérification et de rafraîchissement.

7.5 Correction et régression

Corrigez le prompt en précisant que l’agent doit vérifier les permissions et rafraîchir les données avant de générer le rapport. Relancez l’eval : le pass rate passe de 85 % à 95 %, le negative case passe sans alerte, le golden set passe intégralement, et la comparaison de version indique une improvement sans regression.

Vous pouvez merger et release. Le gate CI a bloqué cette régression avant la production.

7.6 Tableau de correspondance des champs

ÉtapeChamps utilisés
Localisation du problèmetraceId, span_id, tool_calls, state_events
Mise à jour du datasetinput, expected tool calls, trajectory assertions, human labels
Gate CIpass rate, golden set, negative cases
Vérification du correctifpass rate, version comparison

Cette boucle montre le chemin complet entre échec de production et test de régression. Après chaque rétrospective d’incident, transformez traceId, tool call, approvalId, state event et jugement humain en eval example. Le prochain release ne retombe alors pas dans le même piège.

8. À lire ensuite

  • State machines d’agent et limites du prompt : comprendre l’origine des contraintes de transition d’état et des champs de trajectory assertion
  • Modèle de permissions d’agent : comprendre les champs approval records et les règles de tool calls à haut risque
  • Conception d’approbation humaine : transformer approval records et flux d’approbation en tests durables
  • Contrôle des coûts et routage de modèles : comprendre comment les seuils de coût deviennent des conditions de gate
  • Monitoring d’agent et reprise après échec : exporter les failed traces et construire une boucle de rétrospective d’incident

Construire un dataset d'évaluation d'agent et une suite de régression

Transformer des tâches réelles d'agents, des traces de production, des cas d'échec, des trajectoires de tool calls et des labels humains en eval dataset versionné, exécuté dans les release gates CI.

⏱️ Estimated time: 60 min

  1. 1

    Step 1: Collecter les tâches candidates

    Collectez des tâches réelles depuis la production, le staging, les tests manuels et les rétrospectives d'incident. Priorisez les flux fréquents, risqués ou déjà touchés par une régression.
  2. 2

    Step 2: Associer les traces d'exécution

    Associez chaque tâche à traceId, span_id, state events, tool calls, approval records et sortie finale afin de pouvoir relier l'échec au bon point d'exécution.
  3. 3

    Step 3: Anonymiser les données brutes

    Supprimez ou remplacez PII, secrets, données client, vrais numéros de commande et champs sensibles des sorties d'outils. Ne gardez que les informations structurées utiles à l'évaluation.
  4. 4

    Step 4: Extraire le schema du dataset

    Ajoutez à chaque échantillon input, expected output, expected tool calls, trajectory assertions, rubric, risk tags, human labels et métadonnées de version.
  5. 5

    Step 5: Découper en couches

    Répartissez les échantillons entre golden set, negative cases, edge cases et regression cases, chacun avec son seuil de passage et sa règle d'alerte.
  6. 6

    Step 6: Configurer les évaluateurs

    Utilisez code evaluator, rule evaluator, LLM-as-judge ou human annotation selon les dimensions. Ne dépendez pas d'un score global unique.
  7. 7

    Step 7: Brancher sur les release gates

    Exécutez la regression suite dans CI avant les mises à niveau de modèle, les changements de prompt et les modifications de tool schema.
  8. 8

    Step 8: Mettre à jour après chaque incident

    Après chaque rétrospective d'incident, ajoutez de nouveaux cases et consignez dataset version, raison du changement, périmètre et politique de conservation des données.

FAQ

Peut-on utiliser directement des traces de production comme eval dataset ?
Non. Les traces de production doivent d'abord être anonymisées : retirer PII, secrets et données client, puis ajouter des labels humains comme correct, faux ou partiellement correct, avant de classer l'échantillon dans un golden set, des negative cases ou des edge cases. La documentation OpenAI Agents SDK Tracing rappelle aussi que certains spans peuvent capturer des entrées et sorties sensibles.
Comment écrire une expected trajectory pour les tool calls d'un agent ?
Partez d'une exécution réussie, extrayez la séquence de tool calls, définissez les outils obligatoires et interdits, puis ajoutez des contraintes d'ordre sur les transitions d'état. L'évaluation d'agent doit vérifier le choix des outils, le format des arguments et la trajectoire d'exécution, pas seulement la réponse finale.
Tous les cas d'échec doivent-ils entrer dans la regression suite ?
Non. Priorisez les cas fréquents, à risque élevé, déjà responsables d'un incident, couvrant une transition d'état critique ou capables d'empêcher une régression répétée. Les cas long tail peuvent rester dans la couche edge cases tant que leur risque ne justifie pas un gate dur.
Comment fixer un seuil de release quand les scores LLM-as-judge fluctuent ?
Ne regardez pas seulement le score total. Le golden set doit passer intégralement, et le seuil de pass rate doit refléter le risque métier, par exemple 90 %. Notez séparément choix des outils, format des arguments, trajectoire, qualité de réponse finale et alignement avec les labels humains, puis combinez avec des assertions de code et de règles.
Faut-il stocker les entrées utilisateur brutes et les sorties d'outils ?
Seulement après anonymisation. L'entrée utilisateur peut être conservée après suppression ou remplacement des PII, et les sorties d'outils ne devraient garder que les champs clés. traceId et span_id peuvent rester pour le diagnostic, mais une trace brute complète ne doit pas entrer directement dans l'eval dataset.
Comment diagnostiquer vite une ancienne tâche qui se dégrade après un changement de modèle ?
Commencez par l'alerte du gate CI. Vérifiez le pass rate et la comparaison de régression, ouvrez le test case en échec, puis analysez le choix des outils, le format des arguments et les transitions d'état. La cause se trouve souvent dans le prompt, le tool schema, la recherche, le modèle de permissions ou la frontière de state machine.
Quel est le lien entre un eval dataset interne et les benchmarks publics ?
Les benchmarks publics mesurent des capacités générales et aident à choisir un modèle. Un dataset interne mesure vos tâches produit, vos outils, vos permissions, votre distribution de données et vos modes d'échec ; c'est donc le signal principal pour les décisions de release. Les deux se complètent sans se remplacer.
Que faire si OpenAI Evals platform ferme ?
Au 2026-07-07, la documentation OpenAI indique que l'Evals platform doit devenir read-only pour les utilisateurs existants le 2026-10-31, puis être shutdown le 2026-11-30. Gardez votre dataset portable : définissez test data, ground truth et grader en JSON/YAML au lieu de lier votre système de régression à une seule plateforme.

14 min de lecture · Publié le: 21 oct. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog