mastra-ai/mastra · error

@mastra/livekit: no Mastra agent specified. Set `agent` on c

Error message

@mastra/livekit: no Mastra agent specified. Set `agent` on createLiveKitWorker or pass `agentId` in the dispatch metadata (e.g. via liveKitConnectionRoute).

What it means

resolveMastraAgent determines which Mastra agent the voice worker should talk to: it takes options.agent (value or async function), falls back to the `agentId` in the LiveKit dispatch metadata, and throws if both are absent. Without an agent reference it cannot route the conversation.

Source

Thrown at integrations/livekit/src/worker.ts:248

      `@mastra/livekit: turnDetection '${kind}' requires '@livekit/agents-plugin-livekit'. ` +
        "Install it or use a built-in mode like 'vad' or 'stt'.",
      { cause: error },
    );
  }
  return kind === 'english'
    ? (new plugin.turnDetector.EnglishModel() as TurnDetectionSetting)
    : (new plugin.turnDetector.MultilingualModel() as TurnDetectionSetting);
}

async function resolveMastraAgent(
  options: CreateLiveKitWorkerOptions,
  args: ResolveMastraAgentArgs,
): Promise<MastraAgent> {
  let ref: string | MastraAgent | undefined =
    typeof options.agent === 'function' ? await options.agent(args) : options.agent;
  ref ??= args.metadata.agentId;
  if (!ref) {
    throw new Error(
      '@mastra/livekit: no Mastra agent specified. Set `agent` on createLiveKitWorker or pass ' +
        '`agentId` in the dispatch metadata (e.g. via liveKitConnectionRoute).',
    );
  }
  if (typeof ref !== 'string') return ref;
  try {
    return options.mastra.getAgentById(ref);
  } catch {
    return options.mastra.getAgent(ref);
  }
}

// Returns the workflow boxed in an object: `Workflow` is thenable (it has a `.then()` builder
// method), so a bare `Promise<Workflow>` return — or awaiting a `Workflow`-typed value — trips
// TS's thenable checks and, at runtime, `await workflow` would call the builder's `.then`.
async function resolveWorkflow(
  options: CreateLiveKitWorkerOptions,
  args: ResolveMastraAgentArgs,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set `agent` on createLiveKitWorker (an agent instance, id string, or resolver function).
  2. Ensure dispatch metadata includes agentId when dispatching the session (e.g. via liveKitConnectionRoute or dispatchVoiceSession metadata).
  3. If using an async agent resolver, make sure it resolves to a defined agent/id rather than undefined.

Example fix

// before
createLiveKitWorker({ mastra, workflow: 'voiceFlow' }); // no agent anywhere
// after
createLiveKitWorker({ mastra, workflow: 'voiceFlow', agent: 'support-agent' });
// or at dispatch time
await dispatchVoiceSession({ roomName, metadata: { agentId: 'support-agent' } });
Defensive patterns

Strategy: validation

Validate before calling

function assertVoiceAgentConfigured(workerOptions, dispatchMetadata = {}) {
  const resolved = typeof workerOptions.agent === 'function' ? undefined : workerOptions.agent;
  if (!resolved && !dispatchMetadata.agentId) {
    throw new Error('Voice worker needs options.agent or agentId in dispatch metadata');
  }
}
assertVoiceAgentConfigured(opts, roomMetadata);

Try / catch

try {
  await startVoiceSession(args);
} catch (e) {
  if (e instanceof Error && e.message.includes('no Mastra agent specified')) {
    console.error('Dispatch metadata keys:', Object.keys(args.metadata)); // debug missing agentId
  }
  throw e;
}

Prevention

When it happens

Trigger: createLiveKitWorker called without an `agent` option (or an agent resolver returning undefined), and the room's dispatch metadata (set at dispatch time, e.g. by liveKitConnectionRoute) contains no agentId.

Common situations: Worker configured for dynamic per-room agent selection but the dispatch side never set agentId in metadata; agent resolver returning undefined when its lookup fails; migrating from static to dynamic agent config and dropping the default.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/c89809a16261b64a. Report an issue: GitHub.