Créer une évaluation de workflow Instance AI
Chaque eval est un fichier JSON unique dans
packages/@n8n/instance-ai/evaluations/data/workflows/. Le loader
découvre automatiquement les fichiers *.json et les valide selon
schema.ts
(.strict() — les clés inconnues échouent au chargement). Aucune étape d'enregistrement.
Le principe fondamental : écrire les attentes à partir de l'intention, puis calibrer selon une vraie construction. Décidez à l'avance ce qui rend toute solution correcte correcte (les must-haves impliqués par le prompt), puis construisez le workflow une fois pour de vrai afin de calibrer la granularité — assouplissez ce qui est surspécifié, confirmez que les must-haves sont réalisables, et détectez les exigences que l'agent satisfait légitimement d'une autre manière. Ne transcrivez pas une construction observée en assertions : cela surparamètre l'eval en « l'agent a-t-il reproduit cette exécution » au lieu de « a-t-il résolu le problème ». Consultez le README de l'eval pour la référence complète des champs.
Workflow
- Énoncez d'abord les must-haves. À partir du prompt seul, listez ce que chaque workflow correct doit faire (type de trigger, les opérations essentielles, la condition de contrôle). Ceux-ci deviennent des
outcomeExpectationsbrouillons. Champs de cas requis :conversation(≥1 tour, premieruser),executionScenarios(≥1),complexity,tags. - Rédigez le cas à partir du modèle ci-dessous ; validez qu'il se charge (voir « Validate ») avant d'exécuter.
- Exécutez-le une fois (voir « Run locally ») avec
--keep-workflowspour que le workflow construit reste sur l'instance pour inspection. - Inspectez le workflow construit — récupérez-le via
GET /rest/workflows/<id>(l'exécution afficheBUILT (<id>)) et lisez les nœuds, paramètres et connexions. - Calibrez les attentes selon ce que vous avez vu : assouplissez toute assertion que la construction a satisfaite d'une manière valide mais différente, resserrez toute assertion qu'une mauvaise construction aurait contournée, et formulez
executionScenarios(dataSetup→successCriteria) pour correspondre à la façon dont le workflow s'exécute sur les données simulées. Conservez les must-haves ; ajustez uniquement leur granularité. - Réexécutez pour confirmer que les attentes calibrées sont satisfaites. Optionnellement
--iterations 5pour mesurer l'instabilité avant d'ajouter le cas à une couche plus stricte (datasets: ["pr", ...]).
Modèle
{
"description": "Ce que ce cas teste.",
"conversation": [
{ "role": "user", "text": "<le prompt de construction>" }
],
"complexity": "medium",
"tags": ["build", "<nodes>", "<concepts>"],
"triggerType": "schedule",
"datasets": ["full"],
"outcomeExpectations": [
"<une condition must-have que toute workflow correcte satisfait>"
],
"executionScenarios": [
{
"name": "happy-path",
"description": "<ce que cette exécution teste>",
"dataSetup": "<entrée + ce que les services simulés retournent>",
"successCriteria": "<preuve observable que l'exécution a réussi>"
}
]
}
Pour un cas de question de clarification / multi-tour, ajoutez des tours de référence assistant et une instruction de scène user dans [crochets] (comportement proxy, jamais envoyé au builder), p. ex. [Ne mentionnez le canal que si on vous le demande ; alors dites 'Slack #growth.']. Les processExpectations jugent la conversation ; les outcomeExpectations jugent le workflow. Les deux comptent comme unités de taux de réussite.
Dimensionner chaque assertion
Une assertion est bien dimensionnée quand toute construction correcte la passe et une construction mauvaise ou paresseuse la rate. Vérification rapide — le test de substitution : une alternative raisonnable la passerait-elle encore ? Si non, elle est trop stricte ; si une non-solution la passerait aussi, elle est trop lâche. Exemples pour le cas flight-status :
| Verdict | Assertion | Pourquoi |
|---|---|---|
| ❌ trop stricte | « A un nœud HTTP Request appelant flightaware.com » |
Surparamètre une exécution ; une construction valide utilisant AeroDataBox échoue. Le vendeur n'a jamais été l'exigence. |
| ❌ trop stricte | « Envoie l'alerte via un nœud Gmail » | Le canal n'était pas spécifié ; Slack/email/etc. sont tous corrects. |
| ❌ trop lâche | « Récupère les données de vol d'une source quelconque » | Un workflow qui récupère mais ne compare jamais passerait — ne prouve pas la détection de changement. |
| ✅ correcte | « Récupère le statut actuel d'une source externe via un nœud HTTP Request » | Toute construction correcte passe ; une qui code en dur un statut échoue. |
| ✅ correcte | « Persiste le statut précédemment vu et le compare à celui nouvellement récupéré » | Le comportement définissant ; resistant au test de substitution selon les vendeurs et les choix de stockage. |
| ✅ correcte | « L'alerte est envoyée uniquement sur la branche de détection de changement, contrôlée par un conditionnel » | Prouve la gâche sans fixer le nœud ou le canal. |
Mettez l'intention spécifique au vendeur/canal dans processExpectations (jugée à partir de la conversation), pas dans outcomeExpectations.
Assertions robustes vs instabilité du harness
Deux choses différentes — gardez-les séparées :
- Conception d'assertion robuste (faites-le toujours). Les choix de l'agent varient d'une exécution à l'autre — que l'agent pose une question de clarification, quel vendeur/source il choisit.
Les
outcomeExpectationsagnostiques au vendeur ne sont pas une concession à l'instabilité ; ce sont l'assertion correcte, car le vendeur n'a jamais été une exigence. Utilisez le test de substitution ci-dessus. - Instabilité du harness (un défaut — exposez et atténuez, n'acceptez pas). La couche de simulation n'honore pas toujours
dataSetuppour les lectures à état porteur (p. ex. une « valeur antérieure » de Data Table), donc les scénarios de détection de changement peuvent échouer avec[mock_issue]. Un eval qui passe aléatoirement est sans valeur. Quand vous rencontrez cela : réduisezdataSetuppour diriger la simulation, déplacez l'intention fragile vers uneprocessExpectation, ou gardez le scénario en dehors des couches strictes (["full"]uniquement) — et notez-le dans ladescriptiondu cas. N'expédiez pas un scénario dont le succès/l'échec est du bruit.
Scénarios d'exécution négatifs
Ne vous arrêtez pas au happy path. Un workflow qui ne fonctionne que quand tout va bien est sous-testé. Ajoutez des scénarios pour les chemins malheureux que le trigger/source implique, et affirmons le comportement gracieux :
- Pas de données / not-found — source retourne vide ou 404 → workflow se termine sans envoyer une fausse alerte.
- Erreur source / timeout — source retourne 5xx ou expire → workflow n'échoue pas et n'émet pas une alerte « changé » factice.
- Réponse malformée — forme inattendue → traitée sans lever d'exception.
Formulez successCriteria comme l'absence de la mauvaise action (« aucune alerte n'est envoyée », « l'exécution se termine sans erreur ») autant que la présence de la bonne. Si la couche de simulation ne peut pas produire de façon fiable l'entrée défaillante, c'est de l'instabilité du harness — voir ci-dessus.
Validate
cd packages/@n8n/instance-ai
npx tsx -e "import {loadWorkflowTestCasesWithFiles} from './evaluations/data/workflows/index.ts'; console.log(loadWorkflowTestCasesWithFiles('<slug>')[0].fileSlug)"
Run locally
Nécessite une n8n live avec Instance AI activé (pas une instance par défaut) : une clé de modèle,
et un sandbox fonctionnel. Consultez les
notes de configuration pour la combinaison env exacte (le quick-start du README omet les parties auth-sandbox). Ensuite, depuis packages/@n8n/instance-ai :
pnpm eval:instance-ai --filter <slug> --keep-workflows --verbose