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 元件 plugin,包括MastraLLM和createRemoteAgentReplyGenerator()。請在自行建立voice.AgentSession的 worker 中匯入。createRemoteAgentReplyGenerator()亦會從@mastra/livekit/worker匯出,因為它可接入createLiveKitWorker()的generate選項。MastraLLM只由 plugin 提供。
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 step 的 writer。它會轉發 Agent 的文字增量,讓文字轉語音可在完整回覆準備好之前開始;亦會轉發 Tool 呼叫區塊,讓 toolFeedback 觸發,並讓 onTurnComplete 取得 Tool 清單。只傳送 stream.textStream 會在沒有提示下遺失 Tool 呼叫。請將 step 的 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 chat context 轉換為 agent.stream() 接受的純訊息,並排除 instructions 及函式呼叫。在 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 }。
MastraLLMmastrallm 的直接連結
由 Mastra Agent 支援的標準 LiveKit LLM plugin(llm.LLM)。當你自行建立 voice.AgentSession,並希望在 llm 位置使用 Mastra 時使用。createLiveKitWorker() 是受管理的替代方案。選擇方法請參閱使用 Mastra 作為 LLM 元件。
使用 remote 時,plugin 會透過 HTTP 使用伺服器傳送事件(SSE),從你的 Mastra 伺服器串流每個話輪。Agent loop、Tool 及 Memory 均在伺服器端執行;中斷 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 } },
})
plugin 會將 provider 回報為 mastra,並將 model 回報為 Agent id,因此 LiveKit 指標及後備 adapter 可像識別任何其他 LLM 一樣識別它。
建構函式選項建構函式選項 的直接連結
只可提供一個回覆來源:remote、agent 或 generate。
remote?:
agent?:
generate?:
memory?:
requestContext?:
toolFeedback?:
onToolCall?:
onTurnComplete?:
請勿將 memory 與工作階段的 preemptiveGeneration 選項一併使用;LiveKit 會在你自行建立的工作階段中預設啟用此選項。如果推測話輪在 LiveKit 捨棄前已完成,便會將一則使用者訊息和一段從未讀出的回覆保存至 thread。請在工作階段設定 turnHandling: { preemptiveGeneration: { enabled: false } }。無狀態模式(不使用 memory)可配合預先產生使用。
在 Mastra Agent 上執行的 Tool在 Mastra Agent 上執行的 Tool 的直接連結
Tool 會在伺服器端的 Mastra Agent 上定義及執行。plugin 絕不會轉發 LiveKit Tool 定義:如果工作階段傳入非空白的 toolCtx,它會記錄一次性警告,列出被忽略的 Tool。每個 Tool 都必須在伺服器端完成:需要批准或在用戶端執行的 Tool 會令該話輪以具描述性的錯誤失敗,而不會令通話停滯。
Tool 活動會透過 toolFeedback、onToolCall 及 onTurnComplete 傳送至 worker。
指示指示 的直接連結
LiveKit 會將你的 voice.Agent 的 instructions 注入每個請求的 chat context。plugin 會捨棄這些內容,因為應以伺服器端 Mastra Agent 自身的 instructions 為準。如要更改 prompt,請更改 Mastra Agent。
被中斷的話輪被中斷的話輪 的直接連結
當使用者中斷回覆時:
- plugin 會取消串流。伺服器會中止產生內容,且不會保存該話輪的任何內容。
- LiveKit 會在其 chat context 記錄使用者實際聽到的部分,並標記為 interrupted。
- 在下一個話輪,plugin 會重新傳送只有已聽取內容的片段,並將它置於新的使用者訊息之前,讓 Memory thread 回填至與通話相符。訊息會攜帶 LiveKit message id,而伺服器會按 id 移除重複項目,因此重試及重新傳送均保持冪等。
如果使用者在中斷後立即掛線,最後的片段便不會被記錄。當逐字稿必須擷取該片段時,請立即透過工作階段事件進行協調;共用的 message id 表示下一個話輪重新傳送時會執行 upsert,而不會建立重複項目:
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 用量時,plugin 會將資料提供給 LiveKit,因此工作階段的 metrics_collected 事件會像任何 LLM plugin 一樣,包含首個 token 所需時間、持續時間及 token 數量。同一個 usage 物件(promptTokens、completionTokens、promptCachedTokens、totalTokens)會以 result.usage 傳至 onTurnComplete。
錯誤及逾時錯誤及逾時 的直接連結
傳輸層會擲出 LiveKit 的 APIError 類型(APIStatusError、APIConnectionError、APITimeoutError),因此工作階段的重試政策(connOptions.maxRetry)及 FallbackAdapter 容錯轉移會維持原有運作。話輪在產生首個 token 後絕不會重試:語音回覆宜快速失敗,避免重播使用者只聽到一半的內容。
連線及首個 token watchdog 會使用工作階段的 connOptions.timeoutMs(預設為 10 秒),因此即使伺服器接受連線後一直不串流,也不會造成無限期靜音。
如果 Mastra 伺服器在通話期間停止運作,每次回覆嘗試都會在完成重試後以具類型錯誤失敗,而 LiveKit 會在連續數次回覆失敗後關閉工作階段。在容許次數用盡前恢復伺服器,通話便會在下一個話輪復原。
訊息內容訊息內容 的直接連結
訊息只會擷取文字:圖片內容會被捨棄,音訊內容則只會透過其逐字稿納入。語音管線不受影響,但你自行注入 chat context 的項目必須包含文字。
createRemoteAgentReplyGenerator()createremoteagentreplygenerator 的直接連結
建立透過 HTTP/SSE 在遠端 Mastra 伺服器上執行 Agent loop 的回覆產生器。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 來電者。job 會連同其已註冊 callback 一併關閉。
將它配合 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 route,用來簽發 LiveKit access token,並將語音 Agent 分派至房間。前端會呼叫它以加入工作階段。
import { Mastra } from '@mastra/core/mastra'
import { liveKitConnectionRoute } from '@mastra/livekit'
export const mastra = new Mastra({
server: {
apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })],
},
})
route 接受包含可選 agentId、threadId 及 resourceId 欄位的 JSON body,並以 { 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?:
LiveKitSessionMetadatalivekitsessionmetadata 的直接連結
透過 LiveKit job 分派,從 Mastra 伺服器傳至 worker 的 metadata。
agentId?:
threadId?:
resourceId?:
requestContext?:
metadata 會以 JSON 字串傳送。liveKitConnectionRoute() 和 dispatchVoiceSession() 會代你將它序列化;透過自己的程式碼分派時,請使用 serializeSessionMetadata(metadata),或直接在 LiveKit 端設定(例如 SIP 分派規則)中寫入 JSON。requestContext 中的項目會在每個通電話輪傳至 Agent 在執行階段定義的 instructions、Tool 及輸入處理器。