Supervisor Coaching Using Python

Overview

Supervisors in call centers need to coach agents to cultivate an effective team. Coaching involves supervisors listening in on live calls and advising agents without customers’ knowledge. A supervisor can also take over a call and talk to a customer directly. This guide shows how to implement supervisor coaching using Plivo‘s multiparty call (MPC) feature. We’ll look at four tasks:

  • Connecting a customer and an agent
  • Agent adding supervisor to a call
  • Supervisor joining call
  • Supervisor taking over call

Prerequisites

To get started, you need a Plivo account — sign up with your work email address if you don’t have one already. You must have a voice-enabled Plivo phone number to receive incoming calls; you can rent numbers from the Numbers page of the Plivo console, or by using the Numbers API. If this is your first time using Plivo APIs, follow our instructions to set up a Python development environment and a web server and safely expose that server to the internet.

Connect customer and agent

Consider the case of a call center where customers call a hotline number to connect with a customer support representative using a web app powered by Plivo Browser SDK. The call flow goes like this:

  1. Customer dials in from the browser app to talk to an agent.
  2. The customer is added to a multiparty call.
  3. The agent is added to the same multiparty call.

Outline - Connect customer and agent

Here’s what that process looks like in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from flask import Flask, Response, request, make_response
import plivo
from plivo import plivoxml

app=Flask(__name__)

music_url = "https://s3.amazonaws.com/plivocloud/music.mp3"
client = plivo.RestClient(auth_id="<auth_id>", auth_token="<auth_token>")

# Add customer to the MPC. You can assign this to the Plivo app of the endpoint mapped to the customer in the browser app
@app.route("/add/customer/", methods=["GET", "POST"])
def multipartycall_add_customer():
   mpc_name = "test"
   mpc_params = {
       "content": mpc_name,
       "role": "Customer",
       "status_callback_url": "https://<ngrok_identifier>.ngrok.io/add/agent/",
       "status_callback_method": "POST",
       "wait_music_url": music_url,
       "wait_music_method": "GET",
   }
   mpc_element = plivoxml.MultiPartyCallElement(**mpc_params)
   res = plivoxml.ResponseElement()
   res.add(mpc_element)
   return Response(res.to_string(), mimetype="application/xml")

# Add agent to the MPC to talk to the customer
@app.route("/customer/callback/", methods=["GET", "POST"])
def multipartycall_add_agent():
   mpc_EventName = request.form.get("EventName")
   mpc_MPCUUID = request.form.get("MPCUUID")
   mpc_ParticipantCallFrom = request.form.get("ParticipantCallFrom")
   if mpc_EventName == "MPCInitialized":
       call_params = {
           'role': "Agent",
           'uuid': mpc_MPCUUID,
           'start_mpc_on_enter': True,
           'from_': mpc_ParticipantCallFrom, # Customer number as caller ID
           'to_': "sip:websdk171107061912@phone.plivo.com", #Agent's endpoint username or phone number
           'call_status_callback_url': "https://<ngrok_identifier>.ngrok.io/agent/callback/",
           'call_status_callback_method': 'POST',
           "enter_sound": "none"
       }
       try:
           response = client.multi_party_calls.add_participant(**call_params)
       except Exception as e:
           response = client.multi_party_calls.stop(uuid=mpc_MPCUUID)
   return 'ok'

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

Replace the auth placeholders with your authentication credentials from the Plivo console.

Agent adds supervisor to a call

  1. The previous example was a simple case that involved just a customer and an agent. If the call center wants to provide supervisor coaching, agents can add a supervisor to an ongoing multiparty call like this:

    1. The agent clicks an Add Supervisor button on the dialer web app on which they’re talking to the customer.
    2. The supervisor is added to the multiparty call using Plivo’s Add Participant API.
    3. By default, only the agent will be able to hear the supervisor. You can override this by changing the coachMode parameter to false.

Outline - Agent adds supervisor

Here’s what that process looks like in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from flask import Flask, Response, request, make_response
import plivo
from plivo import plivoxml

app=Flask(__name__)

music_url = "https://s3.amazonaws.com/plivocloud/music.mp3"
client = plivo.RestClient(auth_id="<auth_id>", auth_token="<auth_token>")

@app.route("/mpc/customer/", methods=["GET", "POST"])
def multipartycall_customer():
  ....
  ....

# Add agent to the MPC to talk to the customer
@app.route("/customer/callback/", methods=["GET", "POST"])
def multipartycall_agent():
   ....
   ....

# Agent clicks "Add supervisor to the call" option to add them to the ongoing MPC
@app.route("/add_supervisor/<mpc_MPCUUID>", methods=["GET", "POST"])
def add_supervisor(mpc_MPCUUID):   
   call_params = {
       'role': "Supervisor",
       'uuid': mpc_MPCUUID, # you can get this from status_callback_url
       'dial_music': 'None',
       'from_': "<caller_id>", # Agent number as caller ID; you can get this from status_callback_url
       'to_': "sip:browsersdkdemo438313651789286059@phone.plivo.com", #Supervisor Phone number goes here
       'call_status_callback_url': "https://<ngrok_identifier>.ngrok.io/supervisor/callback/",
       'call_status_callback_method': 'POST',
   }
   response = client.multi_party_calls.add_participant(**call_params)
   return str(response)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

