> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # LiveKit `@mastra/livekit` 软件包将 Mastra Agent 连接到 LiveKit Agents 框架。LiveKit 运行音频管线(语音活动检测、语音转文本、轮次检测、文本转语音和插话打断),该软件包则将响应生成桥接到 Mastra Agent 的 `stream()` 调用。 有关设置和相关概念,请参阅 [实时 Voice](https://mastra.zisheng.pro/guides/voice/realtime-voice)。 该软件包有三个入口点: - `@mastra/livekit`:服务端 API,包括 [`liveKitConnectionRoute()`](#livekitconnectionroute)、[`dispatchVoiceSession()`](#dispatchvoicesession)、[`pipeAgentReplyToWriter()`](#pipeagentreplytowriter)、[`serializeSessionMetadata()`](#livekitsessionmetadata) 和 [`createEndCallTool()`](#createendcalltool)。 请从 Mastra 服务端代码导入这些 API。此入口绝不会加载 LiveKit Agents runtime。 - `@mastra/livekit/worker`:worker runtime,包括 [`createLiveKitWorker()`](#createlivekitworker)、[`runLiveKitWorker()`](#runlivekitworker)、[`chatContextToMessages()`](#chatcontexttomessages),以及 session helper [`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` 仅由 plugin 导出。 ## `createLiveKitWorker()` 构建使用 Mastra Agent 响应语音 session 的 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 用于处理语音 session 的 Mastra 实例。 **agent** (`string | (args) => string | Agent | Promise`): 指定响应每个 session 的 Mastra Agent:固定的 Agent key 或 ID,或者每个 session 使用分派元数据和 job context 调用的 resolver。默认为分派元数据中的 agentId。 **workflow** (`string | Workflow | (args) => string | Promise`): 使用 Mastra Workflow 而不是 Agent 生成每个轮次的响应:可以是 Workflow 实例、固定的 Workflow key 或 ID,或者为每个 session 返回 Workflow ID 的 resolver。每个轮次中 Workflow 会运行一次直至完成(不支持 suspend 或 resume)。与 agent 互斥;需要 workflowInput。 **workflowInput** (`(args: VoiceTurnContext & { metadata }) => unknown | Promise`): 将轮次映射为 Workflow 的 inputData。设置 workflow 时必需。每个轮次传递完整转写文本的无状态映射,可避免在 Workflow 中携带对话状态。 **replyStep** (`string`): 仅流式传输此 Workflow step ID 的文本。默认包含所有向其 writer 写入内容的 step。 **resultText** (`(result: unknown) => string | undefined`): 当 Workflow 未通过 writer 流式传输文本时的备用方案:从最终运行结果生成口头响应。 **generate** (`VoiceReplyGenerator`): 最底层的 escape hatch:直接提供任意响应生成器(自定义 Workflow、远程桥接等)。 **stt** (`STT | string`): 语音转文本:LiveKit plugin 实例,或 deepgram/nova-3 之类的推理模型字符串。若要按调用选择,请设置 configuration.stt resolver;它具有更高优先级,此选项作为备用值。 **tts** (`TTS | string`): 文本转语音:LiveKit plugin 实例,或 cartesia/sonic-3 之类的推理模型字符串。若要按调用选择,请设置 configuration.tts resolver;它具有更高优先级,此选项作为备用值。 **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`): 合并到此 helper 所构建内容之上的额外 LiveKit AgentSession 选项。 **memory** (`false | ((args) => { thread, resource } | false)`): Memory 映射。解析出的 Agent 配置 Memory 时,默认为 { thread: metadata.threadId ?? room name, resource: metadata.resourceId ?? thread }。传入 false 可禁用,或传入函数进行自定义。 **toolFeedback** (`(toolCall) => string | undefined`): Mastra Agent 在响应期间开始调用 Tool 时调用。返回一段简短话语,以便在 Tool 运行期间播报。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每个轮次在响应完成到文本转语音的流式传输后调用一次。它在音频路径之外运行,且不会被 await。context 包含生成的响应(text、toolCalls、interrupted、usage)以及解析后的 Memory 映射。 **configuration** (`LiveKitWorkerConfiguration`): 分组的对话与合规配置:开场问候和 AI 披露、同意要求、Agent 发起挂断,以及按调用选择 STT/TTS。 **configuration.greeting** (`GreetingConfiguration`): 开场问候和 AI 披露:text(固定字符串或按调用解析每个租户问候语的 resolver)、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 } 调用一次 resolver,返回顶层 stt 选项接受的任何值。返回 undefined 可回退到顶层 stt。请在多次通话之间缓存 plugin 实例;resolver 在通话设置期间运行。 **configuration.tts** (`(context: VoiceCallContext) => TTS | string | undefined`): 按调用配置文本转语音:每次通话在连接后使用 { metadata, requestContext, roomName, ctx } 调用一次 resolver,返回顶层 tts 选项接受的任何值,即每个租户一种音色或语言。返回 undefined 可回退到顶层 tts。请在多次通话之间缓存 plugin 实例。 **greeting** (`string`): session 开始时播报的静态问候语。已弃用:请优先使用 configuration.greeting.text。 **persistGreeting** (`boolean`): 将播报的问候语作为 assistant 消息保存到 Memory thread,使保存的 thread 忠实记录通话转写。仅在设置问候语且启用 Memory 时适用。已弃用:请优先使用 configuration.greeting.persist。 (Default: `true`) **observability** (`boolean`): Mastra 实例配置 observability 时跟踪每次通话。每个 session 打开一个 voice call span:每个轮次的 Agent 运行嵌套其下,LiveKit 的 STT、TTS、语句结束、VAD 和 LLM 延迟指标成为子 span,最后以按模型汇总的用量关闭该 span。传入 false 可禁用。 (Default: `true`) **inputOptions** (`Partial`): 传给 session.start() 的 LiveKit room 输入选项。 **outputOptions** (`Partial`): 传给 session.start() 的 LiveKit room 输出选项。 **onSessionStart** (`(args: { session, ctx, agent, metadata }) => void | Promise`): session 开始后调用。可在此附加事件监听器或触发响应。 ## `runLiveKitWorker()` 为 worker 入口文件启动 LiveKit worker CLI(`dev`、`start` 和 `connect` 子命令)。请从默认导出 worker 定义的文件中调用,并添加保护,确保仅在直接执行时运行(worker 会为每个 session 生成一个重新导入同一文件的子进程)。使用 `cli.runApp`(来自 `@livekit/agents`)之外的此 helper,可确保 worker runtime 与桥接共享同一份 LiveKit SDK。 ### 选项 **entry** (`string | URL`): 默认导出 Agent 定义的 worker 入口模块。传入 import.meta.url。 **agentName** (`string`): 用于显式分派的 LiveKit Agent 名称。 (Default: `'mastra-voice'`) **serverOptions** (`Partial`): 合并到此 helper 所构建内容之上的额外 LiveKit ServerOptions。 ## `pipeAgentReplyToWriter()` 在 Workflow 响应路径上,将 Mastra Agent 的响应流式传输到 Workflow step 的 `writer`。它会转发 Agent 的文本增量,使文本转语音可在完整响应就绪前开始;还会转发 Tool 调用分块,从而触发 `toolFeedback` 并让 `onTurnComplete` 获取 Tool 列表。仅管道传输 `stream.textStream` 会静默丢弃 Tool 调用。请将 step 的 `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 step 的 writer。 ## `chatContextToMessages()` 将 LiveKit chat context 转换为 `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 plugin(`llm.LLM`)。当你自行构建 `voice.AgentSession` 并希望在 `llm` 槽位使用 Mastra 时,请使用它。[`createLiveKitWorker()`](#createlivekitworker) 是托管式替代方案。有关如何选择,请参阅[将 Mastra 用作 LLM 组件](https://mastra.zisheng.pro/guides/voice/realtime-voice)。 使用 `remote` 时,plugin 通过 HTTP 使用服务器发送事件(SSE)从 Mastra 服务端流式传输每个轮次。Agent 循环、Tool 和 Memory 在服务端运行;中断 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 } }, }) ``` plugin 将 `provider` 报告为 `mastra`,将 `model` 报告为 Agent ID,因此 LiveKit 指标和 fallback adapter 会像识别其他 LLM 一样识别它。 ### 构造函数选项 仅提供一个响应来源:`remote`、`agent` 或 `generate`。 **remote** (`RemoteMastraAgentOptions`): 通过 HTTP 访问的远程 Mastra 服务端。采用与 createRemoteAgentReplyGenerator() 相同的连接选项:baseUrl、agentId、apiPrefix、headers、fetch、timeoutMs、retries、body。 **agent** (`Agent`): 进程内 Mastra Agent。无需第二次部署即可拥有 session。 **generate** (`VoiceReplyGenerator`): 自定义响应来源。generate 来源拥有自己的 hook;下方的 toolFeedback、onToolCall 和 onTurnComplete 仅适用于 remote 和 agent 来源。 **memory** (`{ thread: string; resource?: string } | false`): 对话持久化,按通话解析(例如根据 SIP 呼叫方身份)。设置后,每个轮次仅发送 Agent 上次说话后出现的新消息,并由 Mastra Memory 提供历史记录。省略时,每个轮次都会发送完整的 LiveKit chat context。 (Default: `false`) **requestContext** (`RequestContext | Record`): 转发到生成过程的 Request context(租户、拨入号码等)。 **toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): 返回一段简短话语,以便在服务端 Tool 运行期间播报。 **onToolCall** (`(toolCall: VoiceToolCall) => void`): 每次 Tool 调用在流传输期间开始时调用。可与 runEndCall() 搭配,实现自定义的 Agent 发起挂断流程。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每个轮次在响应完成流式传输后调用一次,不在音频路径上执行,也不会被 await。context 包含生成的响应:text、toolCalls、interrupted 和 usage。 > **注意:** 不要将 `memory` 与 session 的 `preemptiveGeneration` 选项结合使用;在自行构建的 session 中,LiveKit 默认启用该选项。如果推测轮次在 LiveKit 丢弃前完成,会在 thread 中持久化一条用户消息和一条从未播报的响应。请在 session 上设置 `turnHandling: { preemptiveGeneration: { enabled: false } }`。无状态模式(不使用 `memory`)可与抢先生成配合使用。 ### Tool 在 Mastra Agent 上运行 Tool 在服务端的 Mastra Agent 上定义并执行。plugin 绝不会转发 LiveKit Tool 定义:如果 session 传入非空 `toolCtx`,它会记录一次警告,列出被忽略的 Tool。每个 Tool 都必须在服务端完成;需要批准或客户端执行的 Tool 会让轮次以描述性错误失败,而不是使通话卡住。 Tool 活动通过 `toolFeedback`、`onToolCall` 和 `onTurnComplete` 传递到 worker。 ### 指令 LiveKit 会将 `voice.Agent` 的 `instructions` 注入每个请求的 chat context。plugin 会丢弃这些指令,因为服务端 Mastra Agent 自身的指令才是权威来源。若要更改提示词,请更改 Mastra Agent。 ### 中断的轮次 当用户中断响应时: 1. plugin 会取消流。服务端会中止生成,并且不会持久化该轮次的任何内容。 2. LiveKit 会在 chat context 中记录用户实际听到的部分,并将其标记为 interrupted。 3. 下一轮中,plugin 会在新用户消息前重新发送该仅包含已听内容的片段,使 Memory thread 回填到与通话一致。消息携带 LiveKit 消息 ID,服务端会按 ID 去重,因此重试和重新发送保持幂等。 如果用户在中断后立即挂断,最后的片段不会被记录。如果转写必须捕获该片段,请立即根据 session 事件进行协调;共享的消息 ID 意味着下一轮重新发送时会 upsert,而不会重复: ```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 用量时,plugin 会将其提供给 LiveKit,因此 session 的 `metrics_collected` 事件会像其他 LLM plugin 一样包含首 token 时间、持续时间和 token 数。同一个 usage 对象(`promptTokens`、`completionTokens`、`promptCachedTokens`、`totalTokens`)会在 `onTurnComplete` 中作为 `result.usage` 到达。 ### 错误和超时 传输层会抛出 LiveKit 的 `APIError` 类型(`APIStatusError`、`APIConnectionError`、`APITimeoutError`),因此 session 的重试策略(`connOptions.maxRetry`)和 `FallbackAdapter` 故障转移可保持不变。轮次在生成首个 token 后绝不会重试:语音响应快速失败比重播用户只听到一半的内容更合适。 连接和首 token watchdog 使用 session 的 `connOptions.timeoutMs`(默认 10 秒),因此接受连接但始终不传输内容的服务端不会造成无限期静音。 如果 Mastra 服务端在通话期间宕机,每次响应尝试会在重试后以强类型错误失败;连续数次响应失败后,LiveKit 会关闭 session。在该额度用尽前恢复服务端,通话将在下一轮恢复。 ### 消息内容 消息提取仅处理文本:图像内容会被丢弃,音频内容仅通过其转写文本包含。语音管线不受影响,但你自行注入 chat context 的项目必须包含文本。 ## `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 的注册 key 或 ID。 **apiPrefix** (`string`): Mastra API 的路径前缀。 (Default: `'/api'`) **headers** (`Record | () => Record | Promise>`): 静态标头,或每个轮次调用的 resolver,例如用于签发新的授权 token。 **fetch** (`typeof fetch`): 可注入的 fetch 实现,用于测试或代理。 (Default: `globalThis.fetch`) **timeoutMs** (`number`): 连接和首 token 超时(毫秒)。通过 MastraLLM 使用时,改为默认为 session 的 connOptions.timeoutMs。 (Default: `10000`) **retries** (`number`): 仅在第一个分块之前进行的初始连接重试次数。通过 MastraLLM 使用时,由 LiveKit session 负责重试,此值强制设为 0。 (Default: `2`) **body** (`Record`): 合并到每个流请求 body 中的额外字段。 **toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): 返回一段简短话语,以便在服务端 Tool 运行期间播报。 **onToolCall** (`(toolCall: VoiceToolCall) => void`): 每次 Tool 调用在流传输期间开始时调用。 **onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise`): 每个轮次在响应完成流式传输后调用一次,不在音频路径上执行。 ## `speakGreeting()` 在你拥有的 session 上播报开场问候语,并遵循中断和播放选项。返回 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`): 要播报内容的 session。 **greeting** (`{ text?: string; allowInterruptions?: boolean; awaitPlayout?: boolean }`): 问候文本和播放选项。当 awaitPlayout 为 true 时,返回的 Promise 会在问候播放完毕(或被中断)后 resolve。 ## `waitForAgentDoneSpeaking()` 当 Agent 不再生成或播放响应,即状态离开 `thinking` 和 `speaking` 后 resolve。如果 Agent 已空闲,则立即 resolve;作为安全上限,始终会在 `maxWaitMs`(默认 30 秒)内 resolve。在拆除 session 前使用它,可让结束语完整播放而不被截断。 ```typescript import { waitForAgentDoneSpeaking } from '@mastra/livekit/worker' await waitForAgentDoneSpeaking(session) ``` ## `runEndCall()` 在 Agent 请求挂断后结束通话。它会等待 Agent 的结束语,并不受中断地播报可选的最终 `message`。随后删除 room 并挂断呼叫方,包括 SIP 呼叫方。job 会连同其已注册的回调一起关闭。 将它与 [`MastraLLM`](#mastrallm) 的 `onToolCall` 以及服务端 Agent 上的[结束通话 Tool](#createendcalltool) 搭配,可在你拥有的 session 上重新实现 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 正在完成结束语的 session。 **ctx** (`JobContext`): 用于删除 room 并关闭的 LiveKit job context。 **config** (`{ message?: string; reason?: string; maxWaitMs?: number; drainMs?: number }`): 挂断前播报的可选最终消息、要记录的关闭原因、等待结束语的安全上限,以及播放后的排空时间(默认 800ms),后者可让呼叫方缓冲的音频在 room 删除前播放完毕。LiveKit 的播放统计仅限 worker 本地,因此在统计一清空就挂断会截断告别语。 **logger** (`{ warn: (message: string, ...args: unknown[]) => void }`): 在拆除步骤失败时接收警告。请传入 logger 或 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 并挂断。在你拥有的 session 上,可使用 [`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 route](https://mastra.zisheng.pro/docs/server/custom-api-routes),用于签发 LiveKit access token,并将语音 Agent 分派到 room 中。前端调用它加入 session。 ```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 body,并响应 `{ serverUrl, roomName, participantName, participantToken }`。`threadId` 默认为生成的 room 名称。 ### 选项 **path** (`string`): 路由路径。 (Default: `'/voice/livekit/connection-details'`) **serverUrl** (`string`): LiveKit 服务端 URL。 (Default: `process.env.LIVEKIT_URL`) **apiKey** (`string`): LiveKit API key。 (Default: `process.env.LIVEKIT_API_KEY`) **apiSecret** (`string`): LiveKit API secret。 (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`): room 名称,或根据请求生成名称的函数。 **participantIdentity** (`string | (args) => string`): 参与者身份,或根据请求生成身份的函数。 **metadata** (`(args) => LiveKitSessionMetadata | Promise`): 构建传给 worker 的 session 元数据。默认透传请求 body 中的 agentId、threadId 和 resourceId。 ## `dispatchVoiceSession()` 以编程方式将 Mastra 语音 Agent 分派到 LiveKit room:适用于外呼等服务端发起的 session。 ```typescript import { dispatchVoiceSession } from '@mastra/livekit' await dispatchVoiceSession({ roomName: 'support-call-42', agentName: 'mastra-voice', metadata: { agentId: 'support', threadId: 'thread-42' }, }) ``` ### 选项 **roomName** (`string`): 要将 Agent 分派到的 room。按需创建。 **agentName** (`string`): 必须与 worker 的 agentName 匹配。 (Default: `'mastra-voice'`) **metadata** (`LiveKitSessionMetadata`): session 元数据:agentId、threadId、resourceId、requestContext。 **serverUrl** (`string`): LiveKit 服务端 URL。 (Default: `process.env.LIVEKIT_URL`) **apiKey** (`string`): LiveKit API key。 (Default: `process.env.LIVEKIT_API_KEY`) **apiSecret** (`string`): LiveKit API secret。 (Default: `process.env.LIVEKIT_API_SECRET`) ## `LiveKitSessionMetadata` 通过 LiveKit job 分派从 Mastra 服务端传给 worker 的元数据。 **agentId** (`string`): 要运行的 Mastra Agent,以注册 key 或 Agent ID 指定。 **threadId** (`string`): Memory thread ID。默认为 LiveKit room 名称。 **resourceId** (`string`): Memory resource ID,通常为最终用户 ID。 **requestContext** (`Record`): 恢复到 RequestContext 中供 Agent 执行使用的普通对象条目。 元数据以 JSON 字符串形式传输。`liveKitConnectionRoute()` 和 `dispatchVoiceSession()` 会代为序列化;通过自己的代码分派时,请使用 `serializeSessionMetadata(metadata)`,也可以在 SIP 分派规则等 LiveKit 侧配置中直接写入 JSON。`requestContext` 中的条目会在通话的每个轮次传给 Agent 的 runtime 定义指令、Tool 和输入处理器。 ## 相关内容 - [实时 Voice](https://mastra.zisheng.pro/guides/voice/realtime-voice) - [LiveKit Agents 文档](https://docs.livekit.io/agents/)