flat-accountant-15519
12/23/2025, 6:30 AMtall-airline-16756
12/23/2025, 6:30 AMtall-airline-16756
12/23/2025, 6:31 AMchat_ctx for realtime models and which hooks to use since on_user_turn_completed isn't available. Short answer: yes — you can, but use different events.
What to use
• Use on_input_speech_transcribed (recommended). It fires after the realtime model produces a transcription and is the closest equivalent to on_user_turn_completed. Inject system messages there and call await self.update_chat_ctx(chat_ctx).
• Inject at session start with on_enter() for static context (e.g., user tier, persona).
• You can also modify chat_ctx anytime before calling generate_reply() by copying, adding messages, then update_chat_ctx().
Why on_user_turn_completed isn't available
• on_user_turn_completed requires client-side turn detection. Realtime models with server-side turn detection do not fire that hook, so use the transcription event instead.
Small example (Python-style)
async def on_input_speech_transcribed(self, transcription, event_ctx):
ctx = self.chat_ctx.copy()
ctx.add_message(role="system", content=f"[Note: user said: {transcription}]")
await self.update_chat_ctx(ctx)
If you need, I can:
• Provide a full example that includes RAG/DB lookup before injecting,
• Show how to disable server-side turn detection to restore on_user_turn_completed. Which would you prefer? Sources: Turns overview | LiveKit docs | OpenAI Realtime API plugin guide | LiveKit docs | Pipeline nodes and hooks | LiveKit docs | Agents and handoffs | LiveKit docs | Agents (Node.js) | livekit/livekit_composite | DeepWikiflat-accountant-15519
12/23/2025, 6:32 AMtall-airline-16756
12/23/2025, 6:33 AMuser_input_transcribed / on_input_speech_transcribed) and update the chat context.
Python example (AgentSession, final transcript):
from livekit.agents import AgentSession, ChatMessage
from livekit.plugins import google
async def entrypoint(ctx):
session = AgentSession(
llm=google.realtime.RealtimeModel(
model="gemini-2.5-flash-native-audio-preview-09-2025",
voice="Puck",
instructions="You are a helpful assistant."
),
)
@session.on("user_input_transcribed")
async def on_user_transcribed(event):
if event.is_final:
system_msg = ChatMessage(role="system",
content=f"[Note: user said: '{event.transcript}']")
session.chat_ctx.add_message(system_msg)
await session.update_chat_ctx(session.chat_ctx)
await session.start(room=ctx.room)
await ctx.connect()
Node.js/TypeScript example:
import { AgentSession } from "livekit-agents";
import * as google from "@livekit/agents-plugin-google";
const session = new AgentSession({
llm: new google.realtime.RealtimeModel({
model: "gemini-2.5-flash-native-audio-preview-09-2025",
voice: "Puck",
instructions: "You are a helpful assistant."
}),
});
session.on("user_input_transcribed", async (event) => {
if (event.is_final) {
session.chat_ctx.addMessage({
role: "system",
content: `[Note: user said: '${event.transcript}']`
});
await session.update_chat_ctx(session.chat_ctx);
}
});
If you want, I can:
• Provide a full RAG example that fetches data on transcription and injects it, or
• Show how to disable server-side turn detection if you prefer client-side on_user_turn_completed. Which do you want? Sources: Gemini Live API plugin | LiveKit docs | TTS Translator with Gladia STT | LiveKit docs | Google Gemini LLM plugin guide | LiveKit docsflat-accountant-15519
12/23/2025, 6:33 AMtall-airline-16756
12/23/2025, 6:34 AM