operating-livekit-agents

Par livekit · agent-skills

Déploie et exploite un agent LiveKit en production : livraison d'une version sur LiveKit Cloud et rollback, secrets et configuration, modèle de processus worker et prewarming, async sécurisé dans les processus worker, timeouts des providers et dégradation, arrêt gracieux, mises à jour du SDK, et observabilité. À utiliser quand l'utilisateur dit « déployer mon agent », « rollback du déploiement », « suivre les logs de l'agent », « le premier appel après un redémarrage est lent », « attaché à une autre boucle / event loop is closed », « prewarm le VAD », « s'arrêter sans couper les appels », « mettre à jour livekit-agents en toute sécurité », « corréler les logs par session », ou modifie une base de code d'agent déjà en production. Pas pour concevoir l'agent (building-livekit-agents) ou reproduire localement une mauvaise conversation (debugging-livekit-agents).

npx skills add https://github.com/livekit/agent-skills --skill operating-livekit-agents

Exploiter les agents LiveKit

Tout ce qui vient après que l'agent fonctionne : mettre une version sur LiveKit Cloud, la garder rapide et opérationnelle sous charge réelle, et la modifier sans casser ce qui tourne déjà. Les commandes se trouvent sous lk agent ; consultez lk agent --help et l'aide de chaque sous-commande plutôt que de faire confiance à cette skill pour les flags — elle refuse volontairement de les répéter. reading-livekit-docs contient la documentation sur le déploiement et l'observabilité.

Déployer vers LiveKit Cloud

La structure reste stable même si les flags évoluent :

  1. Un répertoire de projet est lié à un agent par un fichier de config que la CLI crée (livekit.toml). Les commandes lancées depuis ce répertoire trouvent l'agent sans id.
  2. L'agent est livré sous forme de conteneur. La CLI peut générer un Dockerfile pour le projet, ou vous apportez une image précompilée. Lancez la commande de démarrage du conteneur en local (lk agent start) avant le premier déploiement — c'est le mode production, avec la journalisation de production et un drain à l'arrêt, et ce n'est pas ce que le mode dev exécute.
  3. Chaque déploiement crée une version et la déploie. status, versions et logs (les logs de build et de déploiement sont séparés) vous indiquent ce qui tourne et pourquoi un déploiement a échoué.
  4. Les secrets sont injectés comme variables d'environnement et gérés séparément du code — jamais intégrés à l'image ou commités. Changer les secrets redémarre l'agent.
  5. Rollback revient à une version antérieure. La rapidité dépend du plan ; la documentation le précise. Connaissez la commande de rollback avant d'en avoir besoin.

Après un déploiement, vérifiez avec les mêmes outils que vous utiliseriez sur l'agent de quelqu'un d'autre : status pour le déploiement, logs pour les premières minutes, et une vraie conversation — running-livekit-simulations peut exécuter un fichier de scénario contre l'agent déployé par nom, ce qui est le contrôle de bout en bout le moins coûteux pour vérifier que ce qui sert le trafic est ce que vous vouliez livrer.

Le modèle de processus worker

Les deux SDK exécutent les sessions dans des processus worker générés à partir d'un parent. Ne pas bien comprendre cela est la source la plus courante de bugs qui n'apparaissent qu'en production.

Le parent précharge ; les enfants héritent. Chargez les ressources coûteuses et en lecture seule — modèles VAD et détection de tour, clients persistants — une seule fois dans le parent via le hook de prewarm du SDK, et chaque session les hérite sans les recharger. Tout ce qui est partagé de cette façon doit être en lecture seule ou thread-safe ; muter l'état du parent depuis un enfant est un comportement indéfini. Ne préchargez pas l'état spécifique à une session, et ne préchargez pas ce qui coûte plus de mémoire qu'il n'en économise — chaque octet du parent se retrouve dans l'empreinte de chaque enfant. Ensuite, vérifiez que l'enfant utilise effectivement l'instance préchargée : l'erreur classique est de précharger un modèle et d'avoir le code de session charger une nouvelle copie de toute façon, rendant le prewarm inutile et le démarrage toujours lent.

Le framework possède la boucle d'événements. Ne créez jamais un nouveau runtime async dans un worker, et ne bloquez jamais sur un appel async depuis un constructeur synchrone pour forcer un résultat. Si l'initialisation nécessite du travail async, chargez en lazy au premier usage depuis une méthode déjà async, ou séparez la construction d'une étape initialize en attente. Quand vous voyez des erreurs sur des événements liés à une boucle différente, une boucle déjà en cours, des tâches détruites en attente, ou une boucle fermée qui ne peut pas être réutilisée, la cause est presque toujours l'une de ces deux choses — remontez à l'endroit où un runtime a été créé ou un chemin sync a attendu quelque chose.

Fournisseurs

STT, TTS, LLM, VAD et tout backend échouera en production : limites de débit, timeouts, surcharge, pannes. Définissez des timeouts — un appel qui pend est pire qu'un qui échoue rapidement. Distinguez les défaillances transitoires qui valent la peine d'être retentées des défaillances persistantes qui nécessitent un fallback ou une escalade. Dégradez vers une réponse parlée significative, jamais vers le silence. Journalisez les temps de réponse des fournisseurs, car une latence croissante est généralement le premier signe d'une panne.

Ajouter un fournisseur à un agent existant : vérifiez si le SDK a déjà un plugin avant d'en écrire un ; suivez la façon dont le codebase initialise déjà, configure et gère les erreurs pour ses autres fournisseurs ; passez sa config par le même pipeline ; et testez sous une latence réaliste, pas seulement des réponses en cas d'exécution réussie.

