2

Im looking to invoke a twilio function and obtain a count of available workers.

I have a feeling it might be related to TaskQueues and the Matching Workers who are available?

Ive come up with the following. However, users are still listed as available when they are interacting with a task, which means this wont work necessarily.

exports.handler = function (context, event, callback) {
const client = require('twilio')(context.ACCOUNT_SID, context.AUTH_TOKEN);
client.taskrouter
.workspaces('eee')
.workers.list()
.then(workers => {
    data = {
        availWorkersCount: Object.keys(workers.filter(x=> x.available === true && x.attributes.includes("sales"))).length
    };

    const response = new Twilio.Response();
    response.appendHeader('Access-Control-Allow-Origin', '*');
    response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS POST GET');
    response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
    response.appendHeader('Content-Type', 'application/json');
    response.setBody(data);

    callback(null, response);
});

};

Judy007
  • 5,484
  • 4
  • 46
  • 68
  • Twilio employee here. Have you checked what the `configured_capacity` of your workers' channels is (https://www.twilio.com/docs/taskrouter/api/workerchannel?code-sample=code-list-all-worker-channels-2&code-language=Ruby&code-sdk-version=5.x)? If you're using Flex the default is 10 simultaneous SMS/Chat conversations, and 1 Voice conversation. When you say that workers are still available while interacting with a task, does that include ones that are on voice calls? – Charlie Weems Jul 31 '19 at 00:07
  • Also, using the cumulative statistics endpoint would allow you to get sums of people in each activity state: https://www.twilio.com/docs/taskrouter/api/worker-statistics?code-sample=code-retrieve-all-workers-cumulative-statistics-3&code-language=Ruby&code-sdk-version=5.x – Charlie Weems Jul 31 '19 at 00:11
  • @CharlieWeems, Perhaps you can write an answer whichs shows how the solution depends on the capacity? For simplicity, lets assume the agent can handle at most 1 task per task type. Also, I believe workers are still in 'available' state while responding to a task, regardless of task type. – Judy007 Jul 31 '19 at 19:13
  • My use case here (going a little deeper) is that I invoke the twilio function in Studio to check the available workers. The idea is that if there are no workers available, do XYZ. Otherwise, send to flex. This allows me to optimize the outcome for the customer who initiated some type of inbound task. Ex. WebChat, user initiates webchat, no agents are available, offer customer ability to use chatbot instead. Another example, use initiates inbound text, no agent available, allow chatbot to answer questions. I dont believe this is limited to these types of task types. I believe all channels apply – Judy007 Jul 31 '19 at 19:15
  • I would suggest using TaskRouter itself to do this. It's exactly what it is for, if there are no available workers you can have a task move to another queue and interact with it differently. – philnash Aug 02 '19 at 04:11

1 Answers1

0

I know this is a bit late, but this is the chunk of code I use in a twilio function to do just this. We call the function from the studio flow and use the results to decide if I am going to route the call into voicemail or play some IVR options for picking what queue they should be put in. To use it you can pass in an optional skill to filter down the agents even more. We grab all available workers then filter down to only the ones that have the needed skill.

You could then take this and check if any of the agents that are available also have a task assigned to them then remove them from the count.

const fetch = require("node-fetch");

exports.handler = function(context, event, callback) {
    let response = new Twilio.Response();

    // Set the status code to 200 OK
    response.setStatusCode(200);

    // Set the Content-Type Header
    response.appendHeader('Access-Control-Allow-Origin', '*');
    response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS, POST, GET');
    response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
    response.appendHeader('Content-Type', 'application/json');

    let body = {
        TotalAvailable: 0
    };
    
    let client = context.getTwilioClient();
    client.taskrouter.workspaces(context.WorkspaceSid)
        .workers
        .list({
            available: 'true',
            limit: 50
        })
        .then((workers) => {
            let agents = [];
            let i = 0;
            if(workers){
                for(i = 0; i < workers.length; i++){
                    let worker = workers[i];
                    let item = {};
                    let attributes = JSON.parse(worker.attributes);

                    if(attributes && attributes.routing && attributes.routing.skills && attributes.routing.skills.length > 0){
                        item.skills = attributes.routing.skills;
                        item.nid = attributes.nid;
                        item.first_name = attributes.first_name;
                        item.last_name = attributes.last_name;
                        
                        if(event.skill){
                            if(item.skills.includes(event.skill)){

                                // TODO: filter here 

                                agents.push(item);
                            }    
                        }else{
                            agents.push(item);
                        }
                    }
                }
            }
            body.TotalAvailable = agents.length;
            body.Agents = agents;

            response.setBody(body);
            callback(null, response);
        })
        .catch((ex) => {
            body.error = true;
            body.message = ex;
            response.setBody(body);
            callback(null, response);
        });
};
dp.
  • 229
  • 1
  • 2
  • 11