Picture the situation. You are working on a task that requires you to immediately connect to an on-call employee. You dial their phone number, but it hits their voicemail. Who do you call to resolve the situation?
This use case is not uncommon in organisations that utilise shifts or rosters for their workforce management, and it usually results in the employee having to manually search an on-call roster document for another phone number to call. This process is fine for some use cases, but imagine that the situation was time-critical and needed an immediate response, where every minute and second was critical. Would you want this process to be manual? Probably not.
If you are following along and want to implement this solution, you will need to have the following prerequisites:
- A Twilio account and Twilio phone number
- Twilio Serverless Toolkit installed
- Update Geo Restrictions to allow for outbound calls to your country of choice
- An additional phone number to use as primary/secondary on-call. You can use the same number for primary/secondary.
You can see the full code on GitHub.
Organisations in various industries make use of on-call rosters to respond to events and emergencies outside of working hours. On-call employees are usually expected to be available at any time and with short notice. Clinicians, engineers, emergency services frequently using on-call systems.
An on-call system typically consists of a user interface, where an administrator updates the roster, and a notification mechanism. The inbound event to trigger a notification to the on-call person could be a sensor (IoT), a high severity ticket (webhook), a person in distress (SMS), or a patient contacting a clinician (call).
In this blog post, we will use a call as an example of the inbound event. We will focus on the notification mechanism with the on-call roster hosted in Twilio functions environmental variables. For a more advanced solution that allows you to create rules to automatically adjust your roster, you can consider expanding the solution by using Google Sheets or Microsoft Sharepoint. For Sheets you could explore the use of macros/formulas, and for Sharepoint you could use MS flow to automate the roster updates.
Consider the following use case:
Clinical laboratories usually consist of a number of medical technologists who all work on the analysis of specimens. However, there are certain cases where the expertise of a specialised clinician is required. A medical technologist has to access a portal and can manually call the first person, the secondary etc. on the roster. Wouldn’t it be easier to dial one number and automatically be able to speak to the ‘best’ available person?
Additionally, what if we could also detect when the primary on-call clinician is not available so we can automatically call the secondary, the tertiary, etc. This raises a few different edge cases that could also occur during the process, such as if the primary call hit voicemail, was busy, declined the call or the call timed out.
To detect voicemail we could use Twilio Answering Machine Detection (AMD) and for the rest we evaluate the status callback. The optional StatusCallbackEvent parameter lets you specify which call progress events Twilio will act on. You can use this parameter to tell Twilio to send information to the StatusCallback URL you specified when a call is initiated, ringing, answered, or completed.
The call flow will be as follows:
For the purposes of this tutorial, we would also like to record the calls for compliance and training purposes.
Dependencies and configuration for your build
Download the code and install the dependencies:
git clone https://github.com/apanagidis/twilio-roster cd twilio-roster npm install
Save the .env file and deploy the code using the following command, where roster-test is an arbitrary service name specific to your project:
twilio serverless:deploy --service-name roster-test
Capture the BaseURL of your functions, as shown in the following image. We are going to use it in the next step.
Revisit the included .env file and update it with your other account specific details:
Secondaryare the on-call numbers, i.e. the people that you would like to reachout once there is an incoming call to your on-call system.
BASEURLSRVis the Twilio Functions URL you obtained in the previous step
fromis the Twilio phone number that you will use to receive and initiate outbound calls.
The next step is to save and redeploy the code. As of this writing, when you are deploying using the Twilio Serverless plugin you are not allowed to update code, environmental variables, or dependencies using the Twilio Console. Since we updated the .env file, we need to redeploy the code:
twilio serverless:deploy --service-name roster-test --override-existing-project
Lastly, we need to configure our Twilio phone number to call our /app function every time there is an incoming call.
from phone number and under A call comes in, select your function:
Test your solution
Time to test out what you’ve built. Call your
from number. If everything went well you should be able to hear “On-Call. Attempting to contact primary. Please wait until we connect you”. Then the primary on-call number should ring and be placed in a conference.
Keep an eye on your debug logs
You can also review the logs from Serverless Toolkit:
twilio serverless:logs --tail
There are a few different scenarios that we recommend you try:
- Decline the primary call.
- Wait for the first call to timeout.
- Answer the primary call with a business greeting (to simulate voicemail)
- Decline the secondary call
Call recordings are also available under Programmable Voice section of the Twilio Console
Ideas to improve the solution
Although we have built a functional on-call system, there are plenty of edge cases that we did not cover and therefore room for potential improvements. Here are some ideas to get you started:
- Fetch on-call roster from third party system (i.e. Google Sheets or MS Sharepoint)
- What if the caller hangs up before the primary/secondary answers the call? We should be informing the callee that the caller dropped the call and perhaps follow up with an SMS with the caller details.
- What if the caller was not able to reach either primary or secondary? Perhaps we can follow with an SMS with the caller details or have a last-resort hardcoded number to a backup line.
- What if we want to provide the caller the ability to provide their number for a callback? Maybe the caller is currently using a line that is not able to receive calls or the calls will be routed to the reception.
- Avoid having to populate the Base URL. Make use of Function path as it allows for built-in signature validation and you do not need to populate the BaseURL.
We demonstrated how you can use Twilio Programmable Voice and Twilio Functions to deliver a simple yet powerful on-call roster solution, one that delivers a superior customer experience by giving your employees the option to dial one number and be automatically connected to the ‘best’ available person on your roster. By automating this solution you remove the need for employees to manually search for the next available on-call employee to connect with. Your employees will thank you!
Mike Meisels is an Enterprise Account Executive on the Australia Team. Mike has a background in developing and implementing solution architecture. Mike joined the dark side 4 years ago but still likes to keep his hands dirty with developing solutions for Not For Profits and other organizations. Mike hides in his study away from his 5 daughters, 3 cats, and 2 dogs. Active on LinkedIn, he can be tracked down here.
Adonis is a Twilio Solutions Architect working on the Professional Services team in Singapore. You can reach him at apanagidis [at] twilio.com
Paul is a Technical Program Manager in our APJ Professional Services team who advise and support our customers with their Twilio builds. Based in Melbourne, Australia, you can usually find Paul paddle-boarding in Port Philip Bay or looking after his two young daughters #GirlDad. You can reach him at pfenton [at] twilio.com