Performance : mesurez avant de changer quoi que ce soit

La métrique que les utilisateurs ressentent est le temps jusqu'au premier audio — du moment où l'appelant termine au moment où l'agent commence à parler. Décomposez-la avant d'optimiser : connexion, initialisation du fournisseur, première inférence, exécution d'outil. Observez la croissance du contexte sur un long appel ; un historique non borné signifie que chaque tour est plus lent que le précédent.

Les anti-patterns à rechercher :

  • I/O synchrone dans un contexte async. Un appel HTTP bloquant ou une lecture de fichier gèle l'audio pour chaque opération concurrente dans ce processus.
  • Chargement pendant un appel — un modèle ou une connexion établis au premier usage à l'intérieur d'une session est une latence que l'appelant entend. Déplacez-les vers le prewarm ou la configuration de session.
  • Contexte non borné sans résumé.
  • Chaque outil enregistré globalement indépendamment de la phase de conversation ; chaque définition coûte à chaque appel LLM.

L'endpointing et la détection de tour sont des paramètres d'ajustement, pas des valeurs par défaut à accepter. Trop agressif et l'agent interrompt les gens qui marquent une pause pour réfléchir ; trop prudent et chaque réponse semble tardive. Le bon paramètre dépend du cas d'usage — un agent de support traitant des questions complexes veut de la patience, un assistant réponses rapides veut de la vitesse. Mesurez avec des simulations audio (running-livekit-simulations note l'alternance des tours et la latence perçue) plutôt que par intuition.

Arrêt et mises à jour

En mode production le serveur drague lors d'un signal de terminaison : il cesse d'accepter de nouveaux jobs, termine ceux actifs jusqu'à un timeout de drain, puis se ferme. Deux choses cassent cela. Une période de grâce d'orchestrateur plus courte que le timeout de drain coupe les appels en plein milieu de phrase — alignez-les. Et le travail post-appel (écriture d'état, publication d'événements, finalisation d'enregistrements) non lié au cycle de vie du job est interrompu — assurez-vous qu'il se termine pendant le drain. Le mode dev n'a pas de drain, donc le comportement d'arrêt doit être testé en mode start.

Le SDK évolue rapidement et casse les choses entre les versions. Épinglez la version. Lisez le changelog avec reading-livekit-docs avant de mettre à jour. Mettez à jour sur une branche, lancez la suite de tests, puis ayez de vraies conversations et lancez la suite de simulations — certaines régressions n'apparaissent que dans le dialogue réel. Observez la latence et les taux d'erreur pendant les premières heures après le déploiement.

Observabilité

Trois choses rendent un incident de production traitable au lieu d'un mystère :

  • Chaque ligne de log porte l'id de session, ainsi un appel peut être tracé de bout en bout.
  • Les limites de phase sont chronométrées — connecté, première parole utilisateur, première réponse agent — afin que vous puissiez voir la latence est entrée, pas seulement que c'est le cas.
  • Les métriques des fournisseurs sont suivies séparément des logs d'application, donc un fournisseur qui se dégrade est visible sans creuser.

LiveKit Cloud fournit des logs d'agent, des insights de session et du tracing que vous pouvez exporter vers votre propre fournisseur d'observabilité ; la documentation décrit ce qui est disponible et comment l'intégrer.

Déboguer une panne en production

Classifiez d'abord, puis reproduisez :

  • Erreurs de boucle et tâche — le modèle de processus worker, ci-dessus. Trouvez où un runtime a été créé ou un chemin sync a attendu.
  • Timeouts fournisseur vs dégradation — un timeout unique est transitoire ; une tendance de latence croissante est systémique. Les logs de temps de réponse du fournisseur vous indiquent lequel.
  • Défaillances silencieuses d'outil — un outil qui a levé a été capturé par le framework et l'utilisateur a entendu une réponse vague ou rien. Les outils ont besoin d'une gestion d'erreur explicite qui retourne quelque chose que le modèle peut dire.
  • Instabilité de connexion — comprenez la reconnexion intégrée du SDK avant d'ajouter des retries par-dessus ; journalisez les changements d'état de connexion.

Puis prenez-le localement : reproduisez la conversation avec debugging-livekit-agents, épinglez la cause comme un test avec testing-livekit-agents, et si c'était une défaillance de conversation entière, ajoutez un scénario pour qu'il ne puisse pas revenir discrètement.

Modifier un codebase qui tourne déjà

Lisez d'abord la documentation et les conventions du projet — elles remplacent tout ce qui est général. Lisez deux ou trois modules comme celui que vous êtes sur le point d'ajouter avant de l'écrire, et suivez la façon dont ils sont initialisés, configurés, testés et intégrés au pipeline de configuration. Utilisez les fixtures de test et les patterns de mock qui existent déjà plutôt que d'en construire des parallèles ; une deuxième façon de faire quelque chose qui a déjà une façon confond tout contributeur futur. Mocké à la limite — l'appel du fournisseur, la base de données — et exercez la vraie logique du module.

Skills connexes

  • Concevoir l'agent en premier lieu : building-livekit-agents
  • Reproduire une mauvaise conversation localement : debugging-livekit-agents
  • Épingler un bug de production comme un test : testing-livekit-agents
  • Contrôles de bout en bout contre un agent déployé : running-livekit-simulations
  • Documentation de déploiement et d'observabilité, changelogs : reading-livekit-docs

Skills similaires