little-car-50043
09/24/2025, 5:07 PMtall-airline-16756
09/24/2025, 5:07 PMtall-airline-16756
09/24/2025, 5:08 PMexamples/avatar_agents/ directory. Each one comes with clear setup instructions and helpful code samples to guide you through the integration process.
If you'd like to dive deeper, the Virtual Avatar Integrations Guide is a wonderful resource to check out as well.
Sources: examples/avatar_agents/bey/README.md | Virtual avatar integrations | LiveKit Docs | avatars/hedra/education_avatar/education-frontend/components/livekit/media-...little-car-50043
09/24/2025, 5:10 PMtall-airline-16756
09/24/2025, 5:11 PMAgentSession instances, each connected to a different AvatarSession. These avatars will then publish their own synchronized audio and video tracks independently to the room. This setup is especially handy for scenarios like warm transfers or when multiple agents need to collaborate.
If you’d like, I’m here to help guide you through the setup process—just let me know!
Sources: Workflows | LiveKit Docs | README.md | Anatomy of an Agent | LiveKit Docs | Anatomy of an Agent | LiveKit Docs | Virtual avatar integrations | LiveKit Docslittle-car-50043
09/24/2025, 6:27 PMtall-airline-16756
09/24/2025, 6:27 PMAgentSession can be connected to its own AvatarSession, which means every agent gets their own avatar worker that shares synchronized audio and video tracks in the room.
This way, multiple agents with different avatars can comfortably coexist and interact within the same space. If you'd like, I’m here to help you set this up—just let me know!
Sources: Virtual avatar integrations | LiveKit Docs | examples/avatar_agents/bey/README.mdlittle-car-50043
09/24/2025, 6:28 PMtall-airline-16756
09/24/2025, 6:29 PMAgentSession and AvatarSession instances?
• A friendly step-by-step guide to set up multiple avatars in a room?
• Or maybe some details on how the frontend should handle multiple avatars?
Just let me know what works best for you, and I'll make sure to provide the most helpful example!little-car-50043
09/24/2025, 6:41 PMtall-airline-16756
09/24/2025, 6:42 PMlittle-car-50043
09/24/2025, 6:46 PMtall-airline-16756
09/24/2025, 6:47 PMlittle-car-50043
09/24/2025, 6:49 PMtall-airline-16756
09/24/2025, 6:50 PMsession.generate_reply() method along with some conditional logic. Here’s a friendly guide on how to do it:
1. Keep track of the user’s state using self.session.userdata with a custom data class that holds all the important info.
2. Use conditional logic inside methods like on_enter() or @function_tool functions to decide how the agent should respond, depending on the stored state or what the user says.
3. Call generate_reply() with parameters such as user_input or instructions to tailor the response dynamically.
For instance, you might have one agent ask a question and then, based on the user’s answer, either continue with the same agent or switch to another one. If you'd like, I’d be happy to share a specific code example to make this clearer—just let me know!
Sources: examples/src/basic_tool_call_agent.ts | examples/drive-thru/test_agent.py | Agent speech and audio | LiveKit Docs | Agent speech and audio | LiveKit Docs | Workflows | LiveKit Docslittle-car-50043
09/24/2025, 6:51 PMtall-airline-16756
09/24/2025, 6:51 PMfrom dataclasses import dataclass
from livekit.agents import Agent, AgentSession
@dataclass
class UserData:
preference: str = ""
class AgentA(Agent):
async def on_enter(self) -> None:
await self.session.say("You selected Agent A. How can I assist you?")
class AgentB(Agent):
async def on_enter(self) -> None:
await self.session.say("You selected Agent B. What do you need help with?")
class MainAgent(Agent):
async def on_enter(self) -> None:
await self.session.say("Do you prefer Agent A or Agent B?")
@function_tool
async def handle_preference(self, choice: str) -> Agent:
userdata: UserData = self.session.userdata
userdata.preference = choice
if choice.lower() == "a":
return AgentA()
elif choice.lower() == "b":
return AgentB()
else:
await self.session.say("Invalid choice. Please select A or B.")
return self
# Initialize the session
session = AgentSession[UserData](userdata=UserData())
main_agent = MainAgent()
session.run(main_agent)
To break it down:
• The MainAgent kindly asks the user to pick between Agent A or Agent B.
• Depending on what the user chooses, the session smoothly switches to either AgentA or AgentB.
• We also save the user’s preference in userdata, so it’s easy to refer back to later.
If you’d like, I’m here to walk you through any part of this or provide more examples—just let me know!little-car-50043
09/24/2025, 6:52 PMtall-airline-16756
09/24/2025, 6:53 PMev.cancel_tool_reply() within the function_tools_executed event handler.
For instance, you might define a routing function like this:
@function_tool()
async def route_to_support_agent(self):
return llm.handoff({
"agent": SupportAgent(),
"returns": "Routing completed"
})
@session.on("function_tools_executed")
def on_function_tools_executed(ev):
if "route_to_support_agent" in [fnc.name for fnc in ev.function_calls]:
ev.cancel_tool_reply()
This way, the routing happens smoothly and silently, with no audible response. If you have any questions or need a hand with this, please don’t hesitate to ask—I’m here to help!
Sources: examples/voice_agents/README.md | examples/src/comprehensive_test.tslittle-car-50043
09/24/2025, 6:54 PMtall-airline-16756
09/24/2025, 6:55 PMlittle-car-50043
09/24/2025, 6:56 PMtall-airline-16756
09/24/2025, 6:56 PMimport re
from livekit.agents import Agent, AgentSession
class MainAgent(Agent):
async def on_user_turn_completed(self, chat_context, new_message):
# Access the transcribed text
transcript = new_message.content
# Apply regex to determine routing
if re.match(r"^route to support", transcript, re.IGNORECASE):
await self.session.update_agent(SupportAgent())
elif re.match(r"^route to sales", transcript, re.IGNORECASE):
await self.session.update_agent(SalesAgent())
else:
await self.session.say("I didn’t understand your request. Could you clarify?")
class SupportAgent(Agent):
async def on_enter(self):
await self.session.say("You’ve been routed to Support. How can I assist you?")
class SalesAgent(Agent):
async def on_enter(self):
await self.session.say("You’ve been routed to Sales. What can I help you with?")
# Initialize the session
session = AgentSession()
main_agent = MainAgent()
session.run(main_agent)
Here’s a quick overview:
• The on_user_turn_completed method handles the final transcription once the user finishes speaking.
• Regex patterns help match specific phrases like "route to support" or "route to sales".
• Depending on the match, the session smoothly transitions to the right agent, such as SupportAgent or SalesAgent.
• If nothing matches, the main agent kindly asks the user to clarify their request.
Please don’t hesitate to reach out if you’d like any more help or if there’s anything specific you want to customize further—I’m here to support you!little-car-50043
09/24/2025, 7:05 PMtall-airline-16756
09/24/2025, 7:07 PMAgentSession with the specific TTS and avatar settings that suit their roles. Let’s walk through the steps together:
1. Assigning Unique TTS Models
For instance, you might choose OpenAI TTS for your Support team and Cartesia TTS for Sales. Here's a simple example:
from livekit.plugins import openai, cartesia
# Support Agent TTS
support_tts = openai.TTS(
model="gpt-4o-mini-tts",
voice="ash",
instructions="Speak in a friendly tone."
)
# Sales Agent TTS
sales_tts = cartesia.TTS(
model="sonic-2",
voice="f786b574-daa5-4673-aa0c-cbe3e8534c02"
)
2. Assigning Virtual Avatars
Similarly, you can assign avatars like Tavus for Support and bitHuman for Sales. Here's how you might set that up:
from livekit.plugins import tavus, bithuman
# Support Agent Avatar
support_avatar = tavus.AvatarSession(
replica_id="r4c41453d2",
persona_id="p2fbd605"
)
# Sales Agent Avatar
sales_avatar = bithuman.AvatarSession(
avatar_id="your-avatar-id"
)
3. Integrating with Agent Sessions
Next, you'll want to attach these TTS and avatar configurations to each agent’s session. Here’s an example:
from livekit.agents import AgentSession
# Support Agent Session
support_session = AgentSession(tts=support_tts)
await support_avatar.start(support_session, room=ctx.room)
# Sales Agent Session
sales_session = AgentSession(tts=sales_tts)
await sales_avatar.start(sales_session, room=ctx.room)
4. Frontend Rendering
The avatars will publish video tracks to the room, which you can render using LiveKit's client SDKs. If you’d like, I’m here to help you with the frontend setup or answer any questions you have along the way!
Sources: Bringing AI avatars to voice agents | bitHuman virtual avatar integration guide | LiveKit Docs | LiveKit Agents integrations | LiveKit Docs | OpenAI TTS integration guide | LiveKit Docs | Groq TTS integration guide | LiveKit Docslittle-car-50043
09/24/2025, 7:07 PMtall-airline-16756
09/24/2025, 7:08 PMlittle-car-50043
09/24/2025, 7:45 PM