Skip to main content

Warm Transfers

A warm transfer connects a caller to a human agent while providing context about the conversation. Unlike cold transfers, the receiving agent knows who’s calling and why before the connection is made.

How Warm Transfers Work

1. AI Agent decides to transfer

2. Caller placed on hold with music/message

3. AI dials destination number

4. AI briefs receiving agent

5. Receiving agent accepts/declines

6. All parties connected (or caller returned to AI)

Configuring Warm Transfers

Basic Configuration

{
  "transfer": {
    "type": "warm",
    "destination": "+14155551234",
    "brief_template": "Incoming call from {{caller.name}} regarding {{intent}}. They've been on the line for {{call_duration}}.",
    "hold_music": "default",
    "timeout": 30
  }
}

Brief Templates

Customize what the AI tells the receiving agent:
{
  "brief_template": "Hi, I have {{caller.name}} on the line. They're calling about {{intent}}. Key details: {{conversation.summary}}. Ready to connect?"
}

Available Variables

VariableDescription
{{caller.name}}Caller’s name if known
{{caller.phone}}Caller’s phone number
{{intent}}Detected call intent
{{conversation.summary}}AI-generated summary
{{call_duration}}Time caller has been on
{{data.field_name}}Any collected data

Hold Experience

Configure what callers hear while waiting:
{
  "hold": {
    "type": "music",
    "source": "default",
    "message_interval": 30,
    "message": "Thank you for holding. A team member will be with you shortly."
  }
}

Hold Options

TypeDescription
musicPlay hold music
messagePlay custom message
silenceMuted hold
ringbackStandard ringing sound

Transfer Flow Options

Accept/Decline

The receiving agent can accept or decline:
{
  "transfer": {
    "accept_key": "1",
    "decline_key": "2",
    "prompt": "Press 1 to accept this call, or 2 to send to voicemail."
  }
}

Auto-Connect

Connect immediately without confirmation:
{
  "transfer": {
    "auto_connect": true,
    "whisper": "Incoming transfer regarding {{intent}}"
  }
}

Voicemail Fallback

If the transfer is declined or times out:
{
  "fallback": {
    "action": "voicemail",
    "message": "I wasn't able to reach someone directly. Please leave a message and we'll call you back."
  }
}

Multi-Destination Transfers

Sequential Dialing

Try destinations in order:
{
  "transfer": {
    "type": "warm",
    "destinations": [
      {
        "number": "+14155551111",
        "timeout": 20
      },
      {
        "number": "+14155552222",
        "timeout": 20
      },
      {
        "number": "+14155553333",
        "timeout": 20
      }
    ],
    "fallback": {
      "action": "voicemail"
    }
  }
}

Simultaneous Ring

Ring multiple destinations at once:
{
  "transfer": {
    "type": "warm",
    "strategy": "simultaneous",
    "destinations": [
      "+14155551111",
      "+14155552222"
    ],
    "first_responder_wins": true
  }
}

Skill-Based Routing

Route based on agent skills:
{
  "transfer": {
    "type": "warm",
    "routing": {
      "skill": "billing",
      "priority": "high"
    }
  }
}

Skill Groups

Define skill groups for routing:
{
  "skill_groups": {
    "billing": {
      "agents": [
        { "number": "+14155551111", "priority": 1 },
        { "number": "+14155552222", "priority": 2 }
      ]
    },
    "technical": {
      "agents": [
        { "number": "+14155553333", "priority": 1 }
      ]
    }
  }
}

Screen Pop Integration

Send caller information to the receiving agent’s screen:
{
  "transfer": {
    "screen_pop": {
      "enabled": true,
      "url": "https://crm.yourcompany.com/call?caller={{caller.phone}}&account={{caller.account_id}}",
      "data": {
        "caller_name": "{{caller.name}}",
        "intent": "{{intent}}",
        "summary": "{{conversation.summary}}",
        "collected_data": "{{data}}"
      }
    }
  }
}

Transfer Events

Monitor transfer status via webhooks:
EventDescription
transfer.initiatedTransfer started
transfer.ringingDestination ringing
transfer.answeredRecipient answered
transfer.briefedBrief delivered
transfer.acceptedTransfer accepted
transfer.declinedTransfer declined
transfer.completedParties connected
transfer.failedTransfer failed

Event Payload

{
  "event": "transfer.completed",
  "call_id": "call_abc123",
  "transfer_id": "transfer_xyz789",
  "destination": "+14155551234",
  "duration_to_connect": 12.5,
  "brief_delivered": true,
  "context": {
    "caller_name": "John Smith",
    "intent": "billing_question"
  }
}

Best Practices

Receiving agents are busy. Aim for 10-15 seconds of context, not a full recap.
30 seconds is typical. Too short and agents can’t answer; too long and callers abandon.
If no one answers, route to voicemail or offer a callback.
If auto-connecting, a whisper gives agents heads-up without delay.
High decline rates indicate staffing or routing issues.

Troubleshooting

Transfers failing

  1. Verify destination number is correct
  2. Check if receiving agents are available
  3. Ensure timeout isn’t too short
  4. Verify telephony connection is working

Callers abandoning during hold

  1. Reduce timeout duration
  2. Improve hold music/messaging
  3. Add position-in-queue announcements
  4. Consider callback option

Context not appearing

  1. Verify brief template syntax
  2. Check if variables are being collected
  3. Test screen pop URL separately
  4. Review webhook deliverability

Next Steps