forked from livekit/agents-js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmulti_agent.ts
More file actions
101 lines (90 loc) · 3.18 KB
/
multi_agent.ts
File metadata and controls
101 lines (90 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
//
// SPDX-License-Identifier: Apache-2.0
import {
type JobContext,
type JobProcess,
WorkerOptions,
cli,
defineAgent,
llm,
voice,
} from '@livekit/agents';
import * as deepgram from '@livekit/agents-plugin-deepgram';
import * as elevenlabs from '@livekit/agents-plugin-elevenlabs';
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 { z } from 'zod';
// Shared data that's used by the storyteller agent.
// This structure is passed as a parameter to function calls.
type StoryData = {
name?: string;
location?: string;
};
// Use inheritance to create agent with custom hooks
class IntroAgent extends voice.Agent<StoryData> {
async onEnter() {
this.session.generateReply({
instructions: '"greet the user and gather information"',
});
}
static create() {
return new IntroAgent({
instructions: `You are a story teller. Your goal is to gather a few pieces of information from the user to make the story personalized and engaging. Ask the user for their name and where they are from.`,
tools: {
informationGathered: llm.tool({
description:
'Called when the user has provided the information needed to make the story personalized and engaging.',
parameters: z.object({
name: z.string().describe('The name of the user'),
location: z.string().describe('The location of the user'),
}),
execute: async ({ name, location }, { ctx }) => {
ctx.userData.name = name;
ctx.userData.location = location;
const storyAgent = StoryAgent.create(name, location);
return llm.handoff({ agent: storyAgent, returns: "Let's start the story!" });
},
}),
},
});
}
}
class StoryAgent extends voice.Agent<StoryData> {
async onEnter() {
this.session.generateReply();
}
static create(name: string, location: string) {
return new StoryAgent({
instructions: `You are a storyteller. Use the user's information in order to make the story personalized.
The user's name is ${name}, from ${location}`,
});
}
}
export default defineAgent({
prewarm: async (proc: JobProcess) => {
proc.userData.vad = await silero.VAD.load();
},
entry: async (ctx: JobContext) => {
const userdata: StoryData = {};
const session = new voice.AgentSession({
vad: ctx.proc.userData.vad! as silero.VAD,
stt: new deepgram.STT(),
tts: new elevenlabs.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: userdata,
turnDetection: new livekit.turnDetector.EnglishModel(),
});
await session.start({
agent: IntroAgent.create(),
room: ctx.room,
});
const participant = await ctx.waitForParticipant();
console.log('participant joined: ', participant.identity);
},
});
cli.runApp(new WorkerOptions({ agent: fileURLToPath(import.meta.url) }));