{"record":{"id":"00de05d657a129f5","repo":"mastra-ai/mastra","slug":"mastra-livekit-mastravoiceagent-requires-agent-00de05","errorCode":null,"errorMessage":"@mastra/livekit: MastraVoiceAgent requires `agent` or `generate`.","messagePattern":"@mastra/livekit: MastraVoiceAgent requires `agent` or `generate`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integrations/livekit/src/bridge.ts","lineNumber":474,"sourceCode":"      this.reminder = new DisclosureReminder(\n        options.greetingReminder.everyMs,\n        options.greetingReminder.text?.trim() || DEFAULT_DISCLOSURE_REMINDER,\n      );\n    }\n\n    if (options.generate) {\n      this.replyGenerator = options.generate;\n    } else if (options.agent) {\n      this.mastraAgent = options.agent;\n      this.replyGenerator = createAgentReplyGenerator({\n        agent: options.agent,\n        streamOptions: options.streamOptions,\n        toolFeedback: options.toolFeedback,\n        onToolCall: options.onToolCall,\n        onTurnComplete: options.onTurnComplete,\n      });\n    } else {\n      throw new Error('@mastra/livekit: MastraVoiceAgent requires `agent` or `generate`.');\n    }\n  }\n\n  override async llmNode(\n    chatCtx: llm.ChatContext,\n    _toolCtx: llm.ToolContext,\n    _modelSettings: voice.ModelSettings,\n  ): Promise<ReadableStream<llm.ChatChunk | string> | null> {\n    const messages: VoiceTurnMessage[] =\n      this.memory === false ? chatContextToMessages(chatCtx) : extractNewTurnMessages(chatCtx);\n    if (messages.length === 0) return null;\n\n    const reply = await this.replyGenerator({\n      messages,\n      chatCtx,\n      memory: this.memory,\n      requestContext: this.requestContext,\n      tracingContext: this.streamOptions?.tracingContext,","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/integrations/livekit/src/bridge.ts#L456-L492","documentation":"The MastraVoiceAgent constructor requires exactly one reply source: a Mastra `agent` instance or a `generate` function. When neither is provided, the constructor's else branch throws this error, because without a reply source the agent's llmNode would have nothing to produce voice replies with.","triggerScenarios":"new MastraVoiceAgent({ id, instructions, ... }) with neither `agent` nor `generate` in options — e.g. building options dynamically and both branches that set them failing to run, or calling with only metadata options.","commonSituations":"Conditional code like `if (useAgent) opts.agent = a; if (useGenerate) opts.generate = g;` where neither condition matched; deserialized/parsed config that dropped function-valued `generate`; forgetting to import/instantiate the Mastra agent and passing undefined.","solutions":["Pass a Mastra agent instance: new MastraVoiceAgent({ agent: myAgent }).","Or pass a custom reply function: new MastraVoiceAgent({ generate: async (ctx) => '...' }).","Check options-building code so at least one of agent/generate is always assigned; validate before constructing."],"exampleFix":"// before\nnew MastraVoiceAgent({ id: 'va', instructions: 'You are helpful' })\n// after\nnew MastraVoiceAgent({ id: 'va', instructions: 'You are helpful', agent: new Agent({ name: 'assistant', instructions: '...', model }) })","handlingStrategy":"validation","validationCode":"function assertHasReplySource(o: MastraVoiceAgentOptions): void {\n  if (!o.agent && !o.generate) {\n    throw new Error('MastraVoiceAgent requires `agent` or `generate`');\n  }\n}","typeGuard":"function hasReplySource(o: MastraVoiceAgentOptions): o is MastraVoiceAgentOptions & ({ agent: NonNullable<MastraVoiceAgentOptions['agent']> } | { generate: NonNullable<MastraVoiceAgentOptions['generate']> }) {\n  return Boolean(o.agent || o.generate);\n}","tryCatchPattern":null,"preventionTips":["Make `agent` or `generate` required in your own wrapper's options type so TypeScript enforces it.","Beware deserialized configs silently dropping function-valued `generate` options.","Validate options immediately before construction; fail with a clear message."],"tags":["validation","api-misuse","constructor","livekit"],"backgroundTag":"missing-required-option","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}