diff --git a/package.json b/package.json index 28dd2fd..7b7ee53 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "vitest": "^4.1.4" }, "dependencies": { - "@livekit/agents": "^1.4.7", + "@livekit/agents": "0.0.0-next-20260624041820", "@livekit/plugins-ai-coustics": "^0.2.14", "dotenv": "^17.4.1", "zod": "^3.25.76" diff --git a/src/agent.test.ts b/src/agent.test.ts index 46de9fa..6f61ed5 100644 --- a/src/agent.test.ts +++ b/src/agent.test.ts @@ -1,7 +1,7 @@ import { dedent, inference, initializeLogger, voice } from '@livekit/agents'; import dotenv from 'dotenv'; import { afterEach, beforeEach, describe, it } from 'vitest'; -import { Agent } from './agent'; +import { createAgent } from './agent'; dotenv.config({ path: '.env.local' }); @@ -16,7 +16,7 @@ describe('agent evaluation', () => { beforeEach(async () => { judgeLlm = new inference.LLM({ model: 'openai/gpt-4.1-mini' }); session = new voice.AgentSession(); - await session.start({ agent: new Agent() }); + await session.start({ agent: createAgent() }); }); afterEach(async () => { diff --git a/src/agent.ts b/src/agent.ts index 35da056..ca06058 100644 --- a/src/agent.ts +++ b/src/agent.ts @@ -1,10 +1,10 @@ -import { dedent, inference, voice } from '@livekit/agents'; +import { Agent, dedent, inference } from '@livekit/agents'; -// Define a custom voice AI assistant by extending the base Agent class -export class Agent extends voice.Agent { - constructor() { - super({ - instructions: dedent` +// Build a custom voice AI assistant with the functional `Agent.create` API +// (introduced in @livekit/agents 1.5.0). You can also subclass `voice.Agent`. +export function createAgent() { + return Agent.create({ + instructions: dedent` You are a friendly, reliable voice assistant that answers questions, explains topics, and completes tasks with available tools. # Output rules @@ -38,42 +38,72 @@ export class Agent extends voice.Agent { - Protect privacy and minimize sensitive data. `, - // A Large Language Model (LLM) is your agent's brain, processing user input and generating a response - // See all available models at https://docs.livekit.io/agents/models/llm/ - llm: new inference.LLM({ model: 'openai/gpt-5.2-chat-latest' }), + // A Large Language Model (LLM) is your agent's brain, processing user input and generating a response + // See all available models at https://docs.livekit.io/agents/models/llm/ + llm: new inference.LLM({ model: 'openai/gpt-5.2-chat-latest' }), - // To use a realtime model instead of a voice pipeline, replace the LLM - // with a RealtimeModel and remove the STT/TTS from the AgentSession - // (Note: This is for the OpenAI Realtime API. For other providers, see https://docs.livekit.io/agents/models/realtime/) - // 1. Install '@livekit/agents-plugin-openai' - // 2. Set OPENAI_API_KEY in .env.local - // 3. Add `import * as openai from '@livekit/agents-plugin-openai'` to the top of this file - // 4. Replace the llm option with: - // llm: new openai.realtime.RealtimeModel({ voice: 'marin' }), + // To use a realtime model instead of a voice pipeline, replace the LLM + // with a RealtimeModel and remove the STT/TTS from the AgentSession + // (Note: This is for the OpenAI Realtime API. For other providers, see https://docs.livekit.io/agents/models/realtime/) + // 1. Install '@livekit/agents-plugin-openai' + // 2. Set OPENAI_API_KEY in .env.local + // 3. Add `import * as openai from '@livekit/agents-plugin-openai'` to the top of this file + // 4. Replace the llm option with: + // llm: new openai.realtime.RealtimeModel({ voice: 'marin' }), - // To add tools, specify `tools` in the constructor. - // Here's an example that adds a simple weather tool. - // You also have to add `import { llm } from '@livekit/agents' and `import { z } from 'zod'` to the top of this file - // tools: { - // getWeather: llm.tool({ - // description: dedent` - // Use this tool to look up current weather information in the given location. - // - // If the location is not supported by the weather service, the tool will indicate this. - // You must tell the user the location's weather is unavailable. - // `, - // parameters: z.object({ - // location: z - // .string() - // .describe('The location to look up weather information for (e.g. city name)'), - // }), - // execute: async ({ location }) => { - // console.log(`Looking up weather for ${location}`); - // - // return 'sunny with a temperature of 70 degrees.'; - // }, - // }), - // }, - }); - } + // To add tools, specify `tools` in the constructor. + // Here's an example that adds a simple weather tool. + // You also have to add `import { tool } from '@livekit/agents'` and `import { z } from 'zod'` to the top of this file + // tools: [ + // tool({ + // name: 'getWeather', + // description: dedent` + // Use this tool to look up current weather information in the given location. + // + // If the location is not supported by the weather service, the tool will indicate this. + // You must tell the user the location's weather is unavailable. + // `, + // parameters: z.object({ + // location: z + // .string() + // .describe('The location to look up weather information for (e.g. city name)'), + // }), + // execute: async ({ location }) => { + // console.log(`Looking up weather for ${location}`); + // + // return 'sunny with a temperature of 70 degrees.'; + // }, + // }), + // ], + + // You can also group long-running async tools behind a shared, scoped lifecycle with an + // `AsyncToolset` (import `AsyncToolset` from '@livekit/agents'). `setup` runs when the agent + // becomes active — connect to a backend and register tools via `updateTools` — and `aclose` + // tears it down. Its tools run on a scoped executor, so non-blocking / cancellable async + // tools keep working across agent handoffs. Add the toolset to this `tools` array like any + // other tool: + // + // let supportClient: SupportClient | undefined; + // AsyncToolset.create({ + // id: 'support-backend', + // tools: [], + // setup: async ({ updateTools }) => { + // supportClient = await connectToSupportBackend(); + // updateTools([ + // tool({ + // name: 'lookupOrder', + // description: 'Look up the status of a customer order by its ID.', + // parameters: z.object({ orderId: z.string() }), + // execute: async ({ orderId }, { ctx }) => { + // ctx.update('Looking up your order, one moment.'); + // return `Order ${orderId} is ${await supportClient!.statusOf(orderId)}.`; + // }, + // }), + // ]); + // }, + // aclose: async () => { + // await supportClient?.disconnect(); + // }, + // }), + }); } diff --git a/src/main.ts b/src/main.ts index 664a6fe..ad0769f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ import { ServerOptions, cli, defineAgent, inference, voice } from '@livekit/agen import { audioEnhancement } from '@livekit/plugins-ai-coustics'; import dotenv from 'dotenv'; import { fileURLToPath } from 'node:url'; -import { Agent } from './agent'; +import { createAgent } from './agent'; // Load environment variables from a local file. // Make sure to set LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET @@ -41,7 +41,7 @@ export default defineAgent({ // Start the session, which initializes the voice pipeline and warms up the models await session.start({ - agent: new Agent(), + agent: createAgent(), room: ctx.room, inputOptions: { // ai-coustics QUAIL audio enhancement for noise cancellation