Lifecycle of a Task: Workflows and Assignment

TaskRouter's primary job with a pending Task is to find a matching Worker. This assignment is handled by the Workflows within a Workspace.

When created, every Task is associated with a Workflow that is used to evaluate how to find a matching Worker. These Workflow configurations, represented in JSON, trace the path a Task takes until either a Reservation is accepted or the Task is canceled.

This page demonstrates how a Task finds a matching Worker given a Workflow. Workflows Overview provides documentation on how these Workflows can be configured.

Workflow Example

  "task_routing": {
    "filters": [
      {
        "expression": "type==\"Support\"",
        "filter_friendly_name": "Support Calls",
        "targets": [
          {
            "queue": <Just Support>,
            "timeout": 15,
            "expression": "worker.id IN task.preferred_agents"
          },
          {
            "timeout": 15
          }
        ]
      },
      {
        "expression": "type==\"Sales\"",
        "filter_friendly_name": "Sales Calls",
        "targets": [
          {
            "queue": <Just Sales>,
            "timeout": 15
          }
        ]
      }
    ],
    "default_filter": {
      "queue": <Everyone>
    }
  }
}

This configuration would be represented in Console like:

Sample Workflow

Workflow Basics

A Workflow evaluates linearly from the top to the bottom. A Task will find the first filter that matches that Task's attributes. Within that filter, the Task will then work progressively through each target ("routing step" in Console). A Task will wait in each step for the defined timeout attempting to get an accepted Reservation. If the Task hits the step timeout, it will move to the next step. If the final step is passed without an accepted Reservation, a WorkflowTimeout event will fire and the Task will be deleted.

If a Task doesn't match any filters, it will fallback to the Default Queue (default_filter) and attempt to find a matching Worker until the Task reaches its TTL.

Tracing a Sample 'Sales' Task

Suppose a Task is created for the Workflow defined above with the following attributes:

{
    "type": "Sales"
}

First, the Task would check against the "Support Calls" expression: type==\"Support\"". Failing that check, the Task then succeeds against the "Sales Calls" expression: "type==\"Sales\"".

Sales Filter:

{
    "expression": "type==\"Sales\"",
    "filter_friendly_name": "Sales Calls",
    "targets": [{
        "queue": <Just Sales>,
        "timeout": 15
    }]
}

The single routing step attempts to find a matching Worker in the "Just Sales" TaskQueue. This queue has the following Workers Expression: skills HAS "support".

TaskRouter maintains a list of Workers associated with each queue. Here, TaskRouter already knows all Workers which have the support skill. While the Task is attempting to be assigned, TaskRouter will filter the Workers in the queue for anyone that is in an Available activity state. For multitasking Workspaces, TaskRouter will additionally filter the Workers for anyone who has capacity for the Task's channel.

To summarize: the routing step above will find any Worker in the "Just Sales" queue that is Available and has capacity on the Task's channel.

Creating Reservations

If at least one Worker remains, TaskRouter will create a pending Reservation for the Worker who has been longest idle. A new Reservation is sent to client applications in three ways:

  1. An initialized Worker on the JS SDK can subscribe to the reservation.created event
  2. A reservation.created event will POST to the Event Callback URL
  3. An assignment event will POST to the Assignment Callback URL

If the Reservation is accepted, the Task will continue to its following Task States.

If the Reservation doesn't succeed (i.e., the Reservation is rejected or it times out), the Workflow will check the timeout on the routing step. If the Task is still within the timeout, TaskRouter will attempt to assign the Task to any other matching Workers. Otherwise if the Task is past the routing step timeout, the Task will flow to the next routing step or filter.

Tracing a Sample 'Support' Task

Suppose a Task is created for the Workflow defined above with the following attributes:

{
    "type": "Support",
    "preferred_agents": ["agent01"]
}

First, the Task would check against the "Support Calls" expression: type==\"Support\"" and succeed.

Support Filter:

{
    "expression": "type==\"Support\"",
    "filter_friendly_name": "Support Calls",
    "targets": [{
        "queue": <Just Support>,
        "timeout": 15,
        "expression": "worker.id IN task.preferred_agents"
    },{
        "timeout": 15
    }]
}

Similar to the Sales example above, TaskRouter will first find any Worker in the "Just Support" queue that is Available and has capacity on the Task's channel.

In addition, this routing step has an expression to match a subset of the Workers within the "Just Support' queue. As a result, TaskRouter will only generate a reservation for the Worker identified by "agent01" as a Worker attribute.

No Matching Workers Initially Available

Suppose our support Task is a voice call, and the "agent01" Worker is already on a call. If that Worker has their voice capacity set to 1, this Task will continue to wait for the 15 seconds timeout.

The sample workflow is simplifed for demonstration

In the Workflow above, all Support tasks would wait for 15 seconds attempting to match worker.id IN task.preferred_agents — even if task.preferred_agents doesn't exist. This could be more universally addressed with a filter like:

{
    "expression": "preferred_agents != null",
    "filter_friendly_name": "Preferred Agents",
    "targets": [{
        "queue": <Everyone>,
        "expression": "worker.id IN task.preferred_agents",
        "timeout": 15
    }]
}

After timeout, the Task will progress to the next routing step:

{
    "timeout": 15
}

Although that step doesn't contain a lot of detail, here is how that is rendered in Console:

Single Routing Step

This second step has inherited the previous step's queue, but this time no matching workers expression is applied — any Available Worker can match. Therefore this step behaves similarly to the Sales filter from the previous section.

Filter Summary: TaskRouter will first find any Available Worker in the "Just Support" queue with voice capacity who has "agent01" as their ID. After 15 seconds without a match, TaskRouter will expand the search to anyone in the same queue for another 15 seconds.

Advanced Workflow Features

In addition to the standard Workflow features mentioned here, there are additional features that impact how a Task finds a matching Worker.

  • Worker Ordering — Influencing the sort of which Worker is selected if multiple match the routing step
  • Skip Timeout — Moving to the next routing step if a matching Worker isn't immediately found
  • Multireservation — Sending multiple Reservations simultaneously. First accepeted gets the Task.

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.