Supervisor joins an ongoing call

Not all supervisor calls are initiated by agents — supervisors can jump in themselves. Here’s how this process — often called call barging — works:

  1. An agent is talking to a customer on an ongoing multiparty call.
  2. A supervisor, who is monitoring all the live calls on the call center web dashboard, clicks on a Join the Call button next to the longest call in the queue.
  3. The supervisor can then listen to the call and coach the agent.

Outline - Supervisor joins a call

Here’s what that process looks like in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from flask import Flask, Response, request, make_response
import plivo
from plivo import plivoxml

app=Flask(__name__)

music_url = "https://s3.amazonaws.com/plivocloud/music.mp3"
client = plivo.RestClient(auth_id="<auth_id>", auth_token="<auth_token>")

@app.route("/mpc/customer/", methods=["GET", "POST"])
def multipartycall_customer():
    ....
    ....

# Add agent to the MPC to talk to the customer
@app.route("/customer/callback/", methods=["GET", "POST"])
def multipartycall_agent():
    ....
    ....

# Agent clicks "Add supervisor to the call" option to add them to the ongoing MPC
@app.route("/add_supervisor/", methods=["GET", "POST"])
def add_supervisor():    
    ....
    ....

# Supervisor clicks "Join the call" option to be added to the ongoing MPC
@app.route("/coach_the_agent/<mpc_MPCUUID>", methods=["GET", "POST"])
def join_specific_mpc(mpc_MPCUUID):   
   mpc_name = "test" # MPC name of the call to which the supervisor wishes to join; you can get this from status_callback_url
   mpc_params = {
       "content": mpc_name,
       "role": "Supervisor",
       "coach_mode": True, # The supervisor can talk to only the agent.
       "status_callback_url": "https://<ngrok_identifier>.ngrok.io/supervisor/callback/",
       "status_callback_method": "POST",
       "enter_sound": "none",
   }
   mpc_element = plivoxml.MultiPartyCallElement(**mpc_params)
   res = plivoxml.ResponseElement()
   res.add(mpc_element)
   return Response(res.to_string(), mimetype="application/xml")

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

Supervisor takes over a call

Depending on what they hear, sometimes supervisors want to talk to both the customer and the agent. Here’s how that process might go.

  1. An agent is talking to a customer on an ongoing multiparty call.
  2. The supervisor is monitoring all live calls on the call center web dashboard.
  3. The supervisor clicks on the Take Over the Call button of a specific call, and can then take over the call and talk to both the customer and the agent.

Outline - Supervisor takes over a call

Here’s what that process looks like in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from flask import Flask, Response, request, make_response
import plivo
from plivo import plivoxml

app=Flask(__name__)

music_url = "https://s3.amazonaws.com/plivocloud/music.mp3"
client = plivo.RestClient(auth_id="<auth_id>", auth_token="<auth_token>")

@app.route("/mpc/customer/", methods=["GET", "POST"])
def multipartycall_customer():
    ....
    ....

# Add agent to the MPC to talk to the customer
@app.route("/customer/callback/", methods=["GET", "POST"])
def multipartycall_agent():
    ....
    ....

# Agent clicks "Add supervisor to the call" option to add them to the ongoing MPC
@app.route("/add_supervisor/", methods=["GET", "POST"])
def add_supervisor():    
    ....
    ....

# Supervisor clicks "Join the call" option to be added to the ongoing MPC
@app.route("/coach_the_agent/", methods=["GET", "POST"])
def join_specific_mpc():    
    ....
    ....

# Supervisor clicks "Take over the call" option to be added to the ongoing MPC
@app.route("/talk_to_customer/", methods=["GET", "POST"])
def talk_to_customer():   
   mpc_name = "test" # MPC name of the call to which the supervisor wishes to join; you can get this from status_callback_url
   mpc_params = {
       "content": mpc_name,
       "role": "Supervisor",
       "coach_mode": false, # The supervisor can talk to only the agent
       "status_callback_url": "https://<ngrok_identifier>.ngrok.io/supervisor/callback/",
       "status_callback_method": "POST",
       "enter_sound": "none",
   }
   mpc_element = plivoxml.MultiPartyCallElement(**mpc_params)
   res = plivoxml.ResponseElement()
   res.add(mpc_element)
   return Response(res.to_string(), mimetype="application/xml")

if __name__ == "__main__":
   app.run(host="0.0.0.0", debug=True)

As you can see, Plivo makes it easy to set up and manage multiparty calls. With these capabilities, you can run your own call center, manage call transfers, coach agents, and much more. For more details, see our Multiparty Call API reference page.