ITSkillsCenter
Intelligence Artificielle

LiveKit Agents 1.5 en Python : agent vocal pas-à-pas

9 min de lecture

📍 Guide principal de la série : Agents vocaux IA en 2026 : architecture, modèles, latence. Lire d’abord pour comprendre le contexte global, les choix d’architecture et le budget de latence end-to-end.

LiveKit Agents 1.5 (sortie en avril 2026) est devenu le framework Python de référence pour orchestrer un agent vocal en quelques dizaines de lignes : transport WebRTC géré, plugins natifs pour OpenAI, ElevenLabs, Cartesia, Deepgram, Silero VAD intégré, turn-detector contextuel et support natif du Model Context Protocol. Ce tutoriel construit pas à pas un premier agent fonctionnel sur votre poste local, en pipeline STT-LLM-TTS, capable de tenir une conversation cohérente avec un utilisateur connecté via le playground web officiel.

Prérequis

  • Python 3.10 ou supérieur (Python 3.12 recommandé pour 2026)
  • Un compte LiveKit Cloud (offre gratuite suffisante pour ce tutoriel)
  • Une clé API OpenAI active
  • Un microphone et un casque pour les tests
  • Connexion stable, idéalement filaire — la qualité du WebRTC dépend du réseau
  • Niveau attendu : Python intermédiaire, notions d’asyncio et de gestion d’environnement
  • Temps estimé : 60 à 90 minutes

Étape 1 — Préparer l’environnement Python

L’isolation des dépendances est non-négociable pour LiveKit Agents : le framework embarque CTranslate2, ONNX Runtime, et plusieurs SDK fournisseurs qui peuvent entrer en conflit avec un environnement global. On crée donc un environnement virtuel dédié et on y installe le paquet meta avec les extras correspondant aux plugins dont on a besoin.

python -m venv .venv
source .venv/bin/activate           # Linux/macOS
# .venv\Scripts\activate          # Windows PowerShell
pip install --upgrade pip
pip install "livekit-agents[openai,silero,turn-detector]~=1.5"
pip install python-dotenv

Le triplet [openai,silero,turn-detector] active trois plugins. openai apporte les classes STT, LLM et TTS qui parlent à l’API OpenAI. silero charge le VAD ONNX. turn-detector télécharge le modèle SmolLM v2 fine-tuné pour la prédiction de fin de tour. À la fin de la commande, pip list | grep livekit doit afficher au minimum livekit-agents, livekit-plugins-openai, livekit-plugins-silero et livekit-plugins-turn-detector.

Étape 2 — Récupérer les clés et configurer le fichier .env

L’agent a besoin de trois jeux d’identifiants : ceux de LiveKit pour rejoindre les salles temps réel, ceux d’OpenAI pour appeler les modèles, et l’URL du serveur LiveKit. On les centralise dans un fichier .env à la racine du projet, qu’on n’oubliera pas d’ajouter au .gitignore.

# .env
LIVEKIT_URL=wss://votre-projet.livekit.cloud
LIVEKIT_API_KEY=APIxxxxxxxx
LIVEKIT_API_SECRET=secret_xxxxxxxxxxxx
OPENAI_API_KEY=sk-xxxxxxxxxxxx

Les valeurs LIVEKIT_* proviennent de l’onglet Settings → Keys de votre projet LiveKit Cloud. La clé OpenAI s’obtient dans API keys de la console developers.openai.com avec le scope Realtime et Chat completions activés. Si echo $LIVEKIT_URL renvoie l’URL après source .env ou si load_dotenv() est exécuté en début de programme, l’authentification est prête.

Étape 3 — Le squelette du worker

Un agent LiveKit n’est rien d’autre qu’un worker qui se connecte à votre projet, écoute les rooms entrantes, et instancie une session par room. Le squelette minimal tient en une trentaine de lignes et expose deux fonctions canoniques : un entrypoint appelé pour chaque session, et un __main__ qui lance le worker.

# worker.py
from dotenv import load_dotenv
from livekit import agents
from livekit.agents import AgentSession, Agent, RoomInputOptions
from livekit.plugins import openai, silero
from livekit.plugins.turn_detector.multilingual import MultilingualModel

