RuntimeError: cannot call `SpeechHandle.wait_for_p...
# ask-ai
p
RuntimeError: cannot call
SpeechHandle.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 this
t
Thanks for reaching out, Bryner. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
The error occurs because calling
SpeechHandle.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:
Copy code
@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.py
p
# to hang up the call as part of a function call @function_tool async def end_call(ctx: RunContext): """Called when the user wants to end the call""" # let the agent finish speaking current_speech = ctx.session.current_speech if current_speech: await current_speech.wait_for_playout() await hangup_call() i simply followed what was in the docs. but i get the error.
t
Hey there! I totally get the frustration with this tricky dependency issue. It's like two processes are playing a waiting game with each other, which can cause some real headaches in your code. Good news, though! The fix is pretty straightforward. Instead of using
current_speech.wait_for_playout()
, you'll want to switch to
ctx.wait_for_playout()
. Let me show you how that looks:
Copy code
@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. 😊