Skip to content

A server which allows you to route tasks to agents.

License

Notifications You must be signed in to change notification settings

TopCS/comms-router

 
 

Repository files navigation

Comms Router

Overview

Comms Router implements routing tasks to agents for handling. Routing is based on skills needed for the tasks and capabilities of the agents.

A demo application shows how to apply the router to build a call center.

Concepts

  • Task - work item characterized by its requirements - set of skills needed expressed by the user as key/value pairs.
  • Agent - abstract entity able to handle tasks, characterized by its capabilities - the skills it has expressed by the user as key/value pairs.
  • Queue - collection of tasks waiting for the next available agent. It has a predicate defined by the user that is matched agains the agents' skills to select these able to serve the queue.
  • Plan - defines how a task is handled by the router selecting a queue for it.
  • Router - a container for the router entities allowing different user application to share the same database.

How it works

User application creates a router and then one or more queues, agents and plans.

Then the application calls the router to create a task with its requirements and either places it in a queue or assigns a plan to it.

The plan contains list of rules, which the router executes in order. First rule which predicate matches the task requirements determines the queue for this task.

When an agent become available for this task, it is put into state "busy" and the callback URL provided by the user for this task is called with information about the task and the selected agent.

The user's application then informs the agent about the task and tracks the task's completion. When the task is done, the user's application changes the task's state within the router, which makes the agent available for subsequent tasks.

Installing the router

Requirements

  • Java - Oracle JDK/JRE 8 (build/runtime)
  • Apache Maven - 3.5 (build)
  • SQL Server - MySQL 5.7 (runtime)
  • Java Servlet Container - Tomcat 8 (runtime)

Although the software may work with different flavors of Java, SQL Server or Web Container, currently it is being tested with these listed above.

Build

Install Java and Maven, clone the repo and execute:

mvn install

The resulting war file should be:

web/target/comms-router-web.war

Install

Create database for the router.

Create DB user to be used by the router and grant this user access to the newly created database.

Configure JNDI data source with name "jdbc/commsRouterDB". Details on how to do this in Tomcat can be found here.

Deploy comms-router-web.war into Tomcat. Depending on your Tomcat settings this can be done by simple copying it to the Tomcat's webapps directory.

Configuration

Properties for the comms-router are stored in a file. It's location is specified by java property that can be specified in tomcat's command line with: -Dcomms.router.config.file=/opt/tomcat/conf/application.properties

Alternatively, in $CATALINA_BASE/conf/context.xml or in $CATALINA_BASE/conf/[engine_name]/context.xml with adding <Parameter name="comms.router.config.file" value="/opt/tomcat/conf/application.properties"/>

Authentication setup is described here

Test

List routers:

curl http://localhost:8080/comms-router-web/api/routers

Quick tutorial

Note that the commands listed below are meant to be used with a Unix shell. Some of them need to be modified in order to work on Windows.

For example, the command for creating queues would look like this:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/queues/queue-es -H "Content-Type:application/json" -d "{\"predicate\":\"language==es\"}"

For more information take a look at this batch file.

Resource Identification

Routers are identified by their Ref ID, which can be provided by the user or generated by the system. Router Ref IDs must be unique within the system.

All other resources are identified by the their Ref ID, again provided by the user or generated by the application and the Ref ID of the router that contains them. Their Ref IDs must be unique within their containing router.

Create a router, providing it's Ref ID:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router

Or request the system to assign the Ref ID:

curl -X POST http://localhost:8080/comms-router-web/api/routers

The Ref ID is returned in the response body:

{"ref":"HaOYogXa8qgX9NlRHJi9Y2"}

And URL of the created entity is in the header LOCATION of the response:

Location: http://localhost:8080/comms-router-web/api/routers/HaOYogXa8qgX9NlRHJi9Y2

Create some queues.

For example, let's create one handled by English speaking agents:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/queues/queue-en -H 'Content-Type:application/json' -d$'{"predicate":"language==en"}}'

And one more handled by these speaking Spanish:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/queues/queue-es -H 'Content-Type:application/json' -d$'{"predicate":"language==es"}}'

More detailed explanation of the expression language can be found here

Create agents.

Let's assume we have have three agents - Alice speaking English, Juan speaking Spanish and Maria speaking both English and Spanish.

So for Alice we'll have:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/agents/alice -H 'Content-Type:application/json' -d'{"address":"sip:alice@comms-router.org","capabilities":{"language":["en"]}}'

for Juan:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/agents/juan -H 'Content-Type:application/json' -d '{"address":"sip:juan@comms-router.org","capabilities":{"language":["es"]}}'

and for Maria:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/agents/maria -H 'Content-Type:application/json' -d'{"address":"sip:maria@comms-router.org","capabilities":{"language":["en","es"]}}'

Note the address field. It does not affect the router logic and is used by the user application to store information that it needs to route tasks to this agent. In our example addresses are SIP URIs.

List agents and note the queue assignments:

curl http://localhost:8080/comms-router-web/api/routers/my-router/agents

[
  {
    "ref": "alice",
    "routerRef": "my-router",
    "capabilities": {
      "language": [
        "en"
      ]
    },
    "address": "sip:alice@comms-router.org",
    "state": "offline",
    "queueRefs": [
      "queue-en"
    ]
  },
  {
    "ref": "juan",
    "routerRef": "my-router",
    "capabilities": {
      "language": [
        "es"
      ]
    },
    "address": "sip:juan@comms-router.org",
    "state": "offline",
    "queueRefs": [
      "queue-es"
    ]
  },
  {
    "ref": "maria",
    "routerRef": "my-router",
    "capabilities": {
      "language": [
        "en",
        "es"
      ]
    },
    "address": "sip:maria@comms-router.org",
    "state": "offline",
    "queueRefs": [
      "queue-en",
      "queue-es"
    ]
  }
]

