polite-furniture-24847
07/29/2025, 5:28 AMSpeechHandle.wait_for_playout() from inside the function tool end_call that owns this SpeechHandle. This creates a circular wait: the speech handle is waiting for the function tool to complete, while the function tool is simultaneously waiting for the speech handle.
To wait for the assistant’s spoken response prior to running this tool, use RunContext.wait_for_playout() instead. {"function": "end_call", "speech_id": "speech_700057705f11", "pid": 201, "job_id": "AJ_JHUga9enfkTA"}
how toimplement thistall-airline-16756
07/29/2025, 5:28 AMtall-airline-16756
07/29/2025, 5:29 AMSpeechHandle.wait_for_playout() from within a function tool creates a circular dependency. The speech handle is waiting for the function tool to complete, while the function tool is simultaneously waiting for the speech handle.
To fix this, use RunContext.wait_for_playout() instead. Here's how to implement it:
@function_tool
async def end_call(ctx: RunContext):
"""Use this tool when the user has signaled they wish to end the current call."""
# Wait for the assistant's spoken response prior to running this tool
await ctx.wait_for_playout()
# Now proceed with ending the call
# call API to delete_room
...
The key difference between these two methods is:
• SpeechHandle.wait_for_playout() waits for the entire assistant turn to complete (including all function tools).
• RunContext.wait_for_playout() waits only for the assistant's spoken response prior to running this tool to finish playing.
The RunContext.wait_for_playout() method specifically addresses this use case by waiting for the speech playout corresponding to the current function call step, avoiding the circular dependency issue.
Sources: livekit-agents/livekit/agents/voice/background_audio.pypolite-furniture-24847
07/29/2025, 5:37 AMtall-airline-16756
07/29/2025, 5:37 AMcurrent_speech.wait_for_playout(), you'll want to switch to ctx.wait_for_playout(). Let me show you how that looks:
@function_tool
async def end_call(ctx: RunContext):
"""Called when the user wants to end the call"""
# Wait for the assistant's spoken response prior to running this tool
await ctx.wait_for_playout()
# Now proceed with ending the call
await hangup_call()
By making this small change, you're basically telling the function tool to just chill and wait for the assistant's response to finish playing. No more circular dependency drama! Hope this helps make your code run smoother. 😊