Tips for Setting up Work from Home Agents with Twilio Flex

March 19, 2020
Written by

flex-wfh-header-agents.png

By now, just about everyone has been affected by the COVID-19 virus outbreak. For many people, one of these effects is having to work from home, maybe for the first time in their lives. Many contact centers are scrambling to transition their staff to work from home. Personally, I helped a company in Italy set up a Twilio Flex powered contact center in less than a week to completely replace their existing premise-based solution.

In this blog post, I would like to share a couple of tips that may be useful for companies who are scrambling to allow their contact center employees to work from home.

Changing the default codec in Flex to Opus

The default codec when launching Flex is G.711 (PCMU). This codec is uncompressed, and it is OK to use in an office setting with a commercial grade internet connection. However, when bandwidth is reduced, call quality will degrade significantly.

Most households do not have a high quality, fiber to the home internet connection, and internet traffic has become quite saturated with everyone working from home. Keeping this in mind, it would be a good idea to consider switching the default codec in Flex to Opus.

Why switch to Opus? Opus can deliver much higher voice quality while using approximately half the bandwidth when compared to G.711, (40 kb/s vs 80 kb/s). Opus is a dynamic codec, allowing it to adjust the quality based on the bandwidth available. Lots more information is available about Opus in this blog post and here.

How do you change the default codec in Flex? You will need to change the codec preferences via the Flex Configuration API (https://flex-api.twilio.com/v1/Configuration). Here is a quick curl command that will change the preferences with a single command. A pre-requisite to running this command is having jq installed on your computer.

curl -s 'https://flex-api.twilio.com/v1/Configuration' -u ACxxx:auth_token | jq -r -c '{ ui_attributes: .ui_attributes } * { "account_sid": "ACxxx", "ui_attributes": { "sdkOptions": { "voice": { "codecPreferences": ["opus", "pcmu"] } }}}' | curl -s -X POST 'https://flex-api.twilio.com/v1/Configuration' -u ACxxx:auth_token -H 'Content-Type: application/json' -d @-

Using Twilio Voice Client for Work from home agents

I also worked with a US-based insurance company who had 800 contact center agents. Their existing contact center solution could not support work from home agents, and their implementation was so complex and customized that they were unwilling to completely replace it. Configuring a new solution would simply take too long. Instead, we came up with a solution that allowed them to keep their existing telecom infrastructure in place, including the ACD, but the agents would utilize the Twilio Voice Client.

Here is a quick drawing of the architecture:

architecture

The customer's ACD platform routes the calls as usual. Instead of routing the calls to a SIP endpoint, they are routing the calls to a Twilio DID that is unique for each agent. When Twilio receives the incoming call, it simply routes it to the Twilio Voice Client that the agents have running in a browser tab.

If you are interested in setting up a similar solution, please start by following this guide.

We made a quick modification when the client is requesting the capability token, we pass an additional parameter with the phone number that is assigned to the agent. The code looks like this:

$.getJSON(`https://YOUR_FUNCTION_SUBDOMAIN_HERE/capability-token?phone=${phone}`)

The function which provides the token was modified to set the client name to the phone number that was passed in as a parameter:

exports.handler = function(context, event, callback) {
    
  Object.keys(event).forEach( thisEvent => console.log(`${thisEvent}: ${event[thisEvent]}`));
  
  let response = new Twilio.Response();

  // Add CORS Headers
  let headers = {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET",
    "Content-Type": "application/json"
  };
    
  // Set headers in response
  response.setHeaders(headers);
  
  response.setStatusCode(200);
  
  let ClientCapability = require('twilio').jwt.ClientCapability;

  const identity = `+${event.phone}`;
  const capability = new ClientCapability({
    accountSid: context.ACCOUNT_SID,
    authToken: context.AUTH_TOKEN,
  });

  capability.addScope(new ClientCapability.IncomingClientScope(identity));
  capability.addScope(new ClientCapability.OutgoingClientScope({
    applicationSid: context.TWIML_APP_SID,
    clientName: identity,
  }));

  // Include identity and token in a JSON response
  response.setBody({
    'identity': identity,
    'token': capability.toJwt()
  });
  
  callback(null, response);
};

Please keep in mind that using a Twilio Function to provide this token is not a secure solution, in a production environment you will want to host this function in your own infrastructure to control access to it.

Lastly, the client-voice function had to be modified as well to route the calls to the correct destination:

exports.handler = function(context, event, callback) {
    Object.keys(event).forEach( thisEvent => console.log(`${thisEvent}: ${event[thisEvent]}`));
    
    let twiml = new Twilio.twiml.VoiceResponse();

    if(event.To) {
      // Wrap the phone number or client name in the appropriate TwiML verb
      // if is a valid phone number
      const attr = event.From.substring(0, 6) === 'client' ? 'number' : 'client';

      const dial = twiml.dial({
        answerOnBridge: true,
        callerId: context.CALLER_ID,
      });
      dial[attr]({}, event.To);
    } else {
      twiml.say('Thanks for calling!');
    }

     callback(null, twiml);
};

We’re here to help in the fight against COVID-19

If you are a public health agency, hospital, or health-focused nonprofit and need some help communicating with your doctors, nurses, patients, or the community please reach out to us here.