Skip to main content
This cookbook walks you through building Nexus, a Level 1 IT support voice agent, end to end: pick the models, save the agent, run a live session in a browser, and fetch transcripts.

What you’ll build

Nexus greets the caller, asks whether they’re on Mac or Windows, and walks them through Level 1 troubleshooting steps. By the end of this guide you’ll have:
  • a saved agent on the Lyzr Voice API (reusable across sessions),
  • a Python script that starts and ends sessions,
  • a React component that connects a browser microphone to a live session,
  • a script that pulls the transcript and latency metrics for any past call.

Prerequisites

  • A Lyzr API key. Set it as LYZR_API_KEY for the Python scripts.
  • Python with requests (pip install requests).
  • For the browser section: a React app that can install npm/pnpm packages.

1. Pick your models and a voice

Pipeline mode runs three separate models — STT, LLM, TTS — plus a TTS voice. Before creating the agent, ask the API which options are available so you can pick concrete values for each.
You should see something like:
Hold onto the voice ID — you’ll pass it as engine.voice_id in the next step.
This script takes the happy path: the first configured provider, the first model in each list, the first voice. In production code, handle empty results explicitly and let users pick a voice rather than auto-selecting one.

2. Create the Nexus agent

POST /agents saves an agent definition so you don’t have to send the whole config on every session. The response includes agent.id — store it; the rest of this cookbook references it.
Export the printed ID so the next scripts can pick it up:
Only agent_name, prompt, and engine are strictly required. Everything below the second comment in the payload is polish — drop it for a stripped-down agent and add it back as you need it.

3. Start and end a session

Starting a session dispatches the Python worker, creates a LiveKit room, and returns the credentials your client needs to join. Request to POST /sessions/start:
Response:
You’ll feed livekitUrl and userToken into the LiveKit client in the next step. When the call is done, call POST /sessions/end with either roomName or sessionId. The Python script below handles only the lifecycle — it doesn’t publish a microphone or play audio. On its own it just opens an empty room and waits. You’ll connect a real microphone in step 4.
POST /sessions/end returns immediately and marks the session as ended on the API side. The transcript becomes available once the worker flushes its buffers and observability data arrives — typically a few seconds after the LiveKit room closes.

4. Connect from the browser

The REST API has done its job; from here, all the audio plumbing belongs to the LiveKit SDK. We’ll build two files:
  • voice-api.ts — a thin wrapper around /v1/sessions/start and /v1/sessions/end.
  • NexusVoiceWidget.tsx — a React component that joins the room and renders the agent’s audio.
Install the client packages:

voice-api.ts

NexusVoiceWidget.tsx

The widget renders two audio sinks inside <LiveKitRoom>:
  • RoomAudioRenderer — plays the agent’s voice. This is the one you actually hear Nexus through.
  • BackgroundAudioRenderer — a small custom renderer that attaches the optional background_audio track (office ambience, keyboard sounds during tool calls). It’s separate because the default renderer doesn’t surface non-voice tracks.
Render <NexusVoiceWidget apiKey={...} agentId={...} /> somewhere in your app, click Start call, grant microphone permission, and you should hear Nexus’s greeting within a second or two.
In a real app, never pass apiKey straight to the browser. Proxy /v1/sessions/start through your own backend so the key stays on the server.

5. Read transcripts and metrics

Once a call has ended and the worker has flushed, you can pull aggregate stats for the agent and a per-session transcript with latency metrics on each turn.
llm_node_ttft is the time from the user finishing their turn to the first LLM token; tts_node_ttfb is the time from that first token to the first byte of synthesized audio. Together they’re the dominant contributors to perceived latency.

Where to go next

  • Swap engine.kind from "pipeline" to "realtime" to use a single multimodal model instead of three.
  • Add tools to the agent payload so Nexus can look up tickets, reset passwords, or hand off to a human.
  • Stream transcripts in realtime by subscribing to LiveKit data tracks instead of polling /transcripts/{sessionId} afterward.