Realtime Voice Agent

advanced15 minrealtime-voice-agent.ts

The same WebSocket server, but backed by a realtime model with server-side tools.

What it shows

  • Run VoiceAgent in realtime mode on Gemini Live
  • Talk to it from a WebSocket client

The code

realtime-voice-agent.ts
import { VoiceAgent } from '@cogitator-ai/voice';
import { WebSocket } from 'ws';

const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) throw new Error('Set GOOGLE_API_KEY');

const voiceAgent = new VoiceAgent({
  mode: 'realtime',
  agent: {
    run: async () => ({ content: '' }),
    instructions: 'You are a concise voice concierge. Use tools when they help.',
  },
  realtimeProvider: 'gemini',
  realtimeApiKey: apiKey,
  voice: 'Puck',
  tools: [
    {
      name: 'get_opening_hours',
      description: 'Opening hours of the office for a given weekday',
      parameters: {
        type: 'object',
        properties: { day: { type: 'string', description: 'Weekday name' } },
        required: ['day'],
      },
      execute: async (args) => {
        const { day } = args as { day: string };
        return { day, open: '09:00', close: day.toLowerCase() === 'friday' ? '15:00' : '18:00' };
      },
    },
  ],
});
voiceAgent.on('error', (error) => console.error(error.message));
await voiceAgent.listen(0);

const client = new WebSocket(`ws://localhost:${voiceAgent.port}/voice`);
let audioBytes = 0;
const answered = new Promise<void>((resolve) => {
  client.on('message', (data, isBinary) => {
    if (isBinary) {
      audioBytes += (data as Buffer).length;
      return;
    }
    const event = JSON.parse(data.toString()) as { type: string; text?: string; role?: string };
    if (event.type === 'transcript') console.log(`[${event.role}] ${event.text}`);
    if (event.type === 'turn_end' && audioBytes > 0) resolve();
  });
});
await new Promise<void>((resolve) => client.once('open', () => resolve()));

client.send(JSON.stringify({ type: 'text', text: 'When does the office close on Friday?' }));
await Promise.race([answered, new Promise((resolve) => setTimeout(resolve, 30_000))]);
console.log(`Received ${audioBytes} bytes of PCM16 24kHz audio`);

client.close();
await voiceAgent.close();

Run it

install · bash
pnpm add @cogitator-ai/voice ws ws
EnvironmentGOOGLE_API_KEY
run · bash
GOOGLE_API_KEY=your-key npx tsx realtime-voice-agent.ts

Or run the full example from a clone of the repository (keys in .env):

repository · bash
npx tsx examples/voice/04-realtime-voice-agent.ts

Learn more