busy-spoon-35253
03/05/2026, 9:58 AMtall-airline-16756
03/05/2026, 9:58 AMtall-airline-16756
03/05/2026, 9:58 AM@session.on("conversation_item_added")
async def on_conversation_item(item: ChatItem):
if item.role != "assistant":
return
text = item.text_content()
options = detect_question_type(text) # your heuristic/classifier
if not options:
return
await ctx.room.local_participant.rpc.invoke(
method="agent.displayUI",
data={"type": "options", "options": options}
)
detect_question_type suggestions
• yes/no: if text contains phrases like "yes or no", leading question verbs, or ends with a yes/no prompt → return ["Yes","No"]
• year/date: detect tokens like "what year", "when", or pattern matching for numbers → return plausible years/options
• condition/choices: parse enumerations or known catalog keys when present
Notes on tool_choice and avoiding loops
• Setting tool_choice="required" leads to tool loops or suppressed speech as you observed. With the server-side event approach, you can:
◦ Keep show_options as an optional tool (for when the model intentionally wants to call it).
◦ Rely on conversation_item_added for deterministic chip pushes.
◦ Optionally remove or temporarily hide the show_options tool in the agent’s toolset if you want to fully prevent the model from calling it.
Other hooks (when you might use them)
• Speech playback callbacks (e.g., SpeechHandle callbacks) exist if you need to run something strictly after audio playout finishes (visual feedback tied to TTS end). But for getting the final text and pushing UI, conversation_item_added is simpler and more reliable.
Examples & references (useful)
• conversation_item_added is part of the AgentSession lifecycle and is the right post-generation hook for this use case.
• You can combine this with small server-side state (a short state machine) to ensure the correct chip set for multi-step flows.
If you’d like, I can:
• Provide a complete working agent template (full file) with a robust detect_question_type implementation.
• Show a version that also waits for TTS end before showing chips, if you need chips to appear exactly after audio completes.
Which would you like next: the full template, or a focused detect_question_type implementation tuned to your catalog + dynamic questions?
Sources: Agent session | LiveKit Documentation | Turns overview | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentationbusy-spoon-35253
03/05/2026, 10:03 AMtall-airline-16756
03/05/2026, 10:04 AM