bot_ready handling).
What you’ll run
03-livekit-app-python is a complete app you can clone and run locally:
| Component | What it does |
|---|---|
Next.js app + /api/token | Browser UI and a server-side token endpoint (keeps your LiveKit secret off the client) |
agent/ worker | LiveKit Agents worker with STT, LLM, TTS via LiveKit Inference and the LemonSlice avatar plugin |


bot_ready event on the lemonslice data topic — then it transitions to the full in-call layout. This avoids the black-screen flash you get if you show video as soon as the participant joins.
Prerequisites
- A LiveKit Cloud project (
LIVEKIT_URL,LIVEKIT_API_KEY,LIVEKIT_API_SECRET) - A LemonSlice API key
- Node.js and uv
1. Clone the repo
2. Set environment variables
.env.local at the repo root (both Next.js and the agent worker read it). Replace the placeholders with your values:
.env.local
| Variable | Where to get it |
|---|---|
LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET | LiveKit Cloud project settings |
LEMONSLICE_API_KEY | LemonSlice API keys |
AGENT_NAME | Any dispatch name — default lemonslice works for local dev |
3. Install dependencies
4. Run locally
.env.local is filled in (step 2) and restart both processes.
5. Customize your avatar
Openagent/src/agent.py and change AGENT_IMAGE_URL to any publicly accessible face image. You can also swap STT, LLM, and TTS models in that file.
For every AvatarSession option (agent ID, idle timeout, events, shutdown), see LiveKit integration.
What’s already handled for you
These are the production patterns baked into the starter project — you get them for free by starting here: Secure token server. Browsers never seeLIVEKIT_API_SECRET. Your Next.js route signs a short-lived JWT; the client connects with { token, serverUrl, room }. See the repo README for the /api/token contract.
Ringing → active UI. The frontend listens for bot_ready on the lemonslice topic before showing the live avatar — not on ParticipantConnected. See Best practices for the full pattern and disconnect handling.
Agent dispatch. The worker registers under AGENT_NAME so LiveKit routes room jobs to your agent automatically.
Agent-only prototyping
If you just want to iterate on the agent without a frontend, use02-livekit-playground-demo and connect via the LiveKit Agents Playground. Come back to 03-livekit-app-python when you’re ready to ship a UI.
Next steps
LiveKit integration
Full configuration, RPC events, and graceful shutdown.
Best practices
Agent stack, latency, call lifecycle, and production hardening.

