라이브킷
그만큼@mastra/livekit패키지는 Mastra Agent를 LiveKit Agent 프레임워크에 연결합니다. LiveKit은 오디오 파이프라인(음성 활동 감지, 음성-텍스트, 회전 감지, 텍스트-음성, 참여)을 실행하고 패키지는 응답 생성을 Mastra Agent의stream()부르다.
설정과 개념은 실시간 음성을 참조하세요. 패키지에는 세 가지 진입점이 있습니다.
@mastra/livekit: 서버 측 API인liveKitConnectionRoute(),dispatchVoiceSession(),pipeAgentReplyToWriter(),serializeSessionMetadata(),createEndCallTool()을 제공합니다. Mastra 서버 코드에서 가져오세요. 이 진입점은 LiveKit Agent 런타임을 로드하지 않습니다.@mastra/livekit/worker: 작업자 런타임인createLiveKitWorker(),runLiveKitWorker(),chatContextToMessages()와 세션 헬퍼speakGreeting(),waitForAgentDoneSpeaking(),runEndCall()을 제공합니다. 작업자 진입점 파일에서만 가져오세요.@mastra/livekit/plugin: LLM 구성 요소 플러그인인MastraLLM과createRemoteAgentReplyGenerator()를 제공합니다. 자체voice.AgentSession을 구성하는 작업자에서 가져오세요.createRemoteAgentReplyGenerator()는createLiveKitWorker()의generate옵션에 연결되므로@mastra/livekit/worker에서도 내보냅니다.MastraLLM은 플러그인 전용입니다.
createLiveKitWorker()createlivekitworker에 대한 직접 링크
Mastra Agent와의 음성 세션에 응답하는 LiveKit Agent 정의를 구축합니다. 이를 작업자 항목 파일의 기본 내보내기로 사용하십시오.
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이 되며, Model별 사용량 집계와 함께 span이 닫힙니다. 비활성화하려면 false를 전달하세요.inputOptions?:
outputOptions?:
onSessionStart?:
runLiveKitWorker()runlivekitworker에 대한 직접 링크
작업자 진입점 파일의 LiveKit 작업자 CLI(dev, start, connect 하위 명령)를 시작합니다. 작업자 정의를 기본 내보내기하는 파일에서 호출하고, 직접 실행될 때만 실행되도록 보호하세요. 작업자는 세션마다 동일한 파일을 다시 가져오는 자식 프로세스를 생성합니다. @livekit/agents의 cli.runApp 대신 이 헬퍼를 사용하면 작업자 런타임과 브리지가 하나의 LiveKit SDK 사본을 공유합니다.
옵션옵션에 대한 직접 링크
entry:
agentName?:
serverOptions?:
pipeAgentReplyToWriter()pipeagentreplytowriter에 대한 직접 링크
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()이 허용하는 일반 메시지로 변환하며, 지침과 함수 호출은 제외합니다. 상태 비저장 Workflow에 전체 대화 기록을 전달하려면 workflowInput에서 사용하세요.
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 플러그인(llm.LLM)입니다. 직접 voice.AgentSession을 구성하면서 llm 슬롯에 Mastra를 사용하려는 경우 사용하세요. createLiveKitWorker()는 관리형 대안입니다. 선택 방법은 Mastra를 LLM 구성 요소로 사용하기를 참조하세요.
remote를 사용하면 플러그인은 Server-Sent Events(SSE)를 사용하는 HTTP를 통해 Mastra 서버에서 각 턴을 스트리밍합니다. Agent 루프, 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 } },
})
플러그인은 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 없음)는 선제 생성과 함께 사용할 수 있습니다.
Mastra Agent에서 실행되는 ToolMastra Agent에서 실행되는 Tool에 대한 직접 링크
Tool은 Mastra Agent에서 서버 측에 정의되고 실행됩니다. 플러그인은 LiveKit Tool 정의를 전달하지 않습니다. 세션에서 비어 있지 않은 toolCtx를 전달하면 무시된 Tool 이름을 포함한 경고를 한 번 기록합니다. 모든 Tool은 서버 측에서 완료되어야 합니다. 승인 또는 클라이언트 측 실행이 필요한 Tool은 통화를 멈춘 채 대기하는 대신 설명이 포함된 오류와 함께 턴을 실패시킵니다.
Tool 활동은 toolFeedback, onToolCall, onTurnComplete를 통해 작업자에 전달됩니다.
지침지침에 대한 직접 링크
LiveKit은 voice.Agent의 instructions를 모든 요청의 채팅 컨텍스트에 삽입합니다. 서버 측 Mastra Agent 자체의 지침이 우선하므로 플러그인은 이를 제거합니다. Prompt를 변경하려면 Mastra Agent를 변경하세요.
중단된 회전중단된 회전에 대한 직접 링크
사용자가 답장을 중단하는 경우:
- 플러그인이 스트림을 취소합니다. 서버는 생성을 중단하고 해당 턴부터 아무것도 지속하지 않습니다.
- LiveKit은 사용자가 채팅 컨텍스트에서 실제로 들었던 부분을 녹음하고 중단된 것으로 표시됩니다.
- 다음 차례에 플러그인은 새 사용자 메시지 이전에 주문된 청취 전용 조각을 다시 전송하므로 Memory 스레드가 호출과 일치하도록 다시 채워집니다. 메시지는 LiveKit의 메시지 ID를 전달하고 서버는 ID별로 중복을 제거하므로 재시도 및 재전송은 멱등성을 유지합니다.
중단 후 즉시 전화를 끊은 사용자는 마지막 부분을 녹음하지 않은 상태로 둡니다. 기록에서 캡처해야 하는 경우 세션 이벤트에서 즉시 조정합니다. 공유 메시지 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(),
},
],
})
})
사용량 측정항목사용량 측정항목에 대한 직접 링크
서버가 턴의 토큰 사용량을 보고하면 플러그인이 이를 LiveKit에 제공하므로 세션의 metrics_collected 이벤트에 다른 LLM 플러그인과 마찬가지로 첫 토큰까지의 시간, 지속 시간, 토큰 수가 포함됩니다. 동일한 사용량 객체(promptTokens, completionTokens, promptCachedTokens, totalTokens)가 onTurnComplete의 result.usage로 전달됩니다.
오류 및 시간 초과오류 및 시간 초과에 대한 직접 링크
전송 과정에서는 LiveKit의 APIError 유형(APIStatusError, APIConnectionError, APITimeoutError)을 발생시키므로 세션의 재시도 정책(connOptions.maxRetry)과 FallbackAdapter 장애 조치는 변경 없이 작동합니다. 첫 번째 토큰 이후에는 턴을 재시도하지 않습니다. 음성 응답은 일부만 들린 상태로 다시 재생하는 것보다 빠르게 실패하는 편이 낫습니다.
연결 및 첫 토큰 감시는 세션의 connOptions.timeoutMs(기본값 10초)를 사용하므로 연결을 수락한 뒤 스트리밍하지 않는 서버로 인해 무음 상태가 무기한 지속되지 않습니다.
Mastra 서버가 통화 중에 다운되면 각 응답 시도는 재시도 후 입력된 오류와 함께 실패하며, LiveKit은 여러 번 연속 실패한 응답 후에 세션을 닫습니다. 예산이 소진되기 전에 서버를 복원하고 다음 차례에 통화가 복구됩니다.
메시지 내용메시지 내용에 대한 직접 링크
메시지 추출은 텍스트 전용입니다. 이미지 콘텐츠는 삭제되고 오디오 콘텐츠는 해당 내용을 통해서만 포함됩니다. 음성 파이프라인은 영향을 받지 않지만 채팅 컨텍스트에 직접 삽입하는 항목에는 텍스트가 포함되어야 합니다.
createRemoteAgentReplyGenerator()createremoteagentreplygenerator에 대한 직접 링크
HTTP/SSE를 통해 remote Mastra 서버에서 Agent 루프를 실행하는 응답 생성기를 구성합니다. MastraLLM의 remote 모드가 내부적으로 이를 사용합니다. 모든 기능이 포함된 작업자를 원격 서버와 함께 실행하려면 createLiveKitWorker의 generate 옵션을 통해 직접 사용하세요.
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 경로에서는 작업자 수준의 toolFeedback 및 onTurnComplete 옵션이 적용되지 않으며, 작업자의 통화 종료 감지도 실행되지 않습니다. 대신 생성기에 훅을 전달하세요.
턴(참여)을 취소하면 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 발신자를 포함한 발신자의 통화를 종료합니다. 등록된 콜백과 함께 작업이 종료됩니다.
소유한 세션에서 Agent 주도 통화 종료를 다시 구성하려면 서버 측 Agent의 통화 종료 Tool 및 MastraLLM의 onToolCall과 함께 사용하세요.
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은 의도를 알리고 선택적 장부를 실행할 수 있습니다. 작업자가 실제 전화 끊기를 수행합니다. 이 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: {} }을 설정하면 작업자가 Tool을 감시하고 통화를 종료합니다. 소유한 세션에서는 runEndCall()을 사용해 통화 종료를 다시 구성하세요.
옵션옵션에 대한 직접 링크
id?:
description?:
onEndCall?:
liveKitConnectionRoute()livekitconnectionroute에 대한 직접 링크
음성 Agent가 룸에 디스패치된 LiveKit 액세스 토큰을 발급하는 API 경로를 반환합니다. 프런트엔드가 이를 호출해 세션에 참여합니다.
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?:
LiveKitSessionMetadatalivekitsessionmetadata에 대한 직접 링크
LiveKit 작업 디스패치를 통해 Mastra 서버에서 작업자로 전달되는 메타데이터입니다.
agentId?:
threadId?:
resourceId?:
requestContext?:
메타데이터는 JSON 문자열로 전달됩니다. liveKitConnectionRoute()와 dispatchVoiceSession()은 이를 자동으로 직렬화합니다. 자체 코드로 디스패치할 때는 serializeSessionMetadata(metadata)를 사용하거나, SIP 디스패치 규칙 같은 LiveKit 측 구성에 JSON을 직접 작성하세요. requestContext 항목은 통화의 모든 턴에서 Agent의 런타임 정의 지침, Tool, 입력 프로세서에 전달됩니다.