Tester les agents LiveKit
Les tests au niveau du tour sont la vérification la plus économique et durable qu'un agent puisse avoir. Ils s'exécutent dans la suite existante de l'utilisateur, en mode texte, et ils sont assez rapides pour chaque commit. Les noms et signatures des helpers du framework changent, consulte-les avec reading-livekit-docs avant d'écrire, et utilise la page de documentation sur les tests pour tous les détails d'API que cette skill omet.
Chaque test a la même structure : démarrer une session de test avec l'agent à tester, exécuter un tour utilisateur, et vérifier les événements que ce tour a produits.
Ce qu'un test vérifie
Un tour produit une séquence d'événements. Un tour simple est un message. Un tour plus typique est un appel d'outil, son résultat, peut-être un handoff, puis un message. Tu écris le test en parcourant cette séquence dans l'ordre, en vérifiant chaque événement, puis en vérifiant que le tour n'a rien d'autre.
Il y a trois sortes de vérifications, et l'essentiel de cette skill consiste à savoir laquelle utiliser.
Les vérifications structurelles contrôlent les rôles des messages, qu'un outil a été appelé, ses arguments, ce qu'il a retourné, et qu'un handoff vers un agent spécifique a eu lieu. Elles sont déterministes et échouent pour exactement une raison, donc préfère-les.
Les vérifications jugées utilisent un helper LLM-judge qui donne un message et une chaîne d'intention à un modèle et demande s'ils correspondent. Utilise-les pour le contenu d'une réponse, que tu ne peux pas vérifier exactement. Décris l'intention par le résultat (« dit à l'utilisateur que la réservation est confirmée et donne l'heure »), pas par le libellé.
Les vérifications pour la conversation complète utilisent un helper judge-group qui exécute plusieurs judges intégrés simultanément sur l'historique de chat complet et agrège leurs verdicts. Les judges intégrés couvrent des dimensions comme l'ancrage, la pertinence, la sécurité, l'accomplissement de la tâche et l'utilisation d'outils ; la doc énumère l'ensemble actuel. Utilise ceci quand la question s'étend sur plusieurs tours.
Règles pratiques :
- Vérifie la structure en premier et juge seulement ce qui reste. Une vérification jugée qui aurait pu être structurelle est plus lente et plus instable.
- Ferme le tour. Vérifie qu'il n'y a pas d'événements supplémentaires. Sinon, un test peut réussir tandis que l'agent fait aussi quelque chose que tu n'as pas voulu.
- Un comportement par test. Quand un test qui vérifie six choses échoue, il te dit très peu de choses.
Mocker les outils
Les tests ne doivent pas frapper de vrais backends, car cela rend une suite lente et non-déterministe. Remplace les outils de l'agent à tester et retourne des valeurs fixes.
Deux points au-delà de l'API :
- Mocker les échecs ainsi que les succès. Retourner une erreur d'un mock fait que l'outil lève une exception, ce qui te permet de tester ce que l'agent dit quand un backend est en panne. La plupart des agents manquent ce test, et c'est le comportement que les utilisateurs remarquent le plus.
- La portée compte. Par défaut, les mocks s'appliquent dans un bloc autour de tes propres appels
run(), ce qui est ce qu'un test a besoin. Une forme session-scoped existe aussi pour une session qui s'exécute seule et a besoin que les mocks soient actifs pendant toute sa durée de vie. Les points d'entrée de simulation utilisent cette forme, les tests ne le font pas. Voirwriting-livekit-scenarios.
Le mocking change seulement l'exécution. Le modèle voit toujours les vrais schémas d'outils, donc la sélection d'outils est toujours testée.
Multi-tour et historique ensemencé
Il y a deux façons de tester un comportement qui dépend des tours précédents :
- Exécuter les tours. Chaque tour s'ajoute à l'historique de conversation, donc le deuxième tour voit le premier. Utilise ceci quand le chemin compte : collecter des détails entre les tours, l'utilisateur changeant d'avis en cours de flux, un handoff portant du contexte.
- Ensemencer l'historique. Construis un historique de chat et donne-le à l'agent pour commencer à l'état qui t'intéresse. Utilise ceci quand les tours de configuration ne sont pas ce que tu testes. C'est plus rapide et moins fragile que de rejouer cinq tours pour atteindre le sixième.
Que tester
À peu près dans l'ordre de la valeur :
- Le comportement que l'utilisateur a demandé. Chaque agent a besoin au moins de ceci.
- Invocation d'outil : le bon outil avec les bons arguments pour une demande représentative.
- Échec d'outil : ce que l'agent dit quand un outil génère une erreur ou ne retourne rien.
- Refus et limites : l'agent refuse ce qu'il devrait refuser et n'invente pas de données qu'il ne peut pas avoir. Le refus est la condition de réussite.
- Handoffs : la transition se déclenche quand elle devrait, et l'agent suivant a ce dont il a besoin.
- Chaque bug que tu as corrigé. Sans un test, un bug corrigé peut revenir inaperçu.
Trois sortes de preuves, bien distinctes
Une suite de tests pour un agent qui fait des choses — réserve, édite, confirme — a besoin de trois sortes de tests, et les confondre, c'est comment une suite verte expédie un agent cassé :
- Les tests d'application déterministes prouvent les gardes, les no-ops, les valeurs vides vs inconnues, les corrections, l'échec du stockage et les nouvelles tentatives, directement contre le noyau d'application. Rapides, exacts, pas de modèle.
- Les tests réels du SDK avec un fournisseur scriptable prouvent le câblage d'événements et la plomberie d'outils : que l'écouteur se déclenche, que l'outil reçoit ce que la session envoie. Un fournisseur scriptable prouve la mécanique, jamais la compréhension du langage — ses phrases exactes sont des fixtures, pas des exigences.
- Les tests en langage ordinaire avec le modèle réel prouvent que le modèle peut accomplir la tâche à partir de la façon dont les appelants parlent réellement : paraphrases absentes du prompt, corrections mélangées avec l'accord, la même courte réponse répondant à des questions différentes.
Les raccourcis qui ressemblent à des tests et ne le sont pas : appeler un helper ou remplir un état privé au lieu de conduire l'interaction ; dire à l'appelant du test quel outil nommer ; mocker la mutation même dont la correction est testée ; comparer la sortie seulement avec l'exporteur propre de l'application ; réessayer un tour échoué jusqu'à ce qu'il réussisse ; supprimer l'assertion qui a échoué.
N'écris pas de tests qui punissent un comportement correct
Le test d'agent mauvais le plus courant affirme que l'agent fait quelque chose qu'il ne devrait pas : énonce des données qu'il ne peut pas connaître, donne une recommandation médicale, juridique ou financière spécifique, ou complète un flux qui aurait dû être bloqué. Si l'agent ne peut réussir que en se mal comportant, corrige le test.
Pour une barrière de sécurité, la réussite est que l'agent refuse, escalade ou décline d'inventer quelque chose. Écris l'assertion de cette façon.
Où ceci s'inscrit
- Exploration interactive pendant la construction →
debugging-livekit-agents. Boucle plus rapide, aucune assertion conservée. - Au niveau du tour, déterministe, à chaque commit → ici. Vérification durable la moins chère.
- Conversations complètes notées par un utilisateur simulé, avant une sortie →
running-livekit-simulations. Plus cher, et capture le comportement émergent que les tests au niveau du tour manquent.
Quand une simulation continue à échouer de la même façon, le bug est généralement au niveau du tour. Écris un test pour cela ici, qui épingle la cause plus précisément et la capture plus tôt.
Skills connexes
- Surface d'API actuelle :
reading-livekit-docs - Trouver le bug en premier :
debugging-livekit-agents - Simulations, y compris état ensemencé et mocks session-scoped :
writing-livekit-scenarios,running-livekit-simulations