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:
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 Node.js development environment and a web server and safely expose that server to the internet.
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:
Here’s what that process looks in Node.js.
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
var plivo = require('../plivo-node/');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
var musicUrl = "https://s3.amazonaws.com/plivocloud/music.mp3"
var client = new plivo.Client("<auth_id>","<auth_token>");
// Add customer to the MPC
app.all('/add/customer/', function (request, response) {
var r = new plivo.Response();
var mpcName = 'test';
var params = {
"role": "Customer",
"statusCallbackUrl": "https://<ngrok_identifier>.ngrok.io/add/agent/",
"statusCallbackMethod": "POST",
"waitMusicUrl": musicUrl,
"waitMusicMethod": "GET",
};
r.addMultiPartyCall(mpcName, params);
console.log(r.toXML());
response.set({ 'Content-Type': 'text/xml' });
response.end(r.toXML());
});
//Add agent to the MPC to talk to the customer
app.all('/add/agent/', function (request, response) {
var mpcEventName = request.query.EventName || request.body.EventName;
var mpcMPCUUID = request.query.MPCUUID || request.body.MPCUUID;
var mpcParticipantCallFrom = request.query.ParticipantCallFrom || request.body.ParticipantCallFrom;
console.log(mpcEventName);
if (mpcEventName == 'MPCInitialized') {
client.multiPartyCalls.addParticipant('Agent', { 'uuid': mpcMPCUUID, 'from': mpcParticipantCallFrom, 'to': 'sip:Testendpoint181116105835@phone.plivo.com', 'status_callback_url': 'https://<ngrok_identifier>.ngrok.io/agent/callback/' })
console.log(response);
}
});
// Collect status callback events after agent joins the MPC
app.all('/agent/callback/', function (request, response) {
var mpcMPCUUID = request.query.MPCUUID;
console.log(mpcMPCUUID)
});
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
Replace the auth placeholders with your authentication credentials from the Plivo console.
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:
Here’s what that process looks like in Node.js.
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
var plivo = require('../plivo-node/');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
var musicUrl = "https://s3.amazonaws.com/plivocloud/music.mp3"
var client = new plivo.Client("<auth_id>","<auth_token>");
// Add customer to the MPC
app.all('/add/customer/', function (request, response) {
...
...
});
//Add agent to the MPC to talk to the customer
app.all('/add/agent/', function (request, response) {
...
...
});
// Collect status callback events after agent joins the MPC
app.all('/agent/callback/', function (request, response) {
...
...
});
// Agent clicks "Add supervisor to the call" option to add them to the ongoing MPC
app.all('/add_supervisor/:mpcMPCUUID', function (request, response) {
var mpcUUID = request.params("mpcMPCUUID");
client.multiPartyCalls.addParticipant('Supervisor', { 'uuid': mpcUUID, 'from': mpcParticipantCallFrom, 'to': 'sip:Testendpoint181116105835@phone.plivo.com', 'status_callback_url': 'https://<ngrok_identifier>.ngrok.io/supervisor/callback/' })
console.log(response);
});
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
Not all supervisor calls are initiated by agents — supervisors can jump in themselves. Here’s how this process — often called call barging — works:
Here’s what that process looks like in Node.js.
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
52
53
54
55
56
var plivo = require('../plivo-node/');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
var musicUrl = "https://s3.amazonaws.com/plivocloud/music.mp3"
var client = new plivo.Client("<auth_id>","<auth_token>");
// Add customer to the MPC
app.all('/add/customer/', function (request, response) {
...
...
});
//Add agent to the MPC to talk to the customer
app.all('/add/agent/', function (request, response) {
...
...
});
// Collect status callback events after agent joins the MPC
app.all('/agent/callback/', function (request, response) {
...
...
});
// Agent clicks "Add supervisor to the call" option to add them to the ongoing MPC
app.all('/add_supervisor/:mpcMPCUUID', function (request, response) {
...
...
});
// Supervisor clicks "Join the call" option to be added to the ongoing MPC
app.all('/coach_the_agent/', function (request, response) {
var r = new plivo.Response();
var mpcName = 'test'; // MPC name of the call to which the supervisor wishes to join; you can get this from status_callback_url
var params = {
"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",
};
r.addMultiPartyCall(mpcName, params);
console.log(r.toXML());
response.set({ 'Content-Type': 'text/xml' });
response.end(r.toXML());
});
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
Depending on what they hear, sometimes supervisors want to talk to both the customer and the agent. Here’s how that process might go.
Here’s what that process looks like in Node.js.
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
52
53
54
55
56
57
58
59
60
61
62
var plivo = require('../plivo-node/');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
var musicUrl = "https://s3.amazonaws.com/plivocloud/music.mp3"
var client = new plivo.Client("<auth_id>","<auth_token>");
// Add customer to the MPC
app.all('/add/customer/', function (request, response) {
...
...
});
//Add agent to the MPC to talk to the customer
app.all('/add/agent/', function (request, response) {
...
...
});
// Collect status callback events after agent joins the MPC
app.all('/agent/callback/', function (request, response) {
...
...
});
// Agent clicks "Add supervisor to the call" option to add him to the ongoing MPC
app.all('/add_supervisor/:mpcMPCUUID', function (request, response) {
...
...
});
// Supervisor clicks "Join the call" option to add him to the ongoing MPC
app.all('/coach_the_agent/', function (request, response) {
...
...
});
// Supervisor clicks "Join the call" option to be added to the ongoing MPC
app.all('/talk_to_customer/', function (request, response) {
var r = new plivo.Response();
var mpcName = 'test'; // MPC name of the call to which the supervisor wishes to join; you can get this from status_callback_url
var params = {
"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",
};
r.addMultiPartyCall(mpcName, params);
console.log(r.toXML());
response.set({ 'Content-Type': 'text/xml' });
response.end(r.toXML());
});
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
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.