Create a plan.

Let's create a plan with a rule that will route tasks requiring Spanish agent in our Spanish queue. Tasks that don't match this rule we will route to the English queue.

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/plans/by-language -H 'Content-Type:application/json' -d$'{"description":"put your plan description", "rules":[{"tag":"spanish", "predicate":"language==es", "routes":[{"queueRef":"queue-es", "priority":3, "timeout":300}, {"priority":10, "timeout":800}]}], "defaultRoute":{"queueRef":"queue-en"}}'

Create tasks.

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/tasks/task-es -H 'Content-Type:application/json' -d$'{"requirements":{"language":"es"},"planRef":"by-language","callbackUrl":"https://requestb.in/1koh4zk1?inspect"}'

Here the task requires agent speaking Spanish and we assign to it our plan that routes tasks by language.

The "callbackUrl" parameter specifies the user application entry point to be called by the router for activity related with this task. An easy way to test the router is to use a requestb.in to accept the callback, as we are doing in this example.

In addition to using a plan to route tasks, the router accepts direct queue assignment by the user application:

curl -X PUT http://localhost:8080/comms-router-web/api/routers/my-router/tasks/task-en -H 'Content-Type:application/json' -d$'{"queueRef":"queue-en","callbackUrl":"https://requestb.in/1koh4zk1?inspect"}'

Let's list the tasks and see the queues assigned:

curl http://localhost:8080/comms-router-web/api/routers/my-router/tasks

[
  {
    "ref": "task-es",
    "routerRef": "my-router",
    "requirements": {
      "language": "es"
    },
    "state": "waiting",
    "queueRef": "queue-es",
    "callbackUrl": "https://requestb.in/1koh4zk1?inspect",
    "priority": 3,
    "createDate": 1524735116224,
    "updateDate": 1524735116224,
    "queuedTimeout": 300
  },
  {
    "ref": "task-en",
    "routerRef": "my-router",
    "state": "waiting",
    "queueRef": "queue-en",
    "callbackUrl": "https://requestb.in/1koh4zk1?inspect",
    "priority": 0,
    "createDate": 1524735126376,
    "updateDate": 1524735126376,
    "queuedTimeout": 3600
  }
]

All tasks are in state "waiting" as all our agents are in state "offline".

Change agent's state. In api it is post request with data we want to change, but the data can be chaged in parallel. We use optimistic locking. It is done through ETAGS header.

* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /comms-router-web/api/routers/my-router/agents/maria HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
> Content-Type:application/json
>
< HTTP/1.1 200
< ETag: "73b6d85f48e15bae419180ce208f9fc5ae7ca9af290aac96c983467e891ba072"
< Content-Type: application/json
< Content-Length: 172
< Date: Thu, 26 Apr 2018 07:19:09 GMT
<
* Connection #0 to host localhost left intact
{"ref":"maria","routerRef":"my-router","capabilities":{"language":["en","es"]},"address":"sip:maria@comms-router.org","state":"offline","queueRefs":["queue-es","queue-en"]}

Value of ETags header is placed in IF-MATCH header of the request for change in agent's state: curl -X POST http://localhost:8080/comms-router-web/api/routers/my-router/agents/maria -H 'Content-Type:application/json' -H 'IF-MATCH:"73b6d85f48e15bae419180ce208f9fc5ae7ca9af290aac96c983467e891ba072"' -d '{"state":"ready"}'

Now the router assigns a task this agent and changes its state to "busy". Call to the provided callbackUrl can be observed in requestb.in.

Complete Task.

When the user application is done with processing a task it must declare it as done:

curl -X POST http://localhost:8080/comms-router-web/api/routers/my-router/tasks/task-es -H 'Content-Type:application/json' -d '{"state":"completed"}'

The router then releases the agent and it is available for other tasks. As in this example the agent "Maria" can serve both queues, it will automatically get the other task we created:

curl http://localhost:8080/comms-router-web/api/routers/my-router/tasks

[
  {
    "ref": "task-es",
    "routerRef": "my-router",
    "requirements": {
      "language": "es"
    },
    "state": "completed",
    "callbackUrl": "https://requestb.in/1koh4zk1?inspect",
    "priority": 3,
    "createDate": 1524735116224,
    "updateDate": 1524735299382,
    "queuedTimeout": 300
  },
  {
    "ref": "task-en",
    "routerRef": "my-router",
    "state": "assigned",
    "queueRef": "queue-en",
    "agentRef": "maria",
    "callbackUrl": "https://requestb.in/1koh4zk1?inspect",
    "priority": 0,
    "createDate": 1524735126376,
    "updateDate": 1524735299403,
    "queuedTimeout": 3600
  }
]

We should finish our journey by making this task completed:

curl -X POST http://localhost:8080/comms-router-web/api/routers/my-router/tasks/task-en -H 'Content-Type:application/json' -d '{"state":"completed"}'

Additional resources

  • Browse docs directory for additional documentation.
  • See our demo application as an example how to integrate the router with Nexmo API]

About

A server which allows you to route tasks to agents.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 83.5%
  • Common Lisp 14.0%
  • Scala 1.0%
  • PHP 0.6%
  • Shell 0.5%
  • Batchfile 0.3%
  • HTML 0.1%