Some decisions should not be made by a model. A refund above a limit. An angry caller who has asked for a person twice. A legal or medical judgement. A VIP the client wants handled personally.
A cold transfer, just forwarding the call, makes the caller start again from zero. A Warm Handover is the voice agent pattern that does what a good receptionist does. It puts the caller on hold, calls the manager and briefs them: “I have Sam on the line. Order 4471 arrived cold, she wants a full refund, and it’s her third complaint this month.” Then it connects them and steps out.
Use it when
A person has to decide, and the caller should never have to repeat themselves. Refunds above a limit, escalations, legal or medical questions, VIPs, and any call where the agent has tried twice and failed.
Agencies should treat this as a selling point, not a failure mode. “The agent hands hard calls to your manager with a briefing” is what makes a nervous business owner say yes.
Avoid it when
Nobody is available to answer. Ringing an empty desk is worse than not trying. Offer a callback instead and let the Bookends wrap-up schedule it and send the briefing by text.
Latency
Hold time while the person joins. Play hold audio, tell the caller roughly what is happening, and have a fallback after a ringing timeout.
Build it on LiveKit
LiveKit ships a prebuilt WarmTransferTask (in beta, Python). It puts the caller on hold, dials the person into a private consultation room, briefs them from the conversation history, then connects them to the caller.
import os
from livekit.agents import Agent, RunContext, function_tool
from livekit.agents.beta.workflows import WarmTransferTask
class Support(Agent):
@function_tool()
async def escalate_to_manager(self, ctx: RunContext, reason: str) -> str:
"""Bring in the on-call manager. Use for refunds over $50 or a repeated request for a person."""
result = await WarmTransferTask(
sip_call_to=os.environ["ON_CALL_NUMBER"],
sip_trunk_id=os.environ["OUTBOUND_TRUNK_ID"],
chat_ctx=self.chat_ctx,
ringing_timeout=30.0,
)
return f"Transfer finished: {result}"
If the manager does not answer, the task returns to the caller so the agent can explain and offer a callback. See LiveKit’s agent-assisted warm transfer guide for the manual workflow and options.
How it combines
Warm Handover is the exit door for every other pattern. An Observer that detects rising frustration is a good trigger. A Relay can end in one. And the Bookends wrap-up should still run afterwards, so the client’s CRM shows both halves of the call.
Common questions
What is the difference between a warm transfer and a cold transfer?
A cold transfer forwards the call and the caller starts again from zero. A warm transfer briefs the person first, so they join already knowing the story.
Can LiveKit do a warm transfer?
Yes. LiveKit ships a prebuilt WarmTransferTask (in beta, Python) that holds the caller, dials the person into a private consultation room, briefs them, then connects the call.
When should a voice agent hand off to a person?
For refunds above a limit, repeated requests for a person, legal or medical judgements, VIP callers, and any call where the agent has tried twice and failed.
Sources and further reading
Mahimai Raja
Mahimai builds production voice agents on LiveKit for small businesses and maintains the open-source livekit-starter. He is building ShipVoice, the voice AI platform for agencies. Find him on X or at [email protected].