load_dotenv()

class Assistant(Agent):
    def __init__(self):
        super().__init__(
            instructions=(
                "Tu es un assistant vocal francophone, poli et concis. "
                "Tu réponds en deux phrases maximum sauf si on te demande "
                "explicitement de développer."
            ),
        )

async def entrypoint(ctx: agents.JobContext):
    session = AgentSession(
        stt=openai.STT(model="gpt-4o-mini-transcribe", language="fr"),
        llm=openai.LLM(model="gpt-4o-mini"),
        tts=openai.TTS(voice="alloy"),
        vad=silero.VAD.load(),
        turn_detection=MultilingualModel(),
    )
    await session.start(
        room=ctx.room,
        agent=Assistant(),
        room_input_options=RoomInputOptions(),
    )

if __name__ == "__main__":
    agents.cli.run_app(agents.WorkerOptions(entrypoint_fnc=entrypoint))

Trois choses méritent l’attention. La classe Assistant hérite d’Agent et porte les instructions système — c’est l’équivalent du system prompt. La fonction entrypoint est async et reçoit un JobContext qui contient la room. AgentSession agrège les briques : STT, LLM, TTS, VAD et turn detection. À ce stade, lancer python worker.py dev doit afficher « registered worker » et rester en attente d’une room.

Étape 4 — Brancher le pipeline STT-LLM-TTS

Le code de l’étape précédente cible déjà un pipeline pleinement fonctionnel, mais comprendre le rôle de chaque ligne aide à le tuner. openai.STT(model="gpt-4o-mini-transcribe", language="fr") envoie l’audio chunk par chunk à l’API et reçoit en retour une transcription incrémentale. Forcer la langue évite les faux positifs sur les premiers mots. openai.LLM(model="gpt-4o-mini") est le modèle de raisonnement, économique et suffisamment rapide pour la voix (premier token vers 250-350 ms). Pour de la qualité supérieure, remplacer par "gpt-4.1" en acceptant un surcoût de 10-20 ms.

# Variantes possibles dans AgentSession :
# llm=openai.LLM(model="gpt-4.1")               # qualité
# llm=openai.LLM(model="gpt-5-mini")            # raisonnement long
# tts=openai.TTS(voice="nova", instructions="ton chaleureux")
# tts=elevenlabs.TTS(voice_id="21m00Tcm4TlvDq8ikWAM", model_id="eleven_flash_v2_5")

Chaque substitution est un drop-in : la classe respecte le même contrat. La signature des plugins est documentée dans livekit-plugins-openai et livekit-plugins-elevenlabs. À l’exécution, on observera le premier audio sortant typiquement entre 700 et 1 100 ms après la fin de la phrase utilisateur — précisément le budget évoqué dans le guide d’introduction.

Étape 5 — Activer le VAD et le turn-detector contextuel

Le VAD seul provoque trop d’interruptions sur les pauses de réflexion : l’utilisateur prend une demi-seconde pour formuler, l’agent croit qu’il a fini, l’agent répond à mi-phrase. Le turn-detector contextuel basé sur SmolLM v2 lit la transcription en cours et prédit la probabilité de fin de tour avec un score sémantique, ce qui supprime la majorité de ces faux départs.

# Déjà présent dans le squelette de l'étape 3 :
vad=silero.VAD.load(),
turn_detection=MultilingualModel(),

# Réglages fréquents :
session = AgentSession(
    ...,
    min_endpointing_delay=0.5,   # silence minimal avant clôture
    max_endpointing_delay=6.0,   # silence maximal toléré
)

min_endpointing_delay est le délai minimum de silence avant que la session considère le tour clos, en secondes. Sous 0,3 s le risque d’interruption explose, au-dessus d’1 s la conversation semble lente. max_endpointing_delay protège contre le cas où l’utilisateur reste muet : l’agent reprend la main après ce délai. Tester avec et sans MultilingualModel rend la différence audible immédiatement, surtout sur les phrases qui contiennent une virgule ou un mot d’hésitation.

Étape 6 — Tester avec l’Agent Console LiveKit

LiveKit Cloud fournit l’Agent Console, un debugger web qui agit comme client WebRTC face à votre worker, sans avoir à coder un front. C’est l’outil de test naturel pour cette étape.

# Terminal 1 : lancer le worker
python worker.py dev

# Dans un navigateur, ouvrir :
# https://cloud.livekit.io/  (onglet Agents → Launch Console)
# Le navigateur ouvre l'Agent Console connectée à votre projet
# Cliquer "Connect" → autoriser le micro

Au démarrage, le worker affiche « registered worker ». Dans l’Agent Console, après Connect, on doit voir une connexion établie côté worker (« new job ») et entendre l’agent saluer dans les deux secondes. Si rien ne se passe, vérifier que LIVEKIT_URL dans le navigateur correspond à celle du worker, et que la console n’affiche pas d’erreur 401 (clé API mal recopiée).

Étape 7 — Affiner le system prompt et la voix

La qualité perçue d’un agent dépend autant de son prompt que de sa stack technique. Le prompt système doit être court, concret, et imposer un format de réponse adapté à la voix : phrases brèves, pas d’énumérations, pas de markdown, ton conforme au persona attendu.

class Assistant(Agent):
    def __init__(self):
        super().__init__(
            instructions=(
                "Tu es Aïda, assistante vocale d'un service de support technique. "
                "Tu réponds en français, en deux phrases maximum sauf si on te "
                "demande de développer. Ne lis jamais d'URL, jamais de listes "
                "à puces. Si tu ne sais pas, dis-le simplement."
            ),
        )

Trois règles tiennent presque toutes les améliorations qualitatives. Limiter explicitement la longueur de réponse — la voix supporte mal les pavés. Interdire les structures écrites — listes, code, URL longues — qui sonnent mal une fois oralisées. Donner un nom et un rôle au persona — la cohérence du ton sur la durée s’en trouve renforcée. Côté TTS, tester deux ou trois voix permet souvent de gagner plus en perception qu’en optimisant la latence d’une centaine de millisecondes.

Étape 8 — Mesurer la latence end-to-end

Tant qu’on ne mesure pas, on optimise à l’aveugle. LiveKit Agents 1.5 expose des métriques par session via session.metrics et permet de les pousser en logs ou en OpenTelemetry. La méthode la plus simple consiste à instrumenter manuellement le moment où l’utilisateur termine sa phrase et le moment où le premier sample audio est joué.

import time
from livekit.agents import metrics

@session.on("user_input_transcribed")
def _on_input(ev):
    session._t0 = time.perf_counter()

@session.on("agent_first_audio")
def _on_first_audio(ev):
    if hasattr(session, "_t0"):
        ms = (time.perf_counter() - session._t0) * 1000
        print(f"[latency] end-to-end = {ms:.0f} ms")

En sortie, un agent bien configuré sur la même région cloud que l’API affiche typiquement 700-900 ms. Au-delà de 1 100 ms, vérifier dans cet ordre : la région du projet LiveKit (Europe vs US), le modèle LLM (passer de gpt-4o à gpt-4o-mini fait souvent gagner 200 ms), et le streaming TTS (sans streaming, on attend la phrase complète avant de générer l’audio).

Erreurs fréquentes

Symptôme Cause probable Solution
L’agent ne se déclenche jamais Worker pas connecté, mauvais LIVEKIT_URL Vérifier python worker.py dev log « registered worker »
L’agent coupe l’utilisateur sur les pauses VAD seul, min_endpointing_delay trop court Activer MultilingualModel et passer à 0,6 s
Latence > 1 500 ms Région cloud lointaine, LLM trop gros Co-locer projet LiveKit et inférence dans la même région
Voix robotique TTS OpenAI tts-1 par défaut Passer sur tts-1-hd ou ElevenLabs Flash v2.5
Erreur 401 OpenAI Clé sans scope Realtime, ou crédit épuisé Régénérer la clé, vérifier la facturation
Worker plante après 10 minutes Fuite mémoire ONNX si VAD non libéré Mettre à jour livekit-plugins-silero >= 0.7

Dans la continuité

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité