LiveKit
@mastra/livekit 套件會將 Mastra Agent 連接至 LiveKit Agents 框架。LiveKit 會執行音訊管線(語音活動偵測、語音轉文字、對話輪次偵測、文字轉語音、插話),而此套件會將回覆產生流程橋接至 Mastra Agent 的 stream() 呼叫。
設定方式與相關概念請參閱即時語音。
此套件有三個進入點:
@mastra/livekit:伺服器端 API,包括liveKitConnectionRoute()、dispatchVoiceSession()、pipeAgentReplyToWriter()、serializeSessionMetadata()和createEndCallTool()。請從 Mastra 伺服器程式碼匯入。此進入點絕不會載入 LiveKit Agents 執行階段。@mastra/livekit/worker:Worker 執行階段,包括createLiveKitWorker()、runLiveKitWorker()、chatContextToMessages(),以及工作階段輔助函式speakGreeting()、waitForAgentDoneSpeaking()和runEndCall()。只從 Worker 進入檔匯入。@mastra/livekit/plugin:LLM 元件外掛,包括MastraLLM和createRemoteAgentReplyGenerator()。請在自行建立voice.AgentSession的 Worker 中匯入。createRemoteAgentReplyGenerator()也會從@mastra/livekit/worker匯出,因為它可插入createLiveKitWorker()的generate選項。MastraLLM僅限外掛使用。
createLiveKitWorker()「createlivekitworker」的直接連結
建立使用 Mastra Agent 回應語音工作階段的 LiveKit Agent 定義。請將它作為 Worker 進入檔的預設匯出。
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' })
}
選項「選項」的直接連結
mastra:
agent?:
workflow?:
workflowInput?:
replyStep?:
resultText?:
generate?:
stt?:
tts?:
vad?:
turnDetection?:
turnHandling?:
sessionOptions?:
memory?:
toolFeedback?:
onTurnComplete?:
configuration?:
greeting?:
consentPolicy?:
endCall?:
stt?:
tts?:
greeting?:
persistGreeting?:
observability?:
voice call span:每輪的 Agent 執行都會巢狀放在其中,LiveKit 的 STT、TTS、話語結束、VAD 與 LLM 延遲指標會成為子 span,span 則會以個別模型的用量彙總結束。傳入 false 可停用。inputOptions?:
outputOptions?:
onSessionStart?:
runLiveKitWorker()「runlivekitworker」的直接連結
為 Worker 進入檔啟動 LiveKit Worker CLI(dev、start 和 connect 子命令)。請從預設匯出 Worker 定義的檔案呼叫,並加入防護條件,使其只在直接執行時運作(Worker 會為每個工作階段衍生子處理程序,並重新匯入同一個檔案)。使用此輔助函式,而非 @livekit/agents 的 cli.runApp,可確保 Worker 執行階段與橋接共用同一份 LiveKit SDK。
選項「選項」的直接連結
entry:
agentName?:
serverOptions?:
pipeAgentReplyToWriter()「pipeagentreplytowriter」的直接連結
在 Workflow 回覆路徑上,將 Mastra Agent 的回覆串流至 Workflow 步驟的 writer。它會轉送 Agent 的文字差異量,讓文字轉語音能在完整回覆就緒前開始;也會轉送 Tool 呼叫區塊,讓 toolFeedback 觸發,並讓 onTurnComplete 取得 Tool 清單。若只管道傳送 stream.textStream,會無聲地捨棄 Tool 呼叫。請將步驟的 abortSignal 傳入 agent.stream(),讓插話可立即停止產生流程。
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 }
},
})
傳回:Promise<string>,即累積的回覆文字。
參數「參數」的直接連結
agentStream:
writer:
chatContextToMessages()「chatcontexttomessages」的直接連結
將 LiveKit 聊天內容轉換成 agent.stream() 接受的純訊息,並排除指示與函式呼叫。可在 workflowInput 中使用,將完整逐字稿傳入無狀態 Workflow。
import { createLiveKitWorker, chatContextToMessages } from '@mastra/livekit/worker'
export default createLiveKitWorker({
mastra,
workflow: 'phoneConversation',
workflowInput: ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }),
})
傳回:VoiceTurnMessage[],其中每個項目為 { role: 'system' | 'user' | 'assistant'; content: string; id?: string }。
MastraLLM「mastrallm」的直接連結
由 Mastra Agent 支援的標準 LiveKit LLM 外掛 (llm.LLM)。自行建立 voice.AgentSession 並希望在 llm 欄位使用 Mastra 時,可使用此外掛。createLiveKitWorker() 是受管理的替代方案。如何選擇請參閱將 Mastra 作為 LLM 元件。
使用 remote 時,外掛會透過 HTTP 使用伺服器傳送事件 (SSE),從 Mastra 伺服器串流每一輪。Agent 迴圈、Tool 與記憶體會在伺服器端執行,中斷 Agent 也會中止伺服器端的產生流程。
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 } },
})
此外掛會將 provider 回報為 mastra,並將 model 回報為 Agent ID,讓 LiveKit 指標和備援配接器能像辨識其他 LLM 一樣辨識它。
建構函式選項「建構函式選項」的直接連結
請只提供一種回覆來源:remote、agent 或 generate。
remote?:
agent?:
generate?:
memory?:
requestContext?:
toolFeedback?:
onToolCall?:
onTurnComplete?:
請勿同時使用 memory 和工作階段的 preemptiveGeneration 選項;LiveKit 在你自行建立的工作階段中預設會啟用此選項。如果推測性對話輪次在 LiveKit 捨棄前完成,它會將一則使用者訊息和從未朗讀的回覆保存至執行緒。請在工作階段設定 turnHandling: { preemptiveGeneration: { enabled: false } }。無狀態模式(不使用 memory)可搭配預先產生。
Tool 在 Mastra Agent 上執行「Tool 在 Mastra Agent 上執行」的直接連結
Tool 會在伺服器端的 Mastra Agent 上定義及執行。此外掛絕不會轉送 LiveKit Tool 定義:若工作階段傳入非空的 toolCtx,它會記錄一次警告,列出遭忽略的 Tool。每個 Tool 都必須在伺服器端完成;需要核准或使用者端執行的 Tool 會以說明性錯誤讓該輪失敗,而不會讓通話停滯。
Tool 活動會透過 toolFeedback、onToolCall 和 onTurnComplete 傳至 Worker。
指示「指示」的直接連結
LiveKit 會將 voice.Agent 的 instructions 注入每個請求的聊天內容。此外掛會捨棄這些指示,因為以伺服器端 Mastra Agent 自己的指示為準。若要變更提示,請變更 Mastra Agent。
遭中斷的對話輪次「遭中斷的對話輪次」的直接連結
使用者中斷回覆時:
- 外掛會取消串流。伺服器會中止產生流程,且不會保存該輪的任何內容。
- LiveKit 會將使用者實際聽到的部分記錄在聊天內容中,並標示為已中斷。
- 下一輪中,外掛會在新使用者訊息前重新傳送只包含已聽到內容的片段,讓記憶體執行緒回填並與通話一致。訊息會攜帶 LiveKit 的訊息 ID,伺服器則會依 ID 去除重複,因此重試和重新傳送都會維持等冪。
若使用者在中斷後立即掛斷,最後的片段不會留下記錄。當逐字稿必須擷取該片段時,請立即從工作階段事件進行調解;共用的訊息 ID 表示下一輪重新傳送時會更新插入,而不會產生重複內容:
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(),
},
],
})
})
用量指標「用量指標」的直接連結
伺服器回報一輪的 Token 用量時,外掛會將它提供給 LiveKit,因此工作階段的 metrics_collected 事件會像任何 LLM 外掛一樣,包含第一個 Token 所需時間、持續時間和 Token 數量。同一個用量物件 (promptTokens、completionTokens、promptCachedTokens、totalTokens) 也會在 onTurnComplete 以 result.usage 提供。
錯誤與逾時「錯誤與逾時」的直接連結
傳輸層會擲回 LiveKit 的 APIError 類型(APIStatusError、APIConnectionError、APITimeoutError),因此工作階段的重試政策 (connOptions.maxRetry) 和 FallbackAdapter 容錯移轉可維持原有運作方式。第一個 Token 產生後,該輪絕不會重試:語音回覆寧可快速失敗,也不要重播使用者只聽到一半的內容。
連線與第一個 Token 的看門狗會使用工作階段的 connOptions.timeoutMs(預設 10 秒),因此接受連線卻從不進行串流的伺服器不會造成無限期的無聲等待。
若 Mastra 伺服器在通話途中停止運作,每次嘗試回覆都會在重試後以具型別的錯誤失敗;連續多次回覆失敗後,LiveKit 會關閉工作階段。在重試額度用盡前恢復伺服器,通話就會在下一輪復原。
訊息內容「訊息內容」的直接連結
訊息擷取僅支援文字:圖片內容會捨棄,音訊內容則只透過其逐字稿納入。語音管線不受影響,但自行注入聊天內容的項目必須帶有文字。
createRemoteAgentReplyGenerator()「createremoteagentreplygenerator」的直接連結
建立回覆產生器,透過 HTTP/SSE 在遠端 Mastra 伺服器上執行 Agent 迴圈。MastraLLM 的 remote 模式會在內部使用它。若要透過 createLiveKitWorker 的 generate 選項,讓功能完整的 Worker 對遠端伺服器執行,請直接使用它:
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',
})
在 generate 路徑上,Worker 層級的 toolFeedback 和 onTurnComplete 選項不適用,Worker 的結束通話偵測也不會觸發;請改將 Hook 傳入產生器。
取消一輪(插話)會中止 HTTP 請求,進而中止伺服器上的產生流程。錯誤會以 LiveKit APIError 類型擲回。retries 選項只適用於初始連線嘗試。第一個區塊產生後,該輪絕不會重試。
傳回:VoiceReplyGenerator。
選項「選項」的直接連結
baseUrl:
agentId:
apiPrefix?:
headers?:
fetch?:
timeoutMs?:
retries?:
body?:
toolFeedback?:
onToolCall?:
onTurnComplete?:
speakGreeting()「speakgreeting」的直接連結
在你擁有的工作階段上朗讀開場問候,並遵循中斷和播放選項。傳回 LiveKit SpeechHandle;若沒有問候文字,則傳回 undefined。createLiveKitWorker() 會在內部將它用於 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,
})
參數「參數」的直接連結
session:
greeting:
waitForAgentDoneSpeaking()「waitforagentdonespeaking」的直接連結
當 Agent 不再產生或播放回覆,也就是其狀態已離開 thinking 和 speaking 後解析。若 Agent 已閒置,則會立即解析;並且一律會在 maxWaitMs(預設 30 秒)內解析,作為安全上限。請在關閉工作階段前使用,讓結語播放完畢而不被截斷。
import { waitForAgentDoneSpeaking } from '@mastra/livekit/worker'
await waitForAgentDoneSpeaking(session)
runEndCall()「runendcall」的直接連結
在 Agent 要求掛斷後結束通話。它會等待 Agent 的結語,並在不中斷的情況下朗讀選用的最終 message。接著刪除房間並掛斷來電者,包括 SIP 來電者。工作會連同已註冊的回呼一起關閉。
將它與 MastraLLM 的 onToolCall 以及伺服器端 Agent 的結束通話 Tool 搭配,即可在你擁有的工作階段上重新建立 Agent 主動掛斷:
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)
},
})
匯出的常數 DEFAULT_END_CALL_TOOL ('endCall')、DEFAULT_END_CALL_REASON 和 DEFAULT_END_CALL_MAX_WAIT_MS (30000) 包含預設值。
參數「參數」的直接連結
session:
ctx:
config:
logger:
createEndCallTool()「createendcalltool」的直接連結
建立 Agent 想結束通話時所呼叫的 Mastra Tool。此 Tool 會表明意圖,並可執行選用的簿記工作。Worker 會執行實際掛斷。Tool 位於伺服器安全的根進入點。請將它加入伺服器程式碼所定義的 Agent。
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() },
})
搭配 createLiveKitWorker() 時,設定 configuration: { endCall: {} },Worker 便會監看此 Tool 並掛斷。在你擁有的工作階段上,使用 runEndCall() 重新建立掛斷流程。
選項「選項」的直接連結
id?:
description?:
onEndCall?:
liveKitConnectionRoute()「livekitconnectionroute」的直接連結
傳回一個 API 路由,用來產生 LiveKit 存取 Token,並將語音 Agent 分派至房間。前端可呼叫它加入工作階段。
import { Mastra } from '@mastra/core/mastra'
import { liveKitConnectionRoute } from '@mastra/livekit'
export const mastra = new Mastra({
server: {
apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })],
},
})
此路由接受包含選用 agentId、threadId 和 resourceId 欄位的 JSON 本文,並以 { serverUrl, roomName, participantName, participantToken } 回應。threadId 預設為產生的房間名稱。
選項「選項」的直接連結
path?:
serverUrl?:
apiKey?:
apiSecret?:
agentName?:
ttl?:
requiresAuth?:
roomName?:
participantIdentity?:
metadata?:
dispatchVoiceSession()「dispatchvoicesession」的直接連結
以程式設計方式將 Mastra 語音 Agent 分派至 LiveKit 房間,適用於撥出電話等伺服器起始的工作階段。
import { dispatchVoiceSession } from '@mastra/livekit'
await dispatchVoiceSession({
roomName: 'support-call-42',
agentName: 'mastra-voice',
metadata: { agentId: 'support', threadId: 'thread-42' },
})
選項「選項」的直接連結
roomName:
agentName?:
metadata?:
serverUrl?:
apiKey?:
apiSecret?:
LiveKitSessionMetadata「livekitsessionmetadata」的直接連結
透過 LiveKit 工作分派,從 Mastra 伺服器傳至 Worker 的中繼資料。
agentId?:
threadId?:
resourceId?:
requestContext?:
中繼資料會以 JSON 字串傳送。liveKitConnectionRoute() 和 dispatchVoiceSession() 會代為序列化;透過自己的程式碼分派時,請使用 serializeSessionMetadata(metadata),也可以直接在 SIP 分派規則等 LiveKit 端設定中撰寫 JSON。通話的每一輪中,requestContext 的項目都會提供給 Agent 在執行階段定義的指示、Tool 和輸入處理器。