Transfer Call Options
Route callers to human agents or other numbers — blind or attended, sequential or simultaneous, with dynamic resolution and failure handling.
Overview
VoiceElements supports transferring a caller to a human agent or another number, controlled by the AI. Transfers can be blind (caller is immediately bridged) or attended (the AI announces the caller to the recipient first). Numbers can be dialed sequentially (one at a time, move to next on no answer) or simultaneously (all at once, first to answer wins).
Transfers are initiated when the AI calls the vns_transfer_call built-in tool.
You configure transfer behavior through transferServices in
VoiceElements_Instructions in your
CallStart response.
Blind Transfer
Caller is bridged immediately. The AI disconnects once the recipient answers.
Attended Transfer
The AI announces the caller to the recipient and gets confirmation before bridging.
Dynamic Resolution
Your API can return a transfer service at call time based on time of day, queue availability, or any business logic.
The vns_transfer_call Tool
You must define vns_transfer_call in your session configuration so the AI knows it can request a transfer.
Two forms are supported.
Simple — uses the "default" transfer service
No parameters needed when you have a single default transfer destination:
{
"name": "vns_transfer_call",
"description": "Transfers the current call to another number.",
"type": "function",
"parameters": null
}
With parameters — AI selects a named transfer service
Use this when you have multiple transfer services (e.g. afterhours, support) and want the AI to choose:
{
"name": "vns_transfer_call",
"description": "Transfers the current call.",
"type": "function",
"parameters": {
"type": "object",
"properties": {
"transferService": {
"type": "string",
"description": "Name of the transfer service to use (e.g. 'afterhours', 'support')."
}
}
}
}
Transfer Service Resolution Order
When vns_transfer_call is received,
VoiceElements resolves the transfer service using this chain in order:
Named service
If transferService is provided and matches a name in transferServices, use it.
onTransferToolName API call
If the named service wasn't found (or no name was given), and onTransferToolName is configured, your API is called to dynamically return a transfer service.
"default" service
If no transferService was supplied and no API is configured, the entry named "default" in transferServices is used.
Legacy direct number
If the AI passed a transferNumber directly (legacy mode), that number is dialed.
Fail
If none of the above resolve, the AI receives an error response.
Configuring Transfer Services
Transfer services are defined in the transferServices array
inside VoiceElements_Instructions of your CallStart response.
You can define as many named services as you need.
"transferServices": [
{
"name": "default",
"callerId": "+18005551234",
"callerIdName": "Acme Support",
"attended": false,
"useVnsNumberAsCallerId": false,
"dialMode": "sequential",
"transferNumbers": [
{ "number": "+13035551000", "dialTime": 20 },
{ "number": "+13035551001", "dialTime": 30 },
"+13035559999"
]
},
{
"name": "afterhours",
"callerId": "+18005551234",
"callerIdName": "Acme Support",
"attended": false,
"useVnsNumberAsCallerId": false,
"dialMode": "simultaneous",
"transferNumbers": [
"+13035552000",
"+13035552001"
]
}
]
Transfer Service Fields
| Field | Type | Description |
|---|---|---|
| name | string | Identifier. "default" is used when the AI calls vns_transfer_call with no service name. |
| callerId | string | E.164 caller ID shown to the recipient. |
| callerIdName | string | Caller ID name shown to the recipient. |
| attended | boolean | false = blind transfer. true = attended transfer (AI announces caller to recipient). |
| useVnsNumberAsCallerId | boolean | If true, uses the called DID as the caller ID instead of callerId. |
| dialMode | string | "sequential" — try numbers one at a time. "simultaneous" — ring all at once, first to answer wins. |
| transferNumbers | array | Numbers to dial. Each entry can be a plain string or an object with number and dialTime. |
| attendedTransferSessionUpdate | object | Custom session.update sent to the AI when an attended transfer connects. Overrides the built-in defaults entirely when present. |
| failedTransferSessionUpdate | object | Custom session.update sent to the AI when all transfer attempts fail. |
Per-Number Dial Time
Each entry in transferNumbers can be a plain string (uses the default 30-second dial time)
or an object with a custom dialTime in seconds.
The last number can have a longer dialTime if you want the call to reach voicemail.
"transferNumbers": [
{ "number": "+13035551000", "dialTime": 12 },
{ "number": "+13035551001", "dialTime": 18 },
"+13035559999"
]
Blind Transfer
Set "attended": false — the caller is immediately bridged to the first available recipient.
The AI is disconnected once the transfer connects.
Sequential
Numbers are tried one at a time. If the first doesn't answer within its dialTime, the next is tried, and so on. If all fail, the failure handler runs.
Simultaneous
All numbers are called at once. The first to answer wins; all other ringing calls are dropped.
{
"name": "support",
"attended": false,
"dialMode": "sequential",
"transferNumbers": [
{ "number": "+13035551000", "dialTime": 20 },
{ "number": "+13035551001", "dialTime": 20 }
]
}
Attended Transfer
Set "attended": true — the AI is routed to the outgoing call and announces the original caller to the recipient before bridging.
When the transfer channel connects, a session.update is sent to the AI
with instructions for the attended transfer phase. The AI then has access to two built-in tools:
vns_attended_transfer_accepted
Call when the recipient agrees to take the call. The caller is bridged.
vns_attended_transfer_declined
Call when the recipient refuses or voicemail is detected. The failure handler runs.
Default Attended Transfer Instructions
By default, VNS uses the following session.update when the attended transfer connects.
To override it, set attendedTransferSessionUpdate on the transfer service.
{
"type": "session.update",
"session": {
"type": "realtime",
"instructions": "The original caller has requested to be transferred to another number. You have been routed to the outgoing call. When the call is answered take a moment to determine if you reached a voicemail box. If so, then call vns_attended_transfer_declined. If you reach a human, then announce the call to the person that answered. Then ask them to accept the call.\n\n## Tool Call Rules\nYou may only call vns_attended_transfer_accepted or vns_attended_transfer_declined.\n\nvns_attended_transfer_accepted is called when the person answering the transferred call accepts.\n\nvns_attended_transfer_declined is called when the person answering the transferred call refuses the call.",
"tools": [
{
"name": "vns_attended_transfer_accepted",
"description": "Call this function to accept the transfer.",
"type": "function",
"parameters": null
},
{
"name": "vns_attended_transfer_declined",
"description": "Call this function to decline the transfer.",
"type": "function",
"parameters": null
}
]
}
}
Transfer Failure Handling
When all transfer attempts fail (all numbers busy/no-answer, or the recipient declines an attended transfer), VoiceElements runs the failure handler. The AI is routed back to the original caller with new session instructions.
Resolution Order
failedTransferSessionUpdate on the TransferService
Use a custom session.update for this specific service.
onTransferFailedToolName
Call your API to decide what to do. Your API returns a TransferFailedResponse JSON object with one of: a retry transferService, a useNamedTransferService name, or a custom sessionUpdate.
TransferFailedDefaults
The built-in fallback, used when nothing above is configured or all return null. The AI apologizes and ends the call.
Built-in Failure Defaults
When no failure handler is configured, VNS routes the AI back with these instructions:
{
"type": "session.update",
"session": {
"type": "realtime",
"instructions": "The call transfer was unsuccessful. Apologize to the caller and let them know the transfer could not be completed at this time. Suggest they try calling back later. Then call vns_end_conversation to end the call.\n\n## Tool Call Rules\nYou must call vns_end_conversation after delivering your message.",
"tools": [
{
"name": "vns_end_conversation",
"description": "Call this function to end the conversation after delivering the transfer failure message.",
"type": "function",
"parameters": {
"type": "object",
"properties": {
"farewell": {
"type": "string",
"description": "The farewell you would like to say to the caller."
}
},
"required": ["farewell"]
}
}
]
}
}
Dynamic Transfer Service via API
If you want your server to decide which transfer service to use at call time — based on time of day, caller history, or queue availability —
set onTransferToolName to a tool name in your toolkit.
When the AI calls vns_transfer_call,
VoiceElements will call your API endpoint and expect a complete TransferService JSON object back.
// In VoiceElements_Instructions:
"onTransferToolName": "transfer_request"
Your endpoint returns a complete TransferService object:
{
"name": "live-agent",
"callerId": "+18005551234",
"callerIdName": "Acme Support",
"attended": false,
"useVnsNumberAsCallerId": false,
"dialMode": "sequential",
"transferNumbers": [
{ "number": "+13035551000", "dialTime": 20 }
]
}
Additional Configuration Fields
| Field | Description |
|---|---|
| addSecondsToMaxTimeOnTransfer | Extends the maximum call duration by this many seconds once a transfer connects. Default: 7200 (2 hours). |
| onTransferToolName | Tool name to call for dynamic transfer service resolution. Your endpoint returns a full TransferService object. |
| onTransferFailedToolName | Tool name to call when all transfer attempts fail. Your endpoint returns a TransferFailedResponse specifying how to proceed. |
Ready to Automate Your Phone Lines?
See Voice Nexus in action. Book a live demo with our team and we'll walk you through setup, integrations, and pricing.