{"record":{"id":"f9c687381d788712","repo":"mastra-ai/mastra","slug":"mastra-livekit-reply-generation-runs-through-the","errorCode":null,"errorMessage":"@mastra/livekit: reply generation runs through the Mastra agent via llmNode; the placeholder LLM cannot be used for inference.","messagePattern":"@mastra/livekit: reply generation runs through the Mastra agent via llmNode; the placeholder LLM cannot be used for inference\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integrations/livekit/src/bridge.ts","lineNumber":415,"sourceCode":" * The session only runs its cascaded reply pipeline when an `llm` instance is present —\n * `llmNode` replaces the inference step, but the gate checks `llm instanceof LLM`. This\n * placeholder satisfies the gate; the Mastra agent/workflow does the actual generation.\n */\nclass MastraPlaceholderLLM extends llm.LLM {\n  label(): string {\n    return 'mastra.MastraVoiceAgent';\n  }\n\n  override get model(): string {\n    return 'mastra-agent';\n  }\n\n  override get provider(): string {\n    return 'mastra';\n  }\n\n  chat(): llm.LLMStream {\n    throw new Error(\n      '@mastra/livekit: reply generation runs through the Mastra agent via llmNode; the placeholder LLM cannot be used for inference.',\n    );\n  }\n}\n\n/**\n * A LiveKit `voice.Agent` whose replies come from a Mastra agent or workflow.\n *\n * LiveKit keeps ownership of the audio loop (VAD, STT, turn detection, TTS, barge-in) and calls\n * `llmNode` once per detected user turn; the node delegates to a {@link VoiceReplyGenerator}\n * which streams text deltas back. On barge-in LiveKit cancels the returned stream, which aborts\n * the in-flight generation.\n */\nexport class MastraVoiceAgent extends voice.Agent {\n  readonly mastraAgent?: MastraAgent;\n  readonly memory: MastraVoiceAgentMemory | false;\n  readonly requestContext?: RequestContext;\n  readonly streamOptions?: MastraStreamOptions;","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/integrations/livekit/src/bridge.ts#L397-L433","documentation":"The placeholder LLM shipped inside MastraVoiceAgent implements chat() solely to satisfy the LiveKit Agent interface — it never performs inference. If code calls chat() directly (e.g. bypassing the agent's llmNode pipeline), the bridge throws this error to make it explicit that reply generation must flow through the Mastra agent via llmNode.","triggerScenarios":"Calling chat() on a MastraVoiceAgent (or its placeholder LLM) directly, or configuring a LiveKit pipeline component that invokes the LLM's chat() instead of the agent's llmNode — e.g. custom turn-detection or manual session code driving the LLM itself.","commonSituations":"Porting plain LiveKit agent code that called this.llm.chat(...) manually; wiring the MastraVoiceAgent into a pipeline expecting a vanilla LLM; constructing MastraVoiceAgent without agent/generate and then trying to use its LLM.","solutions":["Do not call chat() on the agent's LLM; rely on llmNode which routes turns through the Mastra agent.","Construct MastraVoiceAgent with a valid `agent` (Mastra agent instance) or `generate` function so llmNode has a real reply source.","If you need manual reply generation, use the `generate` option instead of invoking the LLM directly.","Remove or replace any custom pipeline code that calls the LLM's chat() method directly."],"exampleFix":"// before\nconst stream = await voiceAgent.llm.chat(chatCtx); // throws\n// after\nconst stream = voiceAgent.llmNode(chatCtx, toolCtx); // routed through the Mastra agent","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// never call voiceAgent.llm.chat() directly; if wrapping the pipeline:\ntry {\n  const stream = voiceAgent.llmNode(chatCtx, toolCtx);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('placeholder LLM cannot be used')) {\n    throw new Error('Misconfigured pipeline: route replies through llmNode with a real agent/generate');\n  }\n  throw err;\n}","preventionTips":["Treat the agent's LLM as an internal placeholder; only use llmNode for inference.","Always construct MastraVoiceAgent with a real `agent` or `generate` reply source.","When porting vanilla LiveKit code, replace llm.chat(...) calls with the agent pipeline.","Review custom pipeline components for direct LLM method invocation."],"tags":["api-misuse","livekit","voice","llm"],"backgroundTag":"placeholder-llm-called","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}