On-Hold Specialist Transfer
This document explains how to handle a scenario where a user is on hold while the system attempts to connect them to a specialist. If the specialist does not pick up within X seconds or if the call hits voicemail, we take an alternate action (like playing an announcement or scheduling an appointment). This solution integrates Vapi.ai for AI-driven conversations and Twilio for call bridging.
Problem
Vapi.ai does not provide a built-in way to keep the user on hold, dial a specialist, and handle cases where the specialist is unavailable. We want:
- The user already talking to the AI (Vapi).
- The AI offers to connect them to a specialist.
- The user is placed on hold or in a conference room.
- We dial the specialist to join.
- If the specialist answers, everyone is merged.
- If the specialist does not answer (within X seconds or goes to voicemail), we want to either announce “Specialist not available” or schedule an appointment.
Solution
- An inbound call arrives from Vapi or from the user directly.
- We store its details (e.g., Twilio CallSid).
- We send TwiML (or instructions) to put the user in a Twilio conference (on hold).
- We place a second call to the specialist, also directed to join the same conference.
- If the specialist picks up, Twilio merges the calls.
- If not, we handle the no-answer event by playing a message or returning control to the AI for scheduling.
Steps to Solve the Problem
-
Receive Inbound Call
- Twilio posts data to your
/inbound_call
. - You store the call reference.
- You might also invoke Vapi for initial AI instructions.
- Twilio posts data to your
-
Prompt User via Vapi
- The user decides whether they want the specialist.
- If yes, you call an endpoint (e.g.,
/connect
).
-
Create/Join Conference
- In
/connect
, you update the inbound call to go into a conference route. - The user is effectively on hold.
- In
-
Dial Specialist
- You create a second call leg to the specialist’s phone.
- A
statusCallback
can detect no-answer or voicemail.
-
Detect Unanswered
- If Twilio sees a no-answer or failure, your callback logic plays an announcement or signals the AI to schedule an appointment.
-
Merge or Exit
- If the specialist answers, they join the user.
- If not, the user is taken off hold and the call ends or goes back to AI.
-
Use Ephemeral Call (Optional)
- If you need an in-conference announcement, create a short-lived Twilio call that
<Say>
the message to everyone, then ends the conference.
- If you need an in-conference announcement, create a short-lived Twilio call that
Code Example
Below is a minimal Express.js server aligned for On-Hold Specialist Transfer with Vapi and Twilio.
- Express Setup and Environment
/inbound_call
- Handling the Inbound Call
/connect
- Putting User on Hold and Dialing Specialist
/conference
- Placing Callers Into a Conference
/participant-status
- Handling No-Answer or Busy
/announce
(Optional) - Ephemeral Announcement
- Starting the Server
How to Test
-
Environment Variables
SetTWILIO_ACCOUNT_SID
,TWILIO_AUTH_TOKEN
,FROM_NUMBER
,TO_NUMBER
,VAPI_BASE_URL
,PHONE_NUMBER_ID
,ASSISTANT_ID
, andPRIVATE_API_KEY
. -
Expose Your Server
- Use a tool like
ngrok
to create a public URL to port 3000. - Configure your Twilio phone number to call
/inbound_call
when a call comes in.
- Use a tool like
-
Place a Real Call
- Dial your Twilio number from a phone.
- Twilio hits
/inbound_call
, and run Vapi logic. - Trigger
/connect
to conference the user and dial the specialist. - If the specialist answers, they join the same conference.
- If they never answer, Twilio eventually calls
/participant-status
.
-
Use cURL for Testing
- Simulate Inbound:
- Connect:
- Simulate Inbound:
Note on Replacing “Connect” with Vapi Tools
Vapi offers built-in functions or custom tool calls for placing a second call or transferring, you can replace the manual /connect
call with that Vapi functionality. The flow remains the same: user is put in a Twilio conference, the specialist is dialed, and any no-answer events are handled.
Notes & Limitations
-
Voicemail
If a phone’s voicemail picks up, Twilio sees it as answered. Consider advanced detection or a fallback. -
Concurrent Calls
Multiple calls at once require storing separateCallSid
s or similar references. -
Conference Behavior
startConferenceOnEnter: true
merges participants immediately;endConferenceOnExit: true
ends the conference when that participant leaves. -
X Seconds
Decide how you detect no-answer. Typically, Twilio sets a finalcallStatus
if the remote side never picks up.
With these steps and code, you can integrate Vapi Assistant while using Twilio’s conferencing features to hold, dial out to a specialist, and handle an unanswered or unavailable specialist scenario.