Integrate LiveKit Agents

Build a voice assistant with real time email capabilities.

Overview

This guide walks you through building a voice assistant with real time email capabilites. We use the LiveKit Agents SDK to build the voice functionality.

Prequisites

Follow the LiveKit voice AI quickstart to build a simple voice assistant. In this guide we will extend the functionality to this assistant to email.

You should have a file named agent.py which we will modify.

Setup

Install python packages

$pip install agentmail agentmail-toolkit

Set environment variables

1AGENTMAIL_API_KEY=<Your AgentMail API key>
2AGENTMAIL_USERNAME=<Choose a username for your agent's inbox>

Code

To the agent.py file add the following imports

1import os
2import asyncio
3
4from agentmail import AgentMail, AsyncAgentMail, Subscribe, MessageReceived
5from agentmail_toolkit.livekit import AgentMailToolkit

Then add the EmailAssistant class

1class EmailAssistant(Agent):
2 inbox_id: str
3 ws_task: asyncio.Task | None = None
4
5 def __init__(self) -> None:
6 client = AgentMail()
7
8 # By setting the client_id the inbox is created only once.
9 username = os.getenv("AGENTMAIL_USERNAME")
10 inbox = client.inboxes.create(username=username, client_id=f"{username}-inbox")
11
12 self.inbox_id = inbox.inbox_id
13
14 super().__init__(
15 instructions=f"""
16 You are a helpful voice and email AI assistant. Your name is AgentMail. You can receive emails at {self.inbox_id}. You can also send and reply to emails.
17 When using email tools, use "{self.inbox_id}" as the inbox_id parameter. When writing emails, include "AgentMail" in the signature.
18 Always speak in English.
19 IMPORTANT: {self.inbox_id} is your inbox, not the user's inbox.
20 """,
21 # The AgentMail Toolkit has ready-to-go tools for LiveKit agents.
22 tools=AgentMailToolkit(client=client).get_tools(
23 [
24 "list_threads",
25 "get_thread",
26 "get_attachment",
27 "send_message",
28 "reply_to_message",
29 ]
30 ),
31 )
32
33 async def _websocket_task(self):
34 # Open a websocket connection to AgentMail.
35 async with AsyncAgentMail().websockets.connect() as socket:
36 # Subscribe to events from the inbox.
37 await socket.send_subscribe(Subscribe(inbox_ids=[self.inbox_id]))
38
39 while True:
40 data = await socket.recv()
41
42 # If a message is received by the inbox, interrupt the current conversation and generate a reply.
43 if isinstance(data, MessageReceived):
44 self.session.interrupt()
45
46 await self.session.generate_reply(
47 instructions=f"""Say "I've received an email" and then read the email.""",
48 user_input=data.message.model_dump_json(),
49 )
50
51 # Open the websocket connection and generate a greeting when the agent enters the call.
52 async def on_enter(self):
53 self.ws_task = asyncio.create_task(self._websocket_task())
54
55 await self.session.generate_reply(
56 instructions=f"""In English, greet the user, introduce yourself as AgentMail, inform them that you can "receive emails" at {self.inbox_id}, and offer your assistance.""",
57 allow_interruptions=False,
58 )
59
60 # Close the websocket connection when the agent exits the call.
61 async def on_exit(self):
62 if self.ws_task:
63 self.ws_task.cancel()

Finally update the entrypoint function

1await session.start(
2 room=ctx.room,
3 agent=EmailAssistant(), # Replace Assistant with EmailAssistant.
4 room_input_options=RoomInputOptions(
5 noise_cancellation=noise_cancellation.BVC()
6 ),
7)

That’s It

Run your agent inside the terminal and send it an email

$python agent.py console