Skip to main content
IntroductionBuild AgentsAgent FrontendsTelephonyWebRTC TransportManage & DeployReferences

Repeater

Shows how to create an agent that can repeat what the user says.

This example shows how to build a simple repeater: when the user finishes speaking, the agent says back exactly what it heard by listening to the user_input_transcribed event.

Prerequisites

  • Add a .env.local in this directory with your LiveKit credentials:
    LIVEKIT_URL=your_livekit_url
    LIVEKIT_API_KEY=your_api_key
    LIVEKIT_API_SECRET=your_api_secret
  • Install dependencies:
    pip install "livekit-agents" python-dotenv

Load environment and define an AgentServer

Load your .env.local so the media plugins can authenticate and initialize the AgentServer.

from dotenv import load_dotenv
from livekit.agents import JobContext, AgentServer, cli, Agent, AgentSession, inference
load_dotenv(".env.local")
server = AgentServer()

Define the rtc session with transcript handler

Create the session with interruptions disabled so playback is not cut off mid-echo. Attach a handler to user_input_transcribed; once a transcript is marked final, echo it back with session.say.

@server.rtc_session(agent_name="my-agent")
async def entrypoint(ctx: JobContext):
ctx.log_context_fields = {"room": ctx.room.name}
session = AgentSession(
stt=inference.STT(model="deepgram/nova-3-general"),
llm=inference.LLM(model="google/gemma-4-31b-it"),
tts=inference.TTS(model="inworld/inworld-tts-2", voice="Ashley"),
allow_interruptions=False,
)
@session.on("user_input_transcribed")
def on_transcript(transcript):
if transcript.is_final:
session.say(transcript.transcript)
await session.start(
agent=Agent(
instructions="You are a helpful assistant that repeats what the user says."
),
room=ctx.room
)
await ctx.connect()

Run the server

Start the agent server with the CLI runner.

if __name__ == "__main__":
cli.run_app(server)

Run it

lk agent console repeater.py

How it works

  1. A session-level event emits transcripts as the user speaks.
  2. When the transcript is final, the handler calls session.say with the same text.
  3. Because interruptions are disabled, the echoed audio plays fully.
  4. This pattern is a starting point for building more advanced post-processing on transcripts.

Full example

from dotenv import load_dotenv
from livekit.agents import JobContext, AgentServer, cli, Agent, AgentSession, inference
load_dotenv(".env.local")
server = AgentServer()
@server.rtc_session(agent_name="my-agent")
async def entrypoint(ctx: JobContext):
ctx.log_context_fields = {"room": ctx.room.name}
session = AgentSession(
stt=inference.STT(model="deepgram/nova-3-general"),
llm=inference.LLM(model="google/gemma-4-31b-it"),
tts=inference.TTS(model="inworld/inworld-tts-2", voice="Ashley"),
allow_interruptions=False,
)
@session.on("user_input_transcribed")
def on_transcript(transcript):
if transcript.is_final:
session.say(transcript.transcript)
await session.start(
agent=Agent(
instructions="You are a helpful assistant that repeats what the user says."
),
room=ctx.room
)
await ctx.connect()
if __name__ == "__main__":
cli.run_app(server)