Skip to content

Error: runner initialization timed outΒ #909

@cherniavsky94w

Description

@cherniavsky94w

Describe the bug

I am creating new app with aws ecs
I tried run app as start and special room

Relevant log output

file:///app/node_modules/.pnpm/@livekit+agents@1.0.27_@livekit[email protected][email protected]/node_modules/@livekit/agents/dist/ipc/supervised_proc.js:114
throw err;
Error: runner initialization timed out
at Timeout.onTimeout (file:///app/node_modules/.pnpm/@livekit[email protected]@livekit[email protected][email protected]/node_modules/@livekit/agents/dist/ipc/supervised_proc.js:112:19)
at listOnTimeout (node:internal/timers:588:17)
at process.processTimers (node:internal/timers:523:7)

Describe your environment

aws ecs ec2 container

Minimal reproducible example

agent.ts

import {
  type JobContext,
  type JobProcess,
  cli,
  defineAgent,
  voice,
  metrics,
  ServerOptions,
} from '@livekit/agents';
import { type Room } from '@livekit/rtc-node';
import dotenv from 'dotenv';
import * as deepgram from '@livekit/agents-plugin-deepgram';
import * as livekit from '@livekit/agents-plugin-livekit';
import * as openai from '@livekit/agents-plugin-openai';
import * as silero from '@livekit/agents-plugin-silero';
import { fileURLToPath } from 'node:url';
import { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol';
import { AccessToken } from 'livekit-server-sdk';

dotenv.config();
export class RealtimeAgent extends voice.Agent {
  override async onEnter(): Promise<void> {
    await this.session.say("Hello, how can I help you today?", {
      allowInterruptions: false,
    });
    return Promise.resolve();
  }
  static create({
    room,
  }: {
    room: Room;
  }) {
    return new RealtimeAgent({
      instructions: 'You are a helpful agent. Your name is Mario. You can check the weather forecast, search information in the knowledge base and transfer to human.',
    });
  }
}

async function createTokenWithAgentDispatch(roomName: string, agentName: string) {
  const at = new AccessToken();
  at.identity = 'my-participant';
  at.addGrant({ roomJoin: true, room: roomName });
  at.roomConfig = new RoomConfiguration({
    agents: [
      new RoomAgentDispatch({
        agentName: agentName,
        metadata: '{"user_id": "12345"}',
      }),
    ],
  });
  return await at.toJwt();

}

export default defineAgent({
  prewarm: async (proc: JobProcess) => {
    console.log('Starting VAD model prewarm...');
    const startTime = Date.now();
    try {
      proc.userData.vad = await Promise.race([
        silero.VAD.load(),
        new Promise((_, reject) => setTimeout(() => reject(new Error('VAD load timed out')), 5000))
      ]);
      const loadTime = Date.now() - startTime;
      console.log(`VAD model loaded in ${loadTime}ms`);
    } catch (e) {
      console.error('Failed to prewarm VAD model:', e);
      // Fallback or let it fail, but don't hang
      throw e;
    }
  },
  entry: async (ctx: JobContext) => {
    await createTokenWithAgentDispatch(ctx.room.name!, 'realtime-voice-agent');

    const session = new voice.AgentSession({
      // vad: ctx.proc.userData.vad! as silero.VAD,
      stt: new deepgram.STT(),
      tts: new deepgram.TTS(),
      llm: new openai.LLM(),
      // to use realtime model, replace the stt, llm, tts and vad with the following
      // llm: new openai.realtime.RealtimeModel(),
      userData: {},
      turnDetection: new livekit.turnDetector.MultilingualModel(),
    });



    const usageCollector = new metrics.UsageCollector();
    session.on(voice.AgentSessionEventTypes.MetricsCollected, (ev) => {
      metrics.logMetrics(ev.metrics);
      usageCollector.collect(ev.metrics);
    });

    const logUsage = async () => {
      const summary = usageCollector.getSummary();
      console.log(`Usage: ${JSON.stringify(summary)}`);
    };

    ctx.addShutdownCallback(logUsage);

    console.log({ ctx, session })

    await session.start({
      agent: RealtimeAgent.create({ room: ctx.room }),
      room: ctx.room,
    });

    session.on(voice.AgentSessionEventTypes.MetricsCollected, (ev) => {
      metrics.logMetrics(ev.metrics);
      usageCollector.collect(ev.metrics);
    });

    const participant = await ctx.waitForParticipant();
    console.log('participant joined: ', participant.identity);

    // session.on()
  },
});

cli.runApp(new ServerOptions({
  agent: fileURLToPath(import.meta.url),
  agentName: 'realtime-voice-agent',
  logLevel: 'debug',
  production: process.env.NODE_ENV === 'production',
  apiKey: process.env.LIVEKIT_API_KEY as string,
  apiSecret: process.env.LIVEKIT_API_SECRET as string,
  wsURL: process.env.LIVEKIT_URL as string,
  host: '0.0.0.0',
  port: 3001,
  initializeProcessTimeout: 120_000,
}));

Dockerfile

ARG NODE_VERSION=22
ARG PLATFORM=linux/amd64
FROM --platform=${PLATFORM} node:${NODE_VERSION}-slim AS base

WORKDIR /app

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"

RUN apt-get update -qq && \
  apt-get install --no-install-recommends -y ca-certificates libgomp1 && \
  rm -rf /var/lib/apt/lists/* && \
  npm i -g corepack@latest && \
  corepack enable

COPY ./package.json ./pnpm-lock.yaml ./pnpm-workspace.yaml ./tsconfig.json ./.npmrc ./
COPY ./packages/agent ./packages/agent

# Install the project dependencies
RUN pnpm install --frozen-lockfile --filter realtime-voice-agent && \
    pnpm --filter realtime-voice-agent -r build && \
    pnpm deploy --filter realtime-voice-agent --prod packages/agent/deploy && \
    cd packages/agent/deploy


FROM --platform=${PLATFORM} node:${NODE_VERSION}-slim AS app
LABEL project="realtime-voice-agent"
WORKDIR /app

# Create a non-privileged user that the app will run under
# See https://docs.docker.com/develop/develop-images/dockerfile_best_practices/#user
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/app" \
    --shell "/sbin/nologin" \
    --uid "${UID}" \
    appuser

# Set proper permissions
RUN chown -R appuser:appuser /app

COPY --from=base /app/packages/agent/deploy .

RUN apt-get update -qq && \
  apt-get install --no-install-recommends -y ca-certificates libgomp1 tini && \
  rm -rf /var/lib/apt/lists/* && \
  chown -R appuser:appuser /app

USER appuser

RUN node dist/agent.js download-files

ENTRYPOINT ["/bin/sh", "./docker-entrypoint.sh"]

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions