Overview
LemonSlice provides realtime avatars in any style, from lifelike humans to cartoon mascots and animals. You can use the open source LemonSlice integration for LiveKit Agents to seamlessly add virtual avatars to your voice AI app.
Installation
uv add "livekit-agents[lemonslice]~=1.5"
pnpm add @livekit/agents-plugin-lemonslice
Authentication
The LemonSlice plugin requires a LemonSlice API key .
Set LEMONSLICE_API_KEY in your .env file.
Avatar setup
The LemonSlice plugin requires one of three sources to start an avatar session: an image URL set by agent_image_url, an in-memory image set by agent_image, or an agent ID set by agent_id. Only one of these parameters can be configured.
Agent Image URL
The LemonSlice plugin accepts a source image URL from which to generate the avatar. The avatars render as 368x560 pixel videos. LemonSlice will automatically center-crop your image to the target aspect ratio if the dimensions do not match the expected values. LemonSlice supports a wide range of faces, from humanoid to animal, and styles from photorealistic to animated. Best results are achieved with anthropomorphic images where the face and mouth are clearly identifiable. The image URL must be publicly accessible and return an image/* content type.
Agent image
To use an image you generate or already hold in memory, pass a PIL Image as agent_image instead of hosting it at a URL. The plugin uploads the image to LemonSlice directly. Pillow ships with the plugin, so you don't need to install it separately. The same image guidance as Agent Image URL applies: best results come from anthropomorphic images with a clearly identifiable face and mouth.
from pathlib import Pathfrom PIL import Imageavatar = lemonslice.AvatarSession(agent_image=Image.open(Path(__file__).parent / "avatar.jpg"),agent_prompt="Be expressive in your movements and use your hands while talking.",)
Agent ID
To use an existing LemonSlice agent as your avatar, set the agent_id in AvatarSession. You can find the agent ID in the LemonSlice agent dashboard . You can also create new LemonSlice agents through the agent creation flow by specifying an image.
LiveKit TTS settings will supersede selected voices and personalities configured for the LemonSlice agent.
Usage
Use the plugin in an AgentSession. For example, you can use this avatar in the Voice AI quickstart.
from livekit import agentsfrom livekit.agents import AgentServer, AgentSessionfrom livekit.plugins import lemonsliceserver = AgentServer()@server.rtc_session(agent_name="my-agent")async def my_agent(ctx: agents.JobContext):session = AgentSession(# ... stt, llm, tts, etc.)avatar = lemonslice.AvatarSession(# Publicly accessible image URL for the avataragent_image_url="...",# Prompt to guide the avatar's movementsagent_prompt="Be expressive in your movements and use your hands while talking.")# Start the avatar and wait for it to joinawait avatar.start(session, room=ctx.room)# Start your agent session with the userawait session.start(# ... room, agent, room_options, etc....)
import { voice } from '@livekit/agents';import * as lemonslice from '@livekit/agents-plugin-lemonslice';const session = new voice.AgentSession({// Add STT, LLM, TTS, and other components here});const avatar = new lemonslice.AvatarSession({agentImageUrl: 'publicly-accessible-image-url',apiKey: 'your-lemonslice-api-key', // or set LEMONSLICE_API_KEY env var});// Start the avatar and wait for it to joinawait avatar.start(session, room);// Start your agent session with the userawait session.start(// ... room, agent, room_options, etc.);
Preview the avatar in the Agent Console or a frontend starter app that you build.
Parameters
This section describes some of the available parameters. See the plugin reference for a complete list of all available parameters.
agent_image_urlstringPublicly accessible image url for the avatar. See Agent Image Setup for details.
agent_imageImageAn in-memory PIL image for the avatar. See Agent image setup for details.
agent_idstringThe ID of the LemonSlice agent to use. See Agent ID Setup for details.
agent_promptstringA high-level system prompt that subtly influences the avatar's movements, expressions, and emotional demeanor. This prompt is best used to suggest general affect or behavior (e.g., "feel excited" or "look sad") rather than precise or deterministic actions.
idle_timeoutintIdle timeout in seconds. The avatar will leave the session if this timeout is hit. Defaults to 60 seconds. If a negative number is provided, the session will have no idle timeout.
Third-party meeting platforms
Send a LemonSlice avatar into a Zoom, Google Meet, Microsoft Teams, or Webex meeting. The avatar joins through a LemonSlice-managed relay that streams the meeting's mixed audio into your agent's STT and publishes the avatar's audio and video into the call.
avatar = lemonslice.AvatarSession(agent_image_url="...",)# Start the avatar and wait for it to joinawait avatar.start(session, room=ctx.room)# Send the avatar into the meetingawait avatar.join_meeting("https://zoom.us/j/123456789?pwd=abcdef",bot_name="Support Agent",listen_to_meeting_chat=True,)# Start the agent session using meeting audio as inputawait session.start(agent=agent,room=ctx.room,room_options=avatar.room_options(),)
const avatar = new lemonslice.AvatarSession({agentImageUrl: 'publicly-accessible-image-url',});// Start the avatar and wait for it to joinawait avatar.start(session, ctx.room);// Send the avatar into the meetingawait avatar.joinMeeting('https://zoom.us/j/123456789?pwd=abcdef', {botName: 'Support Agent',listenToMeetingChat: true,});// Start the agent session using meeting audio as inputawait session.start({agent,room: ctx.room,...avatar.roomOptions(),});
The avatar leaves the meeting when the avatar session closes. To remove the avatar but keep the session active, call leave_meeting (Python) or leaveMeeting (Node.js).
For meeting URL formats by platform and end-to-end examples, see Send your avatar to a Zoom call in the LemonSlice docs.
Meeting parameters
meeting_urlstringURL of the meeting to join.
bot_namestringDisplay name for the avatar in the meeting. LemonSlice assigns a name if you omit this parameter. The chat relay also uses this name to skip the avatar's own messages, and it expects LemonSlice Avatar by default. Set bot_name unless you disable listen_to_meeting_chat. In Node.js this parameter is called botName.
listen_to_meeting_chatbooleanDefault: TrueRelay meeting chat messages into the agent session as user input. Each message interrupts the agent and triggers a reply. The relay skips messages from bot_name. Set to False to ignore meeting chat. In Node.js this parameter is called listenToMeetingChat.
Additional resources
The following resources provide more information about using LemonSlice with LiveKit Agents.