Skip to content

transfer_call

The transfer_call tool lets agents redirect a live phone call to another number after announcing the transfer. The system uses mark-based coordination to ensure the caller hears the full transfer announcement before the redirect executes.

This tool is conditionally available. It registers only when the agent has at least one configured transfer number with a valid E.164 phone number. If transfer_call is enabled but no numbers are configured, the tool is not registered and the AI model cannot use it.

AgentToolConfig validates transfer numbers via validation_error(). The UI enforces this:

  • Enabling transfer_call auto-adds an empty number row
  • Removing the last number auto-disables transfer_call
  • The Save button stays disabled until at least one valid number exists

The phone_number parameter uses a JSON Schema enum to restrict values to the configured transfer numbers. The AI model can only transfer to pre-approved destinations.

{
"name": "transfer_call",
"description": "Transfer the current call to another phone number.",
"parameters": {
"type": "object",
"properties": {
"phone_number": {
"type": "string",
"description": "The phone number to transfer to",
"enum": ["+12125551234", "+12125559876"]
}
},
"required": ["phone_number"]
}
}

The enum values are populated from TransferCallSettings.numbers at session start.

Model calls transfer_call({ phone_number: "+15551234567" })
→ Send "transfer_call" mark to Twilio after buffered announcement audio
→ Return "Transfer initiated" response to AI so it doesn't stall
→ Twilio plays all buffered audio, then echoes mark back
→ On mark echo: call Twilio REST API to redirect the call
→ Safety net: if mark echo never arrives, force-redirect after 15 seconds

Before PR #183, transfer_call triggered the redirect immediately, cutting off the agent’s transfer announcement mid-sentence. The fix applies the same mark-based pattern used by end_call:

  1. Send mark — insert a "transfer_call" mark into the Twilio audio stream after the agent’s announcement
  2. Return tool response — send “Transfer initiated” back to the AI model so conversation flow continues
  3. Background task — spawn an async task that waits for the mark echo (audio finished playing) or a 15-second timeout
  4. Execute redirect — once the mark returns, call Twilio’s REST API to redirect the call
POST https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Calls/{CallSid}.json
Authorization: Basic {base64(AccountSid:AuthToken)}
Content-Type: application/x-www-form-urlencoded
Twiml=<Response><Dial callerId="{caller_number}">{target_number}</Dial></Response>

The TwiML <Dial> verb redirects the call to the target number while preserving the caller ID.

The tool builder returns a behavioral prompt section appended to the agent’s system instructions. This tells the AI model how to use the tool:

### Call Transfer (CONFIRMATION_FIRST)
- You can transfer calls to these destinations:
- +12125551234 — Sales
- +12125559876 — Support
- ONLY transfer to these numbers.
- ALWAYS confirm with the caller before transferring.
- Before calling the tool, say something like "I'll transfer you now."
- This is a cold transfer — the conversation ends immediately.

The destination list is dynamically generated from TransferCallSettings.numbers, including each number’s label. The mark system ensures the announcement completes before the redirect executes.

FilePurpose
build_transfer_call_tool_definition_service.rsReturns Option<(AgentToolDefinition, String)> — definition + prompt section
handle_transfer_call_tool_call_service.rsCalls Twilio REST API with TwiML redirect
collect_agent_tools_service.rsRegisters transfer_call for agents with configured destinations
twilio_stream_route.rsMark-based coordination logic (lines 338-411)
agent_tool_config_type.rsAgentToolConfig with validation_error() for number requirement
transfer_call_settings_type.rsTransferCallSettings and TransferNumber types
tool_config_form_component.rsUI checkboxes, auto-add/remove logic for transfer numbers
  • Missing or invalid phone_number parameter → returns “Error: missing ‘phone_number’ argument” to AI
  • Missing Twilio credentials → AppError::InvalidInput
  • Twilio API request fails → AppError::Internal with error details