quick-cartoon-22764
02/17/2026, 8:23 PM@function_tool()
async def end_call(self, ctx: RunContext):
"""Called when the agents has collected all information and is ready to end the call."""
<http://log.info|log.info>(f"[{self.agent_name}][correlation_id: {self.room_name}]: Ending the call")
# await ctx.speech_handle.wait_for_playout()
await self.session.say(text=f"Thanks for checking that for me. Really appreciate your time today. Bye!!")
await ctx.wait_for_playout()
await self.hangup()
Can I have wait for playout after session.say?tall-airline-16756
02/17/2026, 8:24 PMtall-airline-16756
02/17/2026, 8:24 PMctx.wait_for_playout() after session.say() in your end_call tool. Yes — that is appropriate and the right pattern to ensure the farewell is fully played before hanging up.
Why this works
• session.say() initiates speaking and returns a SpeechHandle for that utterance.
• Calling ctx.wait_for_playout() immediately after will wait until the current/last speech audio finishes playout to the participant.
• That guarantees the user hears the full goodbye before await self.hangup() runs.
Optional alternative
• You can also capture the handle explicitly and wait on it:
handle = await self.session.say(text="Thanks for checking that for me. Really appreciate your time today. Bye!!")
await handle.wait_for_playout()
await self.hangup()
This makes it explicit which speech you’re waiting for (useful if multiple speech ops could overlap).
Both approaches are valid; use the explicit handle if you want stricter control.
Sources: Agent speech and audio | LiveKit Documentation