Give me example of WarmTransferTask please
# ask-ai
t
Give me example of WarmTransferTask please
✅ 1
t
Thanks for reaching out, Aivis. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’ll show you an example of
WarmTransferTask
and a brief explanation of how it works. Example (Python, Beta):
Copy code
from livekit.agents import Agent, function_tool, RunContext
from livekit.agents.beta.workflows import WarmTransferTask

SUPERVISOR_PHONE = "+15551234567"
SIP_TRUNK_ID = "your-sip-trunk-id"

class SupportAgent(Agent):
    @function_tool()
    async def escalate_to_human(self, context: RunContext):
        await self.session.say(
            "I'm connecting you with a specialist now. I'll share our conversation so you won't need to repeat anything.",
            allow_interruptions=False,
        )
        await context.wait_for_playout()

        result = await WarmTransferTask(
            sip_call_to=SUPERVISOR_PHONE,
            sip_trunk_id=SIP_TRUNK_ID,
            chat_ctx=self.chat_ctx,
        )

        # WarmTransferResult contains the human agent identity
        return result
What this does (brief): • Plays a message, then waits for playout to finish. • Places caller on hold (default hold music) and creates a private consultation room. • Dials the supervisor via SIP using
sip_call_to
and
sip_trunk_id
. • Passes
chat_ctx
so the human receives conversation context. • Moves the supervisor into the caller's room and disconnects the agents, returning a
WarmTransferResult
with
human_agent_identity
. If you want, I can: • Show how to pass custom
hold_audio
or
extra_instructions
. • Convert this to another language or integrate with your SIP setup — which would you prefer? Sources: WarmTransferTask | LiveKit Documentation | The Handoff Pattern for Voice Agents That Replaces IVR Menus | LiveKit, with interactive elements
t
this works, however MoH continues to play even after both parties are connected. It should not play
t
Thanks — I’m responding to your note that MoH continues after both parties are connected. Quick checklist to narrow this down (please tell me which apply): • Are you using the default
hold_audio
(BuiltinAudioClip.HOLD_MUSIC) or a custom audio file/stream? • Which SDK/version of LiveKit Agents are you running? • Does the issue reproduce with the stock warm-transfer example (no custom audio logic)? • Are there any custom room/participant hooks or middleware that might keep audio playing after transfer? Immediate suggestions you can try now: 1. If you use custom
hold_audio
, swap to the default
BuiltinAudioClip.HOLD_MUSIC
and retest to see if the MoH stops when connected. 2. Ensure your custom audio is finite (not an infinite loop/stream) and that playback is closed when
WarmTransferTask
completes. 3. Test with the latest LiveKit Agents release — media lifecycle fixes are included in recent updates. 4. Reproduce using the official warm-transfer example; if it stops there but not in your app, check for middleware or extra audio sources injecting MoH. If you share which of the checklist items apply (especially whether you’re using custom hold audio and your Agents SDK version), I’ll give the next targeted steps. Sources: WarmTransferTask | LiveKit Documentation | The Handoff Pattern for Voice Agents That Replaces IVR Menus | LiveKit | Background audio | LiveKit Documentation, with interactive elements
t
i am not passing
hold_audio
argument at all. Agents version is 1.5.0
t
Thanks — I’m responding to your note that you’re not passing
hold_audio
and are on Agents v1.5.0. Try these targeted steps: 1. Explicitly disable default MoH by calling WarmTransferTask with `hold_audio=None`:
Copy code
result = await WarmTransferTask(
    sip_call_to=SUPERVISOR_PHONE,
    sip_trunk_id=SIP_TRUNK_ID,
    chat_ctx=self.chat_ctx,
    hold_audio=None,
)
1. After the transfer completes, ensure agent sessions are closing so no audio sources remain: ◦ Listen for the agent session
close
event or confirm
WarmTransferResult
returned before assuming cleanup. 1. If disabling MoH fixes it, you can implement manual hold playback that you stop explicitly when the supervisor is joined. 2. If MoH still persists with
hold_audio=None
, please tell me: ◦ A short call flow log (timestamps of hold start, SIP answered, transfer completion) or ◦ Whether you see any lingering published audio tracks for the agent or hold source in the room. I’ll use that info to provide next troubleshooting steps. Sources: WarmTransferTask | LiveKit Documentation | Agent session | LiveKit Documentation, with interactive elements
t
this solves the problem since there is no hold music. how to implement manual hold playback that you stop explicitly when the supervisor is joined? also how to inform caller that you are now connected to a human agent?
t
Good — glad disabling default MoH fixed it. Below is a concise pattern you can follow to (1) play hold music yourself, (2) stop it when the supervisor joins, and (3) inform the caller that they’re connected. Example pattern (Python, within your Agent method):
Copy code
from livekit.agents import Agent, function_tool, RunContext
from livekit.agents.beta.workflows import WarmTransferTask
from livekit.audio import BuiltinAudioClip  # adjust import to your SDK layout

SUPERVISOR_PHONE = "+15551234567"
SIP_TRUNK_ID = "your-sip-trunk-id"

class SupportAgent(Agent):
    @function_tool()
    async def escalate_to_human(self, context: RunContext):
        # 1) Start manual hold playback to the caller
        # publish_hold returns a handle/track id in many SDKs; adjust to your API
        hold_handle = await self.session.publish_audio(BuiltinAudioClip.HOLD_MUSIC)

        # 2) Tell caller you're placing them on hold, wait for playout to finish
        await self.session.say(
            "I'm connecting you with a specialist now. Please hold for a moment.",
            allow_interruptions=False,
        )
        await context.wait_for_playout()

        # 3) Start the warm transfer but disable built-in MoH
        result = await WarmTransferTask(
            sip_call_to=SUPERVISOR_PHONE,
            sip_trunk_id=SIP_TRUNK_ID,
            chat_ctx=self.chat_ctx,
            hold_audio=None,  # we handle hold manually
        )

        # 4) Stop manual hold when supervisor is connected.
        # WarmTransferResult indicates transfer completion; stop hold after result
        await self.session.unpublish_audio(hold_handle)

        # 5) Inform caller that the human is now connected
        # Use session.say (non-interrupting) or a brief TTS
        await self.session.say(
            "You are now connected to a specialist. They will help you from here.",
            allow_interruptions=True,
        )

        return result
Key notes and alternatives: • Publish/unpublish API: Replace `publish_audio`/`unpublish_audio` and
hold_handle
with the exact methods your Agents SDK exposes for publishing and removing an audio source or track. The pattern is: publish an audio source/track for hold, keep its handle, then remove that handle when transfer completes. • Stop timing: Stop/unpublish the hold immediately after
WarmTransferTask
returns a successful
WarmTransferResult
(that indicates the supervisor was joined), or listen for any explicit event that indicates the human was moved into the caller’s room. • Informing the caller: Use
session.say
(TTS) right after stopping hold audio. Keep the message short and allow interruptions if the human may speak right away (
allow_interruptions=True
). • If you need seamless handoff (no overlapping audio): unpublish hold audio first, then
session.say
immediately before/handover so the caller hears the single confirmation message and the human joins without overlap. If you tell me the exact publish/unpublish method names your Agents SDK exposes, I’ll convert the placeholders into the precise calls for your version. , with interactive elements