prehistoric-printer-73777
07/31/2025, 9:41 AMtall-airline-16756
07/31/2025, 9:41 AMtall-airline-16756
07/31/2025, 9:42 AMon_user_turn_completed with a logger to verify its functionality:
import logging
from dotenv import load_dotenv
from livekit.agents import (
Agent,
AgentSession,
AutoSubscribe,
JobContext,
StopResponse,
WorkerOptions,
cli,
llm,
)
from livekit.plugins import openai, silero
load_dotenv()
logger = logging.getLogger("simple-agent")
class SimpleAgent(Agent):
def __init__(self):
super().__init__(
instructions="You are a helpful assistant.",
stt=openai.STT(),
)
async def on_user_turn_completed(self, chat_ctx: llm.ChatContext, new_message: llm.ChatMessage):
user_transcript = new_message.text_content
<http://logger.info|logger.info>(f"User said: {user_transcript}")
# Optional: Stop the agent from generating a reply
# raise StopResponse()
async def entrypoint(ctx: JobContext):
<http://logger.info|logger.info>(f"Starting agent in room: {ctx.room.name}")
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
session = AgentSession(
vad=silero.VAD.load(min_silence_duration=0.3),
)
await session.start(
agent=SimpleAgent(),
room=ctx.room,
)
if __name__ == "__main__":
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
This example demonstrates:
• Setting up a logger to log user input.
• Implementing the on_user_turn_completed method to log the user’s transcript using new_message.text_content.
• Optionally raising StopResponse() to prevent the agent from generating a reply.
The method is triggered when the user’s turn ends, making it ideal for logging, validation, or modifying the chat context.
Sources: tests/test_agent_session.py | Voice pipeline nodes | LiveKit Docsprehistoric-printer-73777
07/31/2025, 9:45 AMtall-airline-16756
07/31/2025, 9:46 AMStopResponse in on_user_turn_completed works smoothly with VoicePipelineAgent in LiveKit agent versions >=0.12.17<0.13.0. It’s a supported and documented way to handle things.
When you raise StopResponse, the agent simply skips the current turn and doesn’t generate a reply. Here’s a quick example to show you how it works:
async def on_user_turn_completed(self, turn_ctx: ChatContext, new_message: ChatMessage):
if not new_message.text_content:
# Raise StopResponse to stop the agent from generating a reply
raise StopResponse()
This feature is super handy if you want to add conditional response logic, like push-to-talk setups or filtering out inputs you don’t want. If you’d like, I’m happy to help you tailor this for your specific setup—just let me know!
Sources: livekit-agents/livekit/agents/voice/agent_activity.py | Voice pipeline nodes | LiveKit Docsprehistoric-printer-73777
07/31/2025, 9:47 AMtall-airline-16756
07/31/2025, 9:48 AMStopResponse into your on_user_turn_completed function, you can simply add this import statement:
from livekit.agents import StopResponse
That’s the usual way to do it. Once you've got it imported, you can use StopResponse to stop the agent from replying. Here’s a quick example:
async def on_user_turn_completed(self, turn_ctx: ChatContext, new_message: ChatMessage):
if not new_message.text_content:
# Raise StopResponse to stop the agent from generating a reply
raise StopResponse()
If you have any questions or want me to walk you through it, just let me know—I’m here to help!
Sources: livekit-agents/livekit/agents/voice/agent_activity.py | home_assistant/homeautomation.py | Voice pipeline nodes | LiveKit Docsprehistoric-printer-73777
07/31/2025, 10:03 AMtall-airline-16756
07/31/2025, 10:04 AMon_user_turn_completed method doesn’t need a decorator to be triggered when the user finishes talking. It’s a lifecycle hook you override in your custom Agent subclass, and the LiveKit framework takes care of calling it automatically right after the user’s turn ends, just before the agent crafts a reply.
Here’s a quick example of how you can implement it:
async def on_user_turn_completed(self, turn_ctx: llm.ChatContext, new_message: llm.ChatMessage):
"""Called when the user has finished speaking, and the LLM is about to respond."""
# Your custom logic here
pass
If you’re not seeing this method get called, here are a few things to double-check:
• Make sure you’ve properly overridden the method in your custom agent class.
• Confirm that your agent is correctly hooked into the session or pipeline (like AgentSession or VoicePipelineAgent).
• Verify that the framework is detecting when the user’s turn ends (for example, using VAD or other ways).
If you’d like, I’m here to help you troubleshoot further—just let me know!
Sources: Voice pipeline nodes | LiveKit Docs | examples/voice_agents/preemptive_generation.pyprehistoric-printer-73777
07/31/2025, 10:36 AMtall-airline-16756
07/31/2025, 10:37 AM