> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # LiveKit `@mastra/livekit` 套件會將 Mastra Agent 連接至 LiveKit Agents 框架。LiveKit 會執行音訊管線(語音活動偵測、語音轉文字、對話輪次偵測、文字轉語音、插話),而此套件會將回覆產生流程橋接至 Mastra Agent 的 `stream()` 呼叫。 設定方式與相關概念請參閱[即時語音](https://mastra.zisheng.pro/zh-TW/guides/voice/realtime-voice)。 此套件有三個進入點: - `@mastra/livekit`:伺服器端 API,包括 [`liveKitConnectionRoute()`](#livekitconnectionroute)、[`dispatchVoiceSession()`](#dispatchvoicesession)、[`pipeAgentReplyToWriter()`](#pipeagentreplytowriter)、[`serializeSessionMetadata()`](#livekitsessionmetadata) 和 [`createEndCallTool()`](#createendcalltool)。請從 Mastra 伺服器程式碼匯入。此進入點絕不會載入 LiveKit Agents 執行階段。 - `@mastra/livekit/worker`:Worker 執行階段,包括 [`createLiveKitWorker()`](#createlivekitworker)、[`runLiveKitWorker()`](#runlivekitworker)、[`chatContextToMessages()`](#chatcontexttomessages),以及工作階段輔助函式 [`speakGreeting()`](#speakgreeting)、[`waitForAgentDoneSpeaking()`](#waitforagentdonespeaking) 和 [`runEndCall()`](#runendcall)。只從 Worker 進入檔匯入。 - `@mastra/livekit/plugin`:LLM 元件外掛,包括 [`MastraLLM`](#mastrallm) 和 [`createRemoteAgentReplyGenerator()`](#createremoteagentreplygenerator)。請在自行建立 `voice.AgentSession` 的 Worker 中匯入。`createRemoteAgentReplyGenerator()` 也會從 `@mastra/livekit/worker` 匯出,因為它可插入 `createLiveKitWorker()` 的 `generate` 選項。`MastraLLM` 僅限外掛使用。 ## `createLiveKitWorker()` 建立使用 Mastra Agent 回應語音工作階段的 LiveKit Agent 定義。請將它作為 Worker 進入檔的預設匯出。 ```typescript 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** (`Mastra`): 由其 Agent 處理語音工作階段的 Mastra 執行個體。 **agent** (`string | (args) => string | Agent | Promise`): 指定回應各工作階段的 Mastra Agent:固定的 Agent 金鑰或 ID,或針對每個工作階段呼叫、接收分派中繼資料和工作內容的解析器。預設使用分派中繼資料中的 agentId。 **workflow** (`string | Workflow | (args) => string | Promise`): 使用 Mastra Workflow(而非 Agent)產生每一輪的回覆:可以是 Workflow 執行個體、固定的 Workflow 金鑰或 ID,或針對每個工作階段傳回 Workflow ID 的解析器。Workflow 每輪都會執行一次直到完成(不可暫停或繼續)。不能與 agent 同時使用;必須提供 workflowInput。 **workflowInput** (`(args: VoiceTurnContext & { metadata }) => unknown | Promise`): 將一輪對話對應至 Workflow 的 inputData。設定 workflow 時為必填。若每輪都透過無狀態對應傳入完整逐字稿,就不必在 Workflow 中攜帶對話狀態。 **replyStep** (`string`): 只串流此 Workflow 步驟 ID 的文字。預設包含會寫入其 writer 的每個步驟。 **resultText** (`(result: unknown) => string | undefined`): Workflow 未透過 writer 串流任何文字時的備援方式:從最終執行結果取得要朗讀的回覆。 **generate** (`VoiceReplyGenerator`): 最低階的逃生出口:直接提供任何回覆產生器(自訂 Workflow、遠端橋接等)。 **stt** (`STT | string`): 語音轉文字:LiveKit 外掛執行個體,或 'deepgram/nova-3' 等推論模型字串。若要針對個別通話選擇,請設定 configuration.stt 解析器;它的優先順序較高,此選項則作為備援。 **tts** (`TTS | string`): 文字轉語音:LiveKit 外掛執行個體,或 'cartesia/sonic-3' 等推論模型字串。若要針對個別通話選擇,請設定 configuration.tts 解析器;它的優先順序較高,此選項則作為備援。 **vad** (`VAD | 'silero' | false`): 語音活動偵測。'silero' 會在預熱期間從 @livekit/agents-plugin-silero 載入 Silero VAD。傳入執行個體可使用自己的實作,傳入 false 則停用。 (Default: `'silero'`) **turnDetection** (`'multilingual' | 'english' | TurnDetectionMode`): 對話輪次結束偵測。'multilingual' 和 'english' 會從 @livekit/agents-plugin-livekit 載入 LiveKit 的語意式對話輪次偵測器。'vad'、'stt' 或 'manual' 等其他值會直接傳遞。 **turnHandling** (`Partial`): 對話輪次處理微調:端點延遲、中斷靈敏度、預先產生。除非在此設定,否則 Worker 會停用 preemptiveGeneration;每次預先產生都會重新執行 Mastra Agent,並保存一則重複的使用者訊息。 **sessionOptions** (`Partial`): 其他 LiveKit AgentSession 選項,會合併並覆寫此輔助函式建立的選項。 **memory** (`false | ((args) => { thread, resource } | false)`): 記憶體對應。當解析後的 Agent 已設定記憶體時,預設為 { thread: metadata.threadId ?? room name, resource: metadata.resourceId ?? thread }。傳入 false 可停用,或傳入函式以自訂。 **toolFeedback** (`(toolCall) => string | undefined`): Mastra Agent 在回覆途中開始 Tool 呼叫時呼叫。傳回 Tool 執行期間要朗讀的短句。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每輪回覆完成文字轉語音串流後呼叫一次。它會在音訊路徑之外執行,且不會等待其完成。內容包含產生的回覆(text、toolCalls、interrupted、usage)與解析後的記憶體對應。 **configuration** (`LiveKitWorkerConfiguration`): 分組的對話與法規遵循設定:開場問候和 AI 揭露、同意要求、Agent 主動掛斷,以及個別通話的 STT/TTS 選擇。 **configuration.greeting** (`GreetingConfiguration`): 開場問候和 AI 揭露:text(固定字串,或針對個別通話解析以提供個別租戶問候)、allowInterruptions、awaitPlayout、persist,以及透過 repeatEvery 和 repeatText 定期再次揭露。 **configuration.consentPolicy** (`ConsentConfiguration`): 通話的同意政策,以具名要求表示(從 summaryStorage 開始)。僅具宣告性質,Worker 本身不會封鎖任何項目。請在執行階段使用 createConsentTool 擷取授權,並在自己的程式碼中強制執行;已宣告的政策會在 onCallEnd 中提供,以便交叉檢查。 **configuration.endCall** (`EndCallConfiguration`): Agent 主動掛斷:Worker 會監看每輪是否使用結束通話 Tool(搭配 createEndCallTool),等待 Agent 的結語播放完畢後中斷連線,並在離開過程中執行 onCallEnd。 **configuration.stt** (`(context: VoiceCallContext) => STT | string | undefined`): 個別通話的語音轉文字:每次通話連線後呼叫一次解析器,接收 { metadata, requestContext, roomName, ctx },並傳回最上層 stt 選項接受的任何項目。傳回 undefined 可改用最上層 stt。請跨通話快取外掛執行個體;解析器會在通話設定期間執行。 **configuration.tts** (`(context: VoiceCallContext) => TTS | string | undefined`): 個別通話的文字轉語音:每次通話連線後呼叫一次解析器,接收 { metadata, requestContext, roomName, ctx },並傳回最上層 tts 選項接受的任何項目,讓每個租戶使用一種語音或語言。傳回 undefined 可改用最上層 tts。請跨通話快取外掛執行個體。 **greeting** (`string`): 工作階段開始時朗讀的靜態問候。已淘汰:請改用 configuration.greeting.text。 **persistGreeting** (`boolean`): 將已朗讀的問候以助理訊息儲存至記憶體執行緒,讓儲存的執行緒忠實呈現通話逐字稿。僅在設定問候且啟用記憶體時適用。已淘汰:請改用 configuration.greeting.persist。 (Default: `true`) **observability** (`boolean`): 當 Mastra 執行個體已設定可觀測性時,為每次通話建立 Trace。每個工作階段開啟一個 voice call span:每輪的 Agent 執行都會巢狀放在其中,LiveKit 的 STT、TTS、話語結束、VAD 與 LLM 延遲指標會成為子 span,span 則會以個別模型的用量彙總結束。傳入 false 可停用。 (Default: `true`) **inputOptions** (`Partial`): 傳入 session.start() 的 LiveKit 房間輸入選項。 **outputOptions** (`Partial`): 傳入 session.start() 的 LiveKit 房間輸出選項。 **onSessionStart** (`(args: { session, ctx, agent, metadata }) => void | Promise`): 工作階段開始後呼叫。可在此附加事件監聽器或觸發回覆。 ## `runLiveKitWorker()` 為 Worker 進入檔啟動 LiveKit Worker CLI(`dev`、`start` 和 `connect` 子命令)。請從預設匯出 Worker 定義的檔案呼叫,並加入防護條件,使其只在直接執行時運作(Worker 會為每個工作階段衍生子處理程序,並重新匯入同一個檔案)。使用此輔助函式,而非 `@livekit/agents` 的 `cli.runApp`,可確保 Worker 執行階段與橋接共用同一份 LiveKit SDK。 ### 選項 **entry** (`string | URL`): 預設匯出 Agent 定義的 Worker 進入模組。請傳入 import.meta.url。 **agentName** (`string`): 用於明確分派的 LiveKit Agent 名稱。 (Default: `'mastra-voice'`) **serverOptions** (`Partial`): 其他 LiveKit ServerOptions,會合併並覆寫此輔助函式建立的選項。 ## `pipeAgentReplyToWriter()` 在 Workflow 回覆路徑上,將 Mastra Agent 的回覆串流至 Workflow 步驟的 `writer`。它會轉送 Agent 的文字差異量,讓文字轉語音能在完整回覆就緒前開始;也會轉送 Tool 呼叫區塊,讓 `toolFeedback` 觸發,並讓 `onTurnComplete` 取得 Tool 清單。若只管道傳送 `stream.textStream`,會無聲地捨棄 Tool 呼叫。請將步驟的 `abortSignal` 傳入 `agent.stream()`,讓插話可立即停止產生流程。 ```typescript 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`,即累積的回覆文字。 ### 參數 **agentStream** (`AgentReplyStreamLike`): agent.stream() 傳回的串流,即任何公開 fullStream 非同步可迭代物件的項目。 **writer** (`WritableStream`): Workflow 步驟的 writer。 ## `chatContextToMessages()` 將 LiveKit 聊天內容轉換成 `agent.stream()` 接受的純訊息,並排除指示與函式呼叫。可在 `workflowInput` 中使用,將完整逐字稿傳入無狀態 Workflow。 ```typescript 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` 由 Mastra Agent 支援的標準 LiveKit LLM 外掛 (`llm.LLM`)。自行建立 `voice.AgentSession` 並希望在 `llm` 欄位使用 Mastra 時,可使用此外掛。[`createLiveKitWorker()`](#createlivekitworker) 是受管理的替代方案。如何選擇請參閱[將 Mastra 作為 LLM 元件](https://mastra.zisheng.pro/zh-TW/guides/voice/realtime-voice)。 使用 `remote` 時,外掛會透過 HTTP 使用伺服器傳送事件 (SSE),從 Mastra 伺服器串流每一輪。Agent 迴圈、Tool 與記憶體會在伺服器端執行,中斷 Agent 也會中止伺服器端的產生流程。 ```typescript 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** (`RemoteMastraAgentOptions`): 透過 HTTP 存取的遠端 Mastra 伺服器。接受與 createRemoteAgentReplyGenerator() 相同的連線選項:baseUrl、agentId、apiPrefix、headers、fetch、timeoutMs、retries、body。 **agent** (`Agent`): 處理程序內的 Mastra Agent。無須第二個部署即可擁有工作階段。 **generate** (`VoiceReplyGenerator`): 自訂回覆來源。generate 來源擁有自己的 Hook;下方的 toolFeedback、onToolCall 和 onTurnComplete 只適用於 remote 和 agent 來源。 **memory** (`{ thread: string; resource?: string } | false`): 對話持久化,會針對個別通話解析(例如依據 SIP 來電者身分)。設定後,每輪只會傳送 Agent 上次說話後的新訊息,並由 Mastra Memory 提供歷程。省略時,每輪都會傳送完整的 LiveKit 聊天內容。 (Default: `false`) **requestContext** (`RequestContext | Record`): 轉送至產生流程的請求內容(租戶、撥入號碼等)。 **toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): 傳回伺服器端 Tool 執行期間要朗讀的短句。 **onToolCall** (`(toolCall: VoiceToolCall) => void`): 每個 Tool 呼叫開始時,在串流途中呼叫。搭配 runEndCall() 可實作自己的 Agent 主動掛斷流程。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每輪回覆完成串流後呼叫一次;它會在音訊路徑之外執行,且不會等待其完成。內容包含產生的回覆:text、toolCalls、interrupted 和 usage。 > **警告:** 請勿同時使用 `memory` 和工作階段的 `preemptiveGeneration` 選項;LiveKit 在你自行建立的工作階段中預設會啟用此選項。如果推測性對話輪次在 LiveKit 捨棄前完成,它會將一則使用者訊息和從未朗讀的回覆保存至執行緒。請在工作階段設定 `turnHandling: { preemptiveGeneration: { enabled: false } }`。無狀態模式(不使用 `memory`)可搭配預先產生。 ### 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。 ### 遭中斷的對話輪次 使用者中斷回覆時: 1. 外掛會取消串流。伺服器會中止產生流程,且不會保存該輪的任何內容。 2. LiveKit 會將使用者實際聽到的部分記錄在聊天內容中,並標示為已中斷。 3. 下一輪中,外掛會在新使用者訊息前重新傳送只包含已聽到內容的片段,讓記憶體執行緒回填並與通話一致。訊息會攜帶 LiveKit 的訊息 ID,伺服器則會依 ID 去除重複,因此重試和重新傳送都會維持等冪。 若使用者在中斷後立即掛斷,最後的片段不會留下記錄。當逐字稿必須擷取該片段時,請立即從工作階段事件進行調解;共用的訊息 ID 表示下一輪重新傳送時會更新插入,而不會產生重複內容: ```typescript 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()` 建立回覆產生器,透過 HTTP/SSE 在**遠端** Mastra 伺服器上執行 Agent 迴圈。`MastraLLM` 的 `remote` 模式會在內部使用它。若要透過 `createLiveKitWorker` 的 `generate` 選項,讓功能完整的 Worker 對遠端伺服器執行,請直接使用它: ```typescript 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** (`string`): 遠端 Mastra 伺服器的基底 URL,例如 https\://my-app.example.com。 **agentId** (`string`): 遠端 Mastra 執行個體上已註冊的 Agent 金鑰或 ID。 **apiPrefix** (`string`): Mastra API 的路徑前置詞。 (Default: `'/api'`) **headers** (`Record | () => Record | Promise>`): 靜態標頭,或每輪呼叫的解析器,例如用來產生新的授權 Token。 **fetch** (`typeof fetch`): 可注入的 fetch 實作,用於測試或 Proxy。 (Default: `globalThis.fetch`) **timeoutMs** (`number`): 連線和第一個 Token 的逾時時間(毫秒)。透過 MastraLLM 使用時,預設改用工作階段的 connOptions.timeoutMs。 (Default: `10000`) **retries** (`number`): 初始連線的重試次數,僅限第一個區塊前。透過 MastraLLM 使用時,重試由 LiveKit 工作階段負責,此值會強制設為 0。 (Default: `2`) **body** (`Record`): 合併至每個串流請求本文的其他欄位。 **toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): 傳回伺服器端 Tool 執行期間要朗讀的短句。 **onToolCall** (`(toolCall: VoiceToolCall) => void`): 每個 Tool 呼叫開始時,在串流途中呼叫。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每輪回覆完成串流後,在音訊路徑之外呼叫一次。 ## `speakGreeting()` 在你擁有的工作階段上朗讀開場問候,並遵循中斷和播放選項。傳回 LiveKit `SpeechHandle`;若沒有問候文字,則傳回 `undefined`。`createLiveKitWorker()` 會在內部將它用於 `greeting` 設定。 ```typescript 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** (`voice.AgentSession`): 要在其中朗讀的工作階段。 **greeting** (`{ text?: string; allowInterruptions?: boolean; awaitPlayout?: boolean }`): 問候文字和播放選項。awaitPlayout 為 true 時,傳回的 Promise 會在問候播放完畢(或遭到中斷)後解析。 ## `waitForAgentDoneSpeaking()` 當 Agent 不再產生或播放回覆,也就是其狀態已離開 `thinking` 和 `speaking` 後解析。若 Agent 已閒置,則會立即解析;並且一律會在 `maxWaitMs`(預設 30 秒)內解析,作為安全上限。請在關閉工作階段前使用,讓結語播放完畢而不被截斷。 ```typescript import { waitForAgentDoneSpeaking } from '@mastra/livekit/worker' await waitForAgentDoneSpeaking(session) ``` ## `runEndCall()` 在 Agent 要求掛斷後結束通話。它會等待 Agent 的結語,並在不中斷的情況下朗讀選用的最終 `message`。接著刪除房間並掛斷來電者,包括 SIP 來電者。工作會連同已註冊的回呼一起關閉。 將它與 [`MastraLLM`](#mastrallm) 的 `onToolCall` 以及伺服器端 Agent 的[結束通話 Tool](#createendcalltool) 搭配,即可在你擁有的工作階段上重新建立 Agent 主動掛斷: ```typescript 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** (`voice.AgentSession`): 其 Agent 正在完成結語的工作階段。 **ctx** (`JobContext`): 用於刪除房間和關閉的 LiveKit 工作內容。 **config** (`{ message?: string; reason?: string; maxWaitMs?: number; drainMs?: number }`): 掛斷前朗讀的選用最終訊息、要記錄的關閉原因、等待結語的安全上限,以及播放後的排空時間(預設 800 毫秒);排空時間讓來電者端緩衝的音訊播放完畢後再刪除房間。LiveKit 的播放計算僅限 Worker 本機,因此在其剛清除時立即掛斷會截斷道別。 **logger** (`{ warn: (message: string, ...args: unknown[]) => void }`): 拆除步驟失敗時接收警告。請傳入記錄器或 console。 ## `createEndCallTool()` 建立 Agent 想結束通話時所呼叫的 Mastra Tool。此 Tool 會表明意圖,並可執行選用的簿記工作。Worker 會執行實際掛斷。Tool 位於伺服器安全的根進入點。請將它加入伺服器程式碼所定義的 Agent。 ```typescript 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()`](#runendcall) 重新建立掛斷流程。 ### 選項 **id** (`string`): Agent 用於結束通話的 Tool ID。必須與 Worker 監看的名稱相符(Worker 的 configuration.endCall.tool,或你自己的 onToolCall 檢查)。 (Default: `'endCall'`) **description** (`string`): 覆寫模型決定是否呼叫 Tool 時所見的說明。 **onEndCall** (`(request: { reason?: string; resourceId?: string; threadId?: string }) => void | Promise`): Agent 叫用 Tool 時呼叫的簿記 Hook,可記錄原因或將通話標示為已解決。它會在該輪內執行,請保持快速;它不會掛斷通話。 ## `liveKitConnectionRoute()` 傳回一個 [API 路由](https://mastra.zisheng.pro/zh-TW/docs/server/custom-api-routes),用來產生 LiveKit 存取 Token,並將語音 Agent 分派至房間。前端可呼叫它加入工作階段。 ```typescript 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** (`string`): 路由路徑。 (Default: `'/voice/livekit/connection-details'`) **serverUrl** (`string`): LiveKit 伺服器 URL。 (Default: `process.env.LIVEKIT_URL`) **apiKey** (`string`): LiveKit API 金鑰。 (Default: `process.env.LIVEKIT_API_KEY`) **apiSecret** (`string`): LiveKit API 密鑰。 (Default: `process.env.LIVEKIT_API_SECRET`) **agentName** (`string`): 用於明確分派的 LiveKit Agent 名稱。必須與 Worker 的 agentName 相符。 (Default: `'mastra-voice'`) **ttl** (`string | number`): Token 存留時間。 (Default: `'15m'`) **requiresAuth** (`boolean`): 路由是否需要驗證。 (Default: `true`) **roomName** (`string | (args) => string`): 房間名稱,或從請求取得名稱的函式。 **participantIdentity** (`string | (args) => string`): 參與者身分,或從請求取得身分的函式。 **metadata** (`(args) => LiveKitSessionMetadata | Promise`): 建立傳遞至 Worker 的工作階段中繼資料。預設會直接傳遞請求本文中的 agentId、threadId 和 resourceId。 ## `dispatchVoiceSession()` 以程式設計方式將 Mastra 語音 Agent 分派至 LiveKit 房間,適用於撥出電話等伺服器起始的工作階段。 ```typescript import { dispatchVoiceSession } from '@mastra/livekit' await dispatchVoiceSession({ roomName: 'support-call-42', agentName: 'mastra-voice', metadata: { agentId: 'support', threadId: 'thread-42' }, }) ``` ### 選項 **roomName** (`string`): 要將 Agent 分派至其中的房間。會視需要建立。 **agentName** (`string`): 必須與 Worker 的 agentName 相符。 (Default: `'mastra-voice'`) **metadata** (`LiveKitSessionMetadata`): 工作階段中繼資料:agentId、threadId、resourceId、requestContext。 **serverUrl** (`string`): LiveKit 伺服器 URL。 (Default: `process.env.LIVEKIT_URL`) **apiKey** (`string`): LiveKit API 金鑰。 (Default: `process.env.LIVEKIT_API_KEY`) **apiSecret** (`string`): LiveKit API 密鑰。 (Default: `process.env.LIVEKIT_API_SECRET`) ## `LiveKitSessionMetadata` 透過 LiveKit 工作分派,從 Mastra 伺服器傳至 Worker 的中繼資料。 **agentId** (`string`): 要執行的 Mastra Agent,以已註冊的金鑰或 Agent ID 指定。 **threadId** (`string`): 記憶體執行緒 ID。預設為 LiveKit 房間名稱。 **resourceId** (`string`): 記憶體資源 ID,通常是終端使用者 ID。 **requestContext** (`Record`): 還原至 RequestContext 供 Agent 執行的純物件項目。 中繼資料會以 JSON 字串傳送。`liveKitConnectionRoute()` 和 `dispatchVoiceSession()` 會代為序列化;透過自己的程式碼分派時,請使用 `serializeSessionMetadata(metadata)`,也可以直接在 SIP 分派規則等 LiveKit 端設定中撰寫 JSON。通話的每一輪中,`requestContext` 的項目都會提供給 Agent 在執行階段定義的指示、Tool 和輸入處理器。 ## 相關內容 - [即時語音](https://mastra.zisheng.pro/zh-TW/guides/voice/realtime-voice) - [LiveKit Agents 文件](https://docs.livekit.io/agents/)