Aller au contenu principal

LiveKit

Le package @mastra/livekit connecte les agents Mastra au framework LiveKit Agents. LiveKit exécute le pipeline audio (détection d’activité vocale, transcription de la parole, détection des tours de parole, synthèse vocale, interruption) et le package relie la génération des réponses à l’appel stream() d’un agent Mastra.

Consultez Voix en temps réel pour découvrir la configuration et les concepts.

Le package comporte trois points d’entrée :

createLiveKitWorker()
Lien direct vers createlivekitworker

Construit une définition d’agent LiveKit qui répond aux sessions vocales avec des agents Mastra. Utilisez-la comme export par défaut du fichier d’entrée de votre worker.

src/mastra/voice-worker.ts
import { fileURLToPath } from 'node:url'
import { createLiveKitWorker, runLiveKitWorker } from '@mastra/livekit/worker'
import { mastra } from './index'

export default createLiveKitWorker({
mastra,
agent: 'support',
stt: 'deepgram/nova-3',
tts: 'cartesia/sonic-3',
turnDetection: 'multilingual',
})

if (process.argv[1] === fileURLToPath(import.meta.url)) {
runLiveKitWorker({ entry: import.meta.url, agentName: 'mastra-voice' })
}

Options
Lien direct vers Options

mastra:

Mastra
L’instance Mastra dont les agents gèrent les sessions vocales.

agent?:

string | (args) => string | Agent | Promise<string | Agent>
Agent Mastra qui répond à chaque session : une clé ou un identifiant d’agent fixe, ou un résolveur appelé à chaque session avec les métadonnées de dispatch et le contexte de tâche. Utilise par défaut l’agentId des métadonnées de dispatch.

workflow?:

string | Workflow | (args) => string | Promise<string>
Génère la réponse de chaque tour avec un workflow Mastra plutôt qu’avec un agent : une instance Workflow, une clé ou un identifiant de workflow fixe, ou un résolveur qui renvoie un identifiant de workflow par session. Le workflow s’exécute une fois jusqu’à son terme à chaque tour (sans suspension ni reprise). Mutuellement exclusif avec agent ; nécessite workflowInput.

workflowInput?:

(args: VoiceTurnContext & { metadata }) => unknown | Promise<unknown>
Convertit un tour en inputData du workflow. Requis lorsque workflow est défini. Un mappage sans état qui transmet la transcription complète à chaque tour évite de conserver l’état de la conversation dans le workflow.

replyStep?:

string
Diffuse uniquement le texte de l’identifiant de cette étape du workflow. Par défaut, inclut chaque étape qui écrit dans son writer.

resultText?:

(result: unknown) => string | undefined
Solution de repli lorsque le workflow ne diffuse aucun texte via writer : déduit la réponse prononcée du résultat final de l’exécution.

generate?:

VoiceReplyGenerator
Échappatoire de plus bas niveau : fournissez directement n’importe quel générateur de réponses (workflow personnalisé, pont distant, etc.).

stt?:

STT | string
Transcription de la parole : une instance de plugin LiveKit ou une chaîne de modèle d’inférence telle que 'deepgram/nova-3'. Pour une sélection par appel, définissez le résolveur configuration.stt ; il est prioritaire, cette option servant de repli.

tts?:

TTS | string
Synthèse vocale : une instance de plugin LiveKit ou une chaîne de modèle d’inférence telle que 'cartesia/sonic-3'. Pour une sélection par appel, définissez le résolveur configuration.tts ; il est prioritaire, cette option servant de repli.

vad?:

VAD | 'silero' | false
= 'silero'
Détection d’activité vocale. 'silero' charge le VAD Silero depuis @livekit/agents-plugin-silero pendant le préchauffage. Transmettez votre propre instance, ou false pour désactiver cette fonction.

turnDetection?:

'multilingual' | 'english' | TurnDetectionMode
Détection de fin de tour. 'multilingual' et 'english' chargent le détecteur sémantique de tours de LiveKit depuis @livekit/agents-plugin-livekit. Les autres valeurs, telles que 'vad', 'stt' ou 'manual', sont transmises telles quelles.

turnHandling?:

Partial<TurnHandlingOptions>
Réglage de la gestion des tours : délais de détection de fin, sensibilité aux interruptions et génération anticipée. Le worker désactive preemptiveGeneration sauf si cette option est définie ici ; chaque tentative anticipée réexécute l’agent Mastra et conserve un doublon du message utilisateur.

sessionOptions?:

Partial<AgentSessionOptions>
Options LiveKit AgentSession supplémentaires fusionnées avec celles construites par cet utilitaire.

memory?:

false | ((args) => { thread, resource } | false)
Mappage de la mémoire. Utilise par défaut { thread: metadata.threadId ?? nom de la salle, resource: metadata.resourceId ?? thread } lorsque la mémoire est configurée pour l’agent résolu. Transmettez false pour le désactiver, ou une fonction pour le personnaliser.

toolFeedback?:

(toolCall) => string | undefined
Appelé lorsque l’agent Mastra lance un appel d’outil au milieu d’une réponse. Renvoyez une courte phrase à prononcer pendant l’exécution de l’outil.

onTurnComplete?:

(ctx: VoiceTurnCompleteContext) => void | Promise<void>
Appelé une fois par tour après la fin de la diffusion de la réponse vers la synthèse vocale. S’exécute hors du chemin audio et n’est pas attendu. Le contexte contient la réponse produite (text, toolCalls, interrupted, usage) et le mappage de mémoire résolu.

configuration?:

LiveKitWorkerConfiguration
Configuration regroupée de la conversation et de la conformité : message d’accueil et divulgation de l’IA, exigences de consentement, raccrochage initié par l’agent et sélection STT/TTS par appel.
LiveKitWorkerConfiguration

greeting?:

GreetingConfiguration
Message d’accueil et divulgation de l’IA : text (chaîne fixe ou résolveur par appel pour des messages propres à chaque locataire), allowInterruptions, awaitPlayout, persist et nouvelle divulgation périodique via repeatEvery et repeatText.

consentPolicy?:

ConsentConfiguration
Politique de consentement de l’appel, sous forme d’exigences nommées (à commencer par summaryStorage). Elle est uniquement déclarative : le worker ne bloque rien par lui-même. Enregistrez les consentements à l’exécution avec createConsentTool et appliquez-les dans votre propre code ; la politique déclarée est exposée dans onCallEnd pour permettre une vérification croisée.

endCall?:

EndCallConfiguration
Raccrochage initié par l’agent : le worker surveille à chaque tour l’outil de fin d’appel (à associer à createEndCallTool), attend la fin de la lecture des derniers mots de l’agent, puis se déconnecte en exécutant onCallEnd avant de terminer.

stt?:

(context: VoiceCallContext) => STT | string | undefined
Transcription de la parole par appel : résolveur invoqué une fois par appel (après la connexion) avec { metadata, requestContext, roomName, ctx }, qui renvoie toute valeur acceptée par l’option stt de premier niveau. Renvoyez undefined pour revenir à la valeur stt de premier niveau. Mettez les instances de plugin en cache entre les appels ; le résolveur s’exécute pendant la configuration de l’appel.

tts?:

(context: VoiceCallContext) => TTS | string | undefined
Synthèse vocale par appel : résolveur invoqué une fois par appel (après la connexion) avec { metadata, requestContext, roomName, ctx }, qui renvoie toute valeur acceptée par l’option tts de premier niveau — une voix ou une langue par locataire. Renvoyez undefined pour revenir à la valeur tts de premier niveau. Mettez les instances de plugin en cache entre les appels.

greeting?:

string
Message d’accueil statique prononcé au démarrage de la session. Obsolète : préférez configuration.greeting.text.

persistGreeting?:

boolean
= true
Enregistre le message d’accueil prononcé dans le thread de mémoire en tant que message de l’assistant, afin que le thread enregistré constitue une transcription fidèle de l’appel. S’applique uniquement lorsqu’un message d’accueil est défini et que la mémoire est activée. Obsolète : préférez configuration.greeting.persist.

observability?:

boolean
= true
Trace chaque appel lorsque l’observabilité est configurée sur l’instance Mastra. Ouvre un span voice call par session : l’exécution de l’agent à chaque tour y est imbriquée, les métriques LiveKit de latence STT, TTS, de fin d’énoncé, VAD et LLM deviennent des spans enfants, et le span se ferme avec un récapitulatif de l’utilisation par modèle. Transmettez false pour désactiver cette fonction.

inputOptions?:

Partial<RoomInputOptions>
Options d’entrée de la salle LiveKit transmises à session.start().

outputOptions?:

Partial<RoomOutputOptions>
Options de sortie de la salle LiveKit transmises à session.start().

onSessionStart?:

(args: { session, ctx, agent, metadata }) => void | Promise<void>
Appelé après le démarrage de la session. Ajoutez ici des écouteurs d’événements ou déclenchez des réponses.

runLiveKitWorker()
Lien direct vers runlivekitworker

Démarre la CLI du worker LiveKit (sous-commandes dev, start et connect) pour un fichier d’entrée de worker. Appelez-la depuis le fichier qui exporte par défaut la définition du worker, avec une condition garantissant qu’elle ne s’exécute que lorsque le fichier est lancé directement (le worker crée un processus enfant par session, qui réimporte le même fichier). L’utilisation de cet utilitaire plutôt que de cli.runApp depuis @livekit/agents garantit que le runtime du worker et le pont partagent une même copie du SDK LiveKit.

Options
Lien direct vers Options

entry:

string | URL
Module d’entrée du worker dont l’export par défaut est la définition de l’agent. Transmettez import.meta.url.

agentName?:

string
= 'mastra-voice'
Nom de l’agent LiveKit pour un dispatch explicite.

serverOptions?:

Partial<ServerOptions>
ServerOptions LiveKit supplémentaires fusionnées avec celles construites par cet utilitaire.

pipeAgentReplyToWriter()
Lien direct vers pipeagentreplytowriter

Diffuse la réponse d’un agent Mastra dans le writer d’une étape du workflow sur le chemin de réponse du workflow. Cette fonction transmet les deltas de texte de l’agent, afin que la synthèse vocale commence avant que la réponse complète soit prête, ainsi que ses fragments d’appels d’outils, afin que toolFeedback se déclenche et que onTurnComplete reçoive la liste des outils. Ne rediriger que stream.textStream supprime silencieusement les appels d’outils. Transmettez le abortSignal de l’étape à agent.stream() afin qu’une interruption arrête rapidement la génération.

src/mastra/workflows/phone-conversation.ts
import { pipeAgentReplyToWriter } from '@mastra/livekit'

const generateResponse = createStep({
id: 'generateResponse',
// input and output schemas omitted
execute: async ({ inputData, mastra, writer, abortSignal }) => {
const stream = await mastra.getAgent('support').stream(inputData.turn, { abortSignal })
const reply = await pipeAgentReplyToWriter(stream, writer)
return { reply }
},
})

Renvoie : Promise<string>, le texte de réponse accumulé.

Paramètres
Lien direct vers Paramètres

agentStream:

AgentReplyStreamLike
Le flux renvoyé par agent.stream() — toute valeur exposant un itérable asynchrone fullStream.

writer:

WritableStream<unknown>
Le writer de l’étape du workflow.

chatContextToMessages()
Lien direct vers chatcontexttomessages

Convertit un contexte de chat LiveKit en messages simples acceptés par agent.stream(), en excluant les instructions et les appels de fonctions. Utilisez cette fonction dans workflowInput pour transmettre la transcription complète à un workflow sans état.

src/mastra/voice-worker.ts
import { createLiveKitWorker, chatContextToMessages } from '@mastra/livekit/worker'

export default createLiveKitWorker({
mastra,
workflow: 'phoneConversation',
workflowInput: ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }),
})

Renvoie : VoiceTurnMessage[], où chaque entrée est { role: 'system' | 'user' | 'assistant'; content: string; id?: string }.

MastraLLM
Lien direct vers mastrallm

Un plugin LLM LiveKit standard (llm.LLM) reposant sur un agent Mastra. Utilisez-le lorsque vous construisez vous-même la voice.AgentSession et souhaitez placer Mastra dans l’emplacement llm. createLiveKitWorker() constitue l’alternative gérée. Consultez Utiliser Mastra comme composant LLM pour choisir la solution appropriée.

Avec remote, le plugin diffuse chaque tour depuis votre serveur Mastra via HTTP à l’aide de Server-Sent Events (SSE). La boucle de l’agent, les outils et la mémoire s’exécutent côté serveur ; interrompre l’agent annule la génération côté serveur.

src/mastra/voice-worker-plugin.ts
import { voice } from '@livekit/agents'
import { MastraLLM } from '@mastra/livekit/plugin'

const session = new voice.AgentSession({
llm: new MastraLLM({
remote: { baseUrl: process.env.MASTRA_URL!, agentId: 'support' },
memory: { thread: callId, resource: userId },
}),
stt: 'deepgram/nova-3',
tts: 'cartesia/sonic-3',
// Required with `memory`: LiveKit enables preemptive generation by default.
turnHandling: { preemptiveGeneration: { enabled: false } },
})

Le plugin définit provider sur mastra et model sur l’identifiant de l’agent, afin que les métriques LiveKit et les adaptateurs de repli l’identifient comme n’importe quel autre LLM.

Options du constructeur
Lien direct vers Options du constructeur

Fournissez exactement une source de réponse : remote, agent ou generate.

remote?:

RemoteMastraAgentOptions
Serveur Mastra distant accessible via HTTP. Accepte les mêmes options de connexion que createRemoteAgentReplyGenerator() : baseUrl, agentId, apiPrefix, headers, fetch, timeoutMs, retries, body.

agent?:

Agent
Agent Mastra exécuté dans le processus. Permet de gérer la session sans second déploiement.

generate?:

VoiceReplyGenerator
Source de réponse personnalisée. Une source generate possède ses propres hooks ; les options toolFeedback, onToolCall et onTurnComplete ci-dessous s’appliquent uniquement aux sources remote et agent.

memory?:

{ thread: string; resource?: string } | false
= false
Persistance de la conversation, résolue par appel (par exemple à partir de l’identité de l’appelant SIP). Lorsqu’elle est définie, seuls les nouveaux messages depuis la dernière prise de parole de l’agent sont envoyés à chaque tour, et Mastra Memory fournit l’historique. Lorsqu’elle est omise, le contexte de chat LiveKit complet est envoyé à chaque tour.

requestContext?:

RequestContext | Record<string, unknown>
Contexte de requête transmis à la génération (locataire, numéro composé, etc.).

toolFeedback?:

(toolCall: VoiceToolCall) => string | undefined
Renvoie une courte phrase à prononcer pendant l’exécution d’un outil côté serveur.

onToolCall?:

(toolCall: VoiceToolCall) => void
Appelé au démarrage de chaque appel d’outil, au milieu du flux. Associez-le à runEndCall() pour implémenter votre propre processus de raccrochage initié par l’agent.

onTurnComplete?:

(ctx: VoiceTurnCompleteContext) => void | Promise<void>
Appelé une fois par tour après la fin de la diffusion de la réponse, hors du chemin audio et sans être attendu. Le contexte contient la réponse produite : text, toolCalls, interrupted et usage.
attention

N’associez pas memory à l’option preemptiveGeneration de la session, que LiveKit active par défaut dans les sessions que vous construisez vous-même. Un tour spéculatif qui se termine avant que LiveKit ne l’abandonne conserve dans le thread un message utilisateur et une réponse jamais prononcée. Définissez turnHandling: { preemptiveGeneration: { enabled: false } } sur la session. Le mode sans état (sans memory) fonctionne avec la génération anticipée.

Exécution des outils sur l’agent Mastra
Lien direct vers Exécution des outils sur l’agent Mastra

Les outils sont définis et exécutés côté serveur sur l’agent Mastra. Le plugin ne transmet jamais les définitions d’outils LiveKit : si la session fournit un toolCtx non vide, il consigne une seule fois un avertissement indiquant les outils ignorés. Chaque outil doit terminer son exécution côté serveur : un outil qui nécessite une approbation ou une exécution côté client fait échouer le tour avec une erreur descriptive au lieu de bloquer l’appel.

L’activité des outils parvient au worker via toolFeedback, onToolCall et onTurnComplete.

Instructions
Lien direct vers Instructions

LiveKit injecte, depuis votre voice.Agent, ses instructions dans le contexte de chat de chaque requête. Le plugin les supprime, car les instructions propres à l’agent Mastra côté serveur font autorité. Pour modifier le prompt, modifiez l’agent Mastra.

Tours interrompus
Lien direct vers Tours interrompus

Lorsque l’utilisateur interrompt une réponse :

  1. Le plugin annule le flux. Le serveur interrompt la génération et ne conserve rien de ce tour.
  2. LiveKit enregistre dans son contexte de chat la partie effectivement entendue par l’utilisateur, en la marquant comme interrompue.
  3. Au tour suivant, le plugin renvoie ce fragment entendu uniquement, placé avant le nouveau message utilisateur, afin que le thread de mémoire soit complété rétroactivement pour correspondre à l’appel. Les messages contiennent les identifiants de message LiveKit et le serveur élimine les doublons par identifiant ; les nouvelles tentatives et les renvois restent donc idempotents.

Si un utilisateur raccroche immédiatement après avoir interrompu la réponse, ce dernier fragment n’est pas enregistré. Lorsque la transcription doit l’inclure, effectuez immédiatement la réconciliation à partir de l’événement de session ; grâce à l’identifiant de message partagé, le renvoi au tour suivant effectue une mise à jour ou une insertion plutôt qu’une duplication :

src/mastra/voice-worker-plugin.ts
import { voice } from '@livekit/agents'
import { MastraClient } from '@mastra/client-js'

const client = new MastraClient({ baseUrl: process.env.MASTRA_URL! })

session.on(voice.AgentSessionEventTypes.ConversationItemAdded, ({ item }) => {
if (item.type !== 'message' || item.role !== 'assistant' || !item.interrupted) return
void client.saveMessageToMemory({
agentId: 'support',
messages: [
{
id: item.id,
threadId: callId,
resourceId: userId,
role: 'assistant',
content: item.textContent ?? '',
type: 'text',
createdAt: new Date(),
},
],
})
})

Métriques d’utilisation
Lien direct vers Métriques d’utilisation

Lorsque le serveur communique l’utilisation des tokens pour un tour, le plugin la transmet à LiveKit. Les événements metrics_collected de la session contiennent ainsi le délai avant le premier token, la durée et le nombre de tokens, comme pour tout plugin LLM. Le même objet d’utilisation (promptTokens, completionTokens, promptCachedTokens, totalTokens) est transmis à onTurnComplete sous la forme result.usage.

Erreurs et délais d’expiration
Lien direct vers Erreurs et délais d’expiration

Le transport lève les types APIError de LiveKit (APIStatusError, APIConnectionError, APITimeoutError), de sorte que la politique de nouvelle tentative de la session (connOptions.maxRetry) et le basculement de FallbackAdapter fonctionnent sans modification. Un tour n’est jamais retenté après son premier token : mieux vaut qu’une réponse vocale échoue rapidement plutôt qu’elle soit rejouée après avoir été entendue en partie.

Un mécanisme de surveillance de la connexion et du premier token utilise le connOptions.timeoutMs de la session (10 secondes par défaut). Ainsi, un serveur qui accepte la connexion sans jamais diffuser de contenu ne peut pas provoquer un silence indéfini.

Si le serveur Mastra tombe en panne pendant un appel, chaque tentative de réponse échoue avec une erreur typée après ses nouvelles tentatives, et LiveKit ferme la session après plusieurs échecs consécutifs. Rétablissez le serveur avant d’épuiser ce quota pour que l’appel reprenne au tour suivant.

Contenu des messages
Lien direct vers Contenu des messages

L’extraction des messages est limitée au texte : le contenu des images est ignoré et le contenu audio est inclus uniquement par l’intermédiaire de sa transcription. Les pipelines vocaux ne sont pas affectés, mais les éléments que vous injectez vous-même dans le contexte de chat doivent contenir du texte.

createRemoteAgentReplyGenerator()
Lien direct vers createremoteagentreplygenerator

Construit un générateur de réponses qui exécute la boucle de l’agent sur un serveur Mastra distant via HTTP/SSE. MastraLLM l’utilise en interne dans son mode remote. Utilisez-le directement par l’intermédiaire de createLiveKitWorker et de son option generate pour exécuter le worker complet avec un serveur distant :

src/mastra/voice-worker.ts
import { createLiveKitWorker, createRemoteAgentReplyGenerator } from '@mastra/livekit/worker'
import { mastra } from './index'

export default createLiveKitWorker({
mastra, // local instance for logger and worker config; replies come from the remote server
generate: createRemoteAgentReplyGenerator({
baseUrl: process.env.MASTRA_URL!,
agentId: 'support',
}),
memory: ({ metadata, roomName }) => ({ thread: metadata.threadId ?? roomName }),
stt: 'deepgram/nova-3',
tts: 'cartesia/sonic-3',
})

Sur le chemin generate, les options toolFeedback et onTurnComplete au niveau du worker ne s’appliquent pas, et la détection de fin d’appel du worker ne se déclenche pas ; transmettez plutôt les hooks au générateur.

L’annulation d’un tour (interruption) met fin à la requête HTTP, ce qui annule la génération sur le serveur. Les erreurs sont levées sous forme de types APIError LiveKit. L’option retries s’applique uniquement aux tentatives de connexion initiales. Un tour n’est jamais retenté après son premier fragment.

Renvoie : VoiceReplyGenerator.

Options
Lien direct vers Options

baseUrl:

string
URL de base du serveur Mastra distant, par exemple https://my-app.example.com.

agentId:

string
Clé enregistrée ou identifiant de l’agent sur l’instance Mastra distante.

apiPrefix?:

string
= '/api'
Préfixe de chemin de l’API Mastra.

headers?:

Record<string, string> | () => Record<string, string> | Promise<Record<string, string>>
En-têtes statiques, ou résolveur invoqué à chaque tour — par exemple pour générer un nouveau token d’autorisation.

fetch?:

typeof fetch
= globalThis.fetch
Implémentation de fetch injectable pour les tests ou les proxys.

timeoutMs?:

number
= 10000
Délai d’expiration de la connexion et du premier token, en millisecondes. Lors d’une utilisation via MastraLLM, prend plutôt par défaut la valeur connOptions.timeoutMs de la session.

retries?:

number
= 2
Tentatives de reconnexion initiale, uniquement avant le premier fragment. Lors d’une utilisation via MastraLLM, la session LiveKit gère les nouvelles tentatives et cette valeur est forcée à 0.

body?:

Record<string, unknown>
Champs supplémentaires fusionnés dans le corps de chaque requête de flux.

toolFeedback?:

(toolCall: VoiceToolCall) => string | undefined
Renvoie une courte phrase à prononcer pendant l’exécution d’un outil côté serveur.

onToolCall?:

(toolCall: VoiceToolCall) => void
Appelé au démarrage de chaque appel d’outil, au milieu du flux.

onTurnComplete?:

(ctx: VoiceTurnCompleteContext) => void | Promise<void>
Appelé une fois par tour après la fin de la diffusion de la réponse, hors du chemin audio.

speakGreeting()
Lien direct vers speakgreeting

Prononce un message d’accueil dans une session que vous gérez, en respectant les options d’interruption et de lecture. Renvoie le SpeechHandle LiveKit, ou undefined en l’absence de texte d’accueil. createLiveKitWorker() l’utilise en interne pour sa configuration greeting.

import { speakGreeting } from '@mastra/livekit/worker'

await speakGreeting(session, {
text: "You've reached support. You're speaking with an AI assistant.",
allowInterruptions: false,
awaitPlayout: true,
})

Paramètres
Lien direct vers Paramètres

session:

voice.AgentSession
Session dans laquelle prononcer le message.

greeting:

{ text?: string; allowInterruptions?: boolean; awaitPlayout?: boolean }
Texte du message d’accueil et options de lecture. Lorsque awaitPlayout vaut true, la promesse renvoyée est résolue une fois la lecture du message d’accueil terminée (ou interrompue).

waitForAgentDoneSpeaking()
Lien direct vers waitforagentdonespeaking

Est résolue dès que l’agent ne produit ni ne lit plus de réponse : son état a quitté thinking et speaking. Elle est résolue immédiatement si l’agent est déjà inactif et, par sécurité, toujours dans le délai maxWaitMs (30 secondes par défaut). Utilisez-la avant de mettre fin à une session pour que les derniers mots soient lus au lieu d’être coupés.

import { waitForAgentDoneSpeaking } from '@mastra/livekit/worker'

await waitForAgentDoneSpeaking(session)

runEndCall()
Lien direct vers runendcall

Met fin à l’appel lorsque l’agent demande à raccrocher. Cette fonction attend les derniers mots de l’agent et prononce, sans interruption, un message final facultatif. Elle supprime ensuite la salle et raccroche l’appelant, y compris les appelants SIP. La tâche s’arrête avec ses callbacks enregistrés.

Associez-la à MastraLLM par l’intermédiaire de son onToolCall et à un outil de fin d’appel sur l’agent côté serveur afin de recréer le raccrochage initié par l’agent dans une session que vous gérez :

src/mastra/voice-worker-plugin.ts
import { MastraLLM } from '@mastra/livekit/plugin'
import { DEFAULT_END_CALL_TOOL, runEndCall } from '@mastra/livekit/worker'

let ending = false

const llm = new MastraLLM({
remote: { baseUrl: process.env.MASTRA_URL!, agentId: 'support' },
onToolCall: ({ toolName }) => {
if (toolName !== DEFAULT_END_CALL_TOOL || ending) return
ending = true
void runEndCall(session, ctx, {}, console)
},
})

Les constantes exportées DEFAULT_END_CALL_TOOL ('endCall'), DEFAULT_END_CALL_REASON et DEFAULT_END_CALL_MAX_WAIT_MS (30000) contiennent les valeurs par défaut.

Paramètres
Lien direct vers Paramètres

session:

voice.AgentSession
Session dont l’agent termine ses derniers mots.

ctx:

JobContext
Contexte de tâche LiveKit utilisé pour supprimer la salle et arrêter la tâche.

config:

{ message?: string; reason?: string; maxWaitMs?: number; drainMs?: number }
Message final facultatif prononcé avant le raccrochage, motif d’arrêt à enregistrer, délai de sécurité pour attendre les derniers mots et délai de vidage après lecture (800 ms par défaut), qui permet au son mis en mémoire tampon chez l’appelant de finir d’être lu avant la suppression de la salle — le suivi de la lecture de LiveKit est local au worker ; raccrocher dès qu’il se termine coupe donc les adieux.

logger:

{ warn: (message: string, ...args: unknown[]) => void }
Reçoit des avertissements lorsque les étapes de fermeture échouent. Transmettez votre logger ou console.

createEndCallTool()
Lien direct vers createendcalltool

Construit l’outil Mastra qu’un agent appelle lorsqu’il souhaite mettre fin à l’appel. L’outil signale cette intention et peut effectuer des opérations de suivi facultatives. Le worker réalise le raccrochage proprement dit. L’outil se trouve dans le point d’entrée racine utilisable en toute sécurité côté serveur. Ajoutez-le aux agents définis dans le code serveur.

src/mastra/agents/support-agent.ts
import { Agent } from '@mastra/core/agent'
import { createEndCallTool } from '@mastra/livekit'

const supportAgent = new Agent({
id: 'support',
name: 'Support',
instructions:
'Help the caller. When everything is wrapped up, say goodbye and call endCall as your final action.',
model: 'openai/gpt-5-mini',
tools: { endCall: createEndCallTool() },
})

Avec createLiveKitWorker(), définissez configuration: { endCall: {} } : le worker surveille alors l’outil et raccroche. Dans une session que vous gérez, recréez le raccrochage avec runEndCall().

Options
Lien direct vers Options

id?:

string
= 'endCall'
Identifiant de l’outil que l’agent appelle pour mettre fin à l’appel. Doit correspondre au nom surveillé par le worker (la propriété configuration.endCall.tool du worker, ou votre propre vérification onToolCall).

description?:

string
Remplace la description présentée au modèle lorsqu’il décide d’appeler l’outil.

onEndCall?:

(request: { reason?: string; resourceId?: string; threadId?: string }) => void | Promise<void>
Hook de suivi appelé lorsque l’agent invoque l’outil — enregistrez le motif ou marquez l’appel comme résolu. Il s’exécute pendant le tour ; veillez à ce qu’il soit rapide. Il ne raccroche pas l’appel.

liveKitConnectionRoute()
Lien direct vers livekitconnectionroute

Renvoie une route d’API qui génère un token d’accès LiveKit et dispatche l’agent vocal dans la salle. Les frontends l’appellent pour rejoindre une session.

src/mastra/index.ts
import { Mastra } from '@mastra/core/mastra'
import { liveKitConnectionRoute } from '@mastra/livekit'

export const mastra = new Mastra({
server: {
apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })],
},
})

La route accepte un corps JSON comportant les champs facultatifs agentId, threadId et resourceId, et répond avec { serverUrl, roomName, participantName, participantToken }. Par défaut, le threadId correspond au nom de salle généré.

Options
Lien direct vers Options

path?:

string
= '/voice/livekit/connection-details'
Chemin de la route.

serverUrl?:

string
= process.env.LIVEKIT_URL
URL du serveur LiveKit.

apiKey?:

string
= process.env.LIVEKIT_API_KEY
Clé d’API LiveKit.

apiSecret?:

string
= process.env.LIVEKIT_API_SECRET
Secret d’API LiveKit.

agentName?:

string
= 'mastra-voice'
Nom de l’agent LiveKit pour un dispatch explicite. Doit correspondre à l’agentName du worker.

ttl?:

string | number
= '15m'
Durée de vie du token.

requiresAuth?:

boolean
= true
Indique si la route nécessite une authentification.

roomName?:

string | (args) => string
Nom de la salle ou fonction qui le déduit de la requête.

participantIdentity?:

string | (args) => string
Identité du participant ou fonction qui la déduit de la requête.

metadata?:

(args) => LiveKitSessionMetadata | Promise<LiveKitSessionMetadata>
Construit les métadonnées de session transmises au worker. Par défaut, transmet agentId, threadId et resourceId depuis le corps de la requête.

dispatchVoiceSession()
Lien direct vers dispatchvoicesession

Dispatche par programmation un agent vocal Mastra dans une salle LiveKit, pour les sessions initiées par le serveur telles que les appels sortants.

import { dispatchVoiceSession } from '@mastra/livekit'

await dispatchVoiceSession({
roomName: 'support-call-42',
agentName: 'mastra-voice',
metadata: { agentId: 'support', threadId: 'thread-42' },
})

Options
Lien direct vers Options

roomName:

string
Salle dans laquelle dispatcher l’agent. Créée à la demande.

agentName?:

string
= 'mastra-voice'
Doit correspondre à l’agentName du worker.

metadata?:

LiveKitSessionMetadata
Métadonnées de session : agentId, threadId, resourceId, requestContext.

serverUrl?:

string
= process.env.LIVEKIT_URL
URL du serveur LiveKit.

apiKey?:

string
= process.env.LIVEKIT_API_KEY
Clé d’API LiveKit.

apiSecret?:

string
= process.env.LIVEKIT_API_SECRET
Secret d’API LiveKit.

LiveKitSessionMetadata
Lien direct vers livekitsessionmetadata

Métadonnées transmises du serveur Mastra au worker par le dispatch de tâche LiveKit.

agentId?:

string
Agent Mastra à exécuter, désigné par sa clé enregistrée ou son identifiant.

threadId?:

string
Identifiant du thread de mémoire. Utilise par défaut le nom de la salle LiveKit.

resourceId?:

string
Identifiant de la ressource de mémoire, généralement celui de l’utilisateur final.

requestContext?:

Record<string, unknown>
Entrées d’un objet simple restaurées dans un RequestContext pour l’exécution de l’agent.

Les métadonnées sont transmises sous forme de chaîne JSON. liveKitConnectionRoute() et dispatchVoiceSession() les sérialisent pour vous ; utilisez serializeSessionMetadata(metadata) lorsque vous effectuez le dispatch depuis votre propre code, ou écrivez directement le JSON dans une configuration côté LiveKit, telle qu’une règle de dispatch SIP. Les entrées de requestContext sont accessibles à chaque tour de l’appel dans les instructions définies à l’exécution, les outils et les processeurs d’entrée de l’agent.