Agents can transfer calls to human agents or other numbers when needed. Two transfer modes are supported: blind (immediate handoff) and warm (introduction before handoff).
Configuration
Add transfer settings to the agent's transfer section:
Code
{ "transfer": { "enabled": true, "mode": "warm", "destinations": [ { "id": "billing", "name": "Billing Support", "number": "+14155550001", "keywords": ["billing", "payment", "invoice", "charge"], "description": "Billing and payment questions", "timeout_seconds": 30 }, { "id": "tech_support", "name": "Technical Support", "number": "+14155550002", "keywords": ["technical", "not working", "error", "bug"], "description": "Technical issues and troubleshooting" } ], "fallback_destination": { "id": "general", "name": "General Support", "number": "+14155550099", "description": "General support queue" }, "on_fail": "return", "fail_message": "I wasn't able to transfer your call right now. Let me help you directly.", "max_retries": 2 }}
Transfer Modes
Blind Transfer
The agent immediately transfers the call without introduction. The destination rings directly.
Code
{ "transfer": { "mode": "blind" } }
Warm Transfer
The agent calls the destination first, delivers an introduction, then bridges the caller. The caller stays on hold while the agent speaks to the destination.
Code
{ "transfer": { "mode": "warm", "warm_intro_template": "Hi, I'm transferring a caller who needs help with {reason}. They said: {summary}", "warm_intro_timeout_seconds": 60, "hold_music": true }}
Template variables available in warm_intro_template:
{reason} — the detected reason for transfer
{summary} — brief summary of the conversation so far
Transfer Destinations
Each destination has:
Field
Required
Description
id
Yes
Unique identifier within this agent
name
Yes
Human-readable name
number
Yes
E.164 phone number to dial
keywords
No
Words/phrases that trigger routing to this destination
description
No
Shown to the LLM to help it choose the right destination
timeout_seconds
No
How long to ring before considering it failed (10–120s)
priority
No
Higher priority destinations are tried first
On Transfer Failure
Control what happens if the transfer fails (busy, no answer, timeout):
on_fail value
Behavior
return
Return to the AI agent conversation (default)
hangup
End the call
voicemail
Leave a voicemail message
Code
{ "transfer": { "on_fail": "return", "fail_message": "I wasn't able to reach the team right now. Let me take a message instead.", "max_retries": 2 }}
Working Hours
Restrict transfers to business hours:
Code
{ "transfer": { "destinations": [ { "id": "support", "name": "Support Team", "number": "+14155550001", "working_hours": { "enabled": true, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "17:00", "timezone": "America/New_York", "unavailable_message": "Our support team is currently unavailable. I can take a message." } } ] }}
Days are 0-indexed: 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
Example: Customer Support Routing
Code
{ "transfer": { "enabled": true, "mode": "blind", "destinations": [ { "id": "tier1", "name": "Tier 1 Support", "number": "+14155550100", "keywords": ["speak to someone", "talk to a person", "human", "agent", "representative"] }, { "id": "billing_dept", "name": "Billing Department", "number": "+14155550101", "keywords": ["billing", "charge", "payment", "refund", "invoice"] } ], "fallback_destination": { "id": "main_queue", "name": "Main Queue", "number": "+14155550000" }, "on_fail": "return", "fail_message": "Our team is busy right now. Would you like to leave a message instead?" }}