I am running a virtual AI assistant that qualifies...
# ask-ai
r
I am running a virtual AI assistant that qualifies callers for a program. If the caller qualifies, the system transfers the call to a human agent. While using LiveKit for the call transfer, I want to play a short message to the caller before the transfer happens (for example: “Please hold while I connect you to an agent”). However, when the transfer is triggered, the message gets cut off and the call connects to the human agent immediately. What is the correct way in LiveKit to ensure that the message finishes playing completely before the call transfer is executed?
t
Thanks for reaching out, Saurabh. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about ensuring a short hold message plays fully before transferring the caller to a human agent. Short answer • Play the message with
session.say()
or
session.generate_reply()
and then await the returned SpeechHandle’s playout completion (use
wait_for_playout()
/
waitForPlayout()
) before calling the SIP transfer. That guarantees the audio finishes before the call is connected to the agent. Why this works •
session.say()
/
session.generate_reply()
return a SpeechHandle. Calling
await handle.wait_for_playout()
ensures the spoken audio is delivered completely to the participant. If you don’t await it, the transfer will run immediately and cut off playback. Examples 1) Python
Copy code
handle = session.generate_reply(instructions="Please hold while I connect you to an agent.")
await handle.wait_for_playout()  # wait until playback finishes

await job_ctx.api.sip.transfer_sip_participant(
    api.TransferSIPParticipantRequest(
        room_name=job_ctx.room.name,
        participant_identity=caller_identity,
        transfer_to=f"tel:{human_agent_number}",
    )
)
2) Node.js / TypeScript
Copy code
const handle = session.generateReply({ instructions: 'Please hold while I connect you to an agent.' });

await handle.waitForPlayout(); // wait until playback finishes

await jobCtx.room.sipTransferParticipant({ transferTo: `tel:${humanAgentNumber}` });
Additional notes • You do not need to change interruption settings just to ensure playout completes — sequencing the play + await + transfer is sufficient. • If you want to support cancelling the transfer while the message plays (e.g., agent becomes available earlier), you can keep a reference to the SpeechHandle and cancel or check its state before transfer. If you’d like, tell me which SDK (Python, Node, or another) and I can provide a copy-paste-ready snippet integrated into your transfer flow. Sources: Agent speech and audio | LiveKit Documentation | How to detect when an agent has finished speaking | LiveKit