Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
twilio avatar

Twilio Taskrouter Routing

  • 82 installs
  • 26 repo stars
  • Updated July 29, 2026
  • twilio/ai

twilio-taskrouter-routing is an agent skill for configuring Twilio TaskRouter Workers, queues, workflows, and assignment callbacks for skills-based routing.

About

The twilio-taskrouter-routing skill implements Twilio TaskRouter for skills-based routing instead of custom queuing logic. It walks through creating a Workspace, Activities for agent states, Workers with JSON attributes, Task Queues with target_workers expressions, and Workflows with filters, timeouts, and default_filter catch-alls. Incoming tasks flow from Workflow routing rules to skill-matched queues, then to Workers via Reservations handled through assignment callbacks that dequeue or conference callers within five seconds. Key patterns include priority routing, AI agent escalation tasks carrying conversation summaries, and multi-tier timeout overflow between specialized and default queues. The skill documents silent failure gotchas such as hyphens in attribute names, HAS on non-array fields, reservation timeout cascades that drain available workers, and immutable Activity available flags. Scale guidance spans single-queue setups under ten agents through Flex-backed multi-tier workflows above fifty. Use for multi-agent contact centers, support queues, or AI-to-human escalation routing.

  • Scaffolds Workspace, Activities, Workers, Task Queues, and Workflows end to end.
  • Handles assignment callbacks with dequeue or conference instructions.
  • Documents skills-based routing, priority tasks, and AI escalation patterns.
  • Explains hyphen, HAS operator, and reservation timeout gotchas.
  • Provides scale guidance from small phone queues to Flex supervisor tooling.

Twilio Taskrouter Routing by the numbers

  • 82 all-time installs (skills.sh)
  • +5 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #3,041 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

twilio-taskrouter-routing capabilities & compatibility

Capabilities
workspace and activity provisioning · worker attribute and task queue expression desig · workflow filter and timeout escalation configura · assignment callback dequeue and conference handl · ai escalation task creation with conversation co
Use cases
orchestration · api development
From the docs

What twilio-taskrouter-routing says it does

TaskRouter is Twilio's skills-based routing engine.
SKILL.md
Developers reinvent TaskRouter in custom Node.js — don't.
SKILL.md
npx skills add https://github.com/twilio/ai --skill twilio-taskrouter-routing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs82
repo stars26
Last updatedJuly 29, 2026
Repositorytwilio/ai

How do I route incoming support tasks to the right agents without building custom queuing logic?

Configure Twilio TaskRouter workspaces with Workers, Task Queues, Workflows, and assignment callbacks for skills-based contact center routing.

Who is it for?

Teams building multi-agent contact centers, support queues, or AI escalation routing on Twilio.

Skip if: Skip for single-agent direct dial flows or apps that do not need queue-based routing.

When should I use this skill?

User asks to set up TaskRouter, skills-based routing, agent queues, or AI escalation to humans.

What you get

A TaskRouter workspace with skill-matched queues, workflow filters, and assignment callback handling for live tasks.

Files

SKILL.mdMarkdownGitHub ↗

Overview

TaskRouter is Twilio's skills-based routing engine. Instead of building custom queuing logic, you define Workers (agents), Task Queues (groups), and Workflows (routing rules). TaskRouter matches incoming tasks to the best available worker.

Incoming Task → Workflow (routing rules) → Task Queue (skill match) → Worker (agent)
                                                                        ↓
                                                                   Reservation
                                                                   (accept/reject)

Common mistake: Developers reinvent TaskRouter in custom Node.js — don't. If you're building skills-based routing, queue management, or agent assignment, use TaskRouter.

---

Prerequisites

  • Twilio account — see twilio-account-setup
  • TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN — see twilio-iam-auth-setup
  • SDK: pip install twilio / npm install twilio
  • For voice routing: a Twilio phone number with webhook configured — see twilio-voice-twiml
  • For AI escalation: ConversationRelay with escalation tools — see twilio-voice-conversation-relay

---

Quickstart

Step 1 — Create a Workspace

A Workspace is the top-level container for all TaskRouter resources.

Python

import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

workspace = client.taskrouter.v1.workspaces.create(
    friendly_name="Support Center",
    event_callback_url="https://yourapp.com/taskrouter-events"
)

workspace_sid = workspace.sid  # WSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(workspace_sid)

Node.js

const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const workspace = await client.taskrouter.v1.workspaces.create({
    friendlyName: "Support Center",
    eventCallbackUrl: "https://yourapp.com/taskrouter-events",
});

const workspaceSid = workspace.sid;

Step 2 — Create Activities (agent states)

Python

# Available — worker can receive tasks
available = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="Available", available=True
)

# Offline — worker cannot receive tasks
offline = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="Offline", available=False
)

# On a task — worker is busy
on_task = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="On Task", available=False
)

Step 3 — Create Workers (agents)

Security: Always use json.dumps() (Python) or JSON.stringify() (Node.js) to construct attribute payloads. String interpolation is vulnerable to JSON injection.

Python

worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(
    friendly_name="Alice",
    attributes='{"skills": ["billing", "technical"], "languages": ["en", "es"], "department": "support"}'
)

Node.js

const worker = await client.taskrouter.v1.workspaces(workspaceSid).workers.create({
    friendlyName: "Alice",
    attributes: JSON.stringify({
        skills: ["billing", "technical"],
        languages: ["en", "es"],
        department: "support",
    }),
});

Step 4 — Create Task Queues

Python

# Billing queue — matches workers with "billing" skill
billing_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(
    friendly_name="Billing",
    target_workers='skills HAS "billing"'
)

# Technical queue
tech_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(
    friendly_name="Technical",
    target_workers='skills HAS "technical"'
)

# Catch-all queue
default_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(
    friendly_name="Default",
    target_workers='1==1'  # matches all workers
)

Step 5 — Create a Workflow (routing rules)

Python

import json

workflow_config = {
    "task_routing": {
        "filters": [
            {
                "filter_friendly_name": "Billing",
                "expression": "department == 'billing'",
                "targets": [
                    {"queue": billing_queue.sid, "timeout": 120}
                ]
            },
            {
                "filter_friendly_name": "Technical",
                "expression": "department == 'technical'",
                "targets": [
                    {"queue": tech_queue.sid, "timeout": 120}
                ]
            }
        ],
        "default_filter": {
            "queue": default_queue.sid
        }
    }
}

workflow = client.taskrouter.v1.workspaces(workspace_sid).workflows.create(
    friendly_name="Support Routing",
    configuration=json.dumps(workflow_config),
    assignment_callback_url="https://yourapp.com/assignment"
)

Step 6 — Create a Task (from an incoming call)

Python

task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(
    attributes='{"department": "billing", "caller": "+15558675310", "priority": 1}',
    workflow_sid=workflow.sid
)

Step 7 — Handle the Assignment Callback

When TaskRouter finds a matching worker, it POSTs to your assignment_callback_url:

Python (Flask)

@app.route("/assignment", methods=["POST"])
def assignment():
    task_sid = request.form["TaskSid"]
    worker_sid = request.form["WorkerSid"]
    reservation_sid = request.form["ReservationSid"]

    # Option A: Dequeue to the worker's phone
    return jsonify({
        "instruction": "dequeue",
        "from": "+15551234567",  # your Twilio number
        "post_work_activity_sid": available_activity_sid
    })

    # Option B: Conference the caller and agent
    # return jsonify({
    #     "instruction": "conference",
    #     "from": "+15551234567",
    #     "post_work_activity_sid": available_activity_sid
    # })

Node.js (Express)

app.post("/assignment", (req, res) => {
    res.json({
        instruction: "dequeue",
        from: "+15551234567",
        post_work_activity_sid: availableActivitySid,
    });
});

---

Key Patterns

Skills-Based Routing

Match tasks to workers based on attributes:

Worker expressionMatches
skills HAS "billing"Workers whose skills array contains "billing"
languages HAS "es"Spanish-speaking workers
department == "support"Workers in support department
experience > 5Workers with 5+ years experience
skills HAS "billing" AND languages HAS "es"Spanish-speaking billing agents

Priority Routing

Tasks with higher priority are assigned first:

# VIP customer — priority 10 (higher = first)
task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(
    attributes='{"department": "billing", "priority": 10, "vip": true}',
    workflow_sid=workflow.sid,
    priority=10
)

AI Agent Escalation

When an AI agent (via TAC) escalates to a human, create a TaskRouter task with the AI's context:

# From your escalation webhook handler
def handle_escalation(escalation_data):
    task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(
        attributes=json.dumps({
            "department": escalation_data["reason_code"],
            "conversation_id": escalation_data["conversation_id"],
            "profile_id": escalation_data["profile_id"],
            "ai_summary": escalation_data["summary"],
            "priority": 5
        }),
        workflow_sid=workflow.sid
    )

The human agent receives the AI's conversation summary and customer profile.

Workflow with Timeout Escalation

Route to specialized queue first, then overflow to general:

workflow_config = {
    "task_routing": {
        "filters": [
            {
                "filter_friendly_name": "Billing Specialist First",
                "expression": "department == 'billing'",
                "targets": [
                    {"queue": billing_queue.sid, "timeout": 60},      # Try billing queue for 60s
                    {"queue": default_queue.sid, "timeout": 120}      # Overflow to general
                ]
            }
        ],
        "default_filter": {
            "queue": default_queue.sid
        }
    }
}

Worker Activity Management

# Set worker to available
client.taskrouter.v1.workspaces(workspace_sid) \
    .workers(worker_sid) \
    .update(activity_sid=available_activity_sid)

# Get real-time worker statistics
stats = client.taskrouter.v1.workspaces(workspace_sid) \
    .workers \
    .statistics() \
    .fetch()

print(f"Available: {stats.realtime['total_available_workers']}")

---

Scale Guidance

AgentsArchitectureNotes
< 10Single workflow, one queue per skillNo Flex needed — agents use phone
10-50Multi-queue workflows, skills-based routingFlex recommended for desktop
50+Multi-tier workflows, priority routing, real-time monitoringFull Flex + supervisor tools

---

Gotchas

1. Hyphens in Attribute Names Break Silently

# WRONG — hyphens in attribute keys break workflow expressions
worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(
    friendly_name="Alice",
    attributes='{"skill-level": 5}'  # hyphen breaks expression evaluation
)

# RIGHT — use underscores or camelCase
worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(
    friendly_name="Alice",
    attributes='{"skill_level": 5}'
)

No error — the expression silently fails to match.

2. HAS Operator on Non-Array Attributes

# WRONG — "billing" is a string, not an array. HAS silently matches nothing.
target_workers = 'department HAS "billing"'

# RIGHT — use == for string attributes
target_workers = 'department == "billing"'

# RIGHT — use HAS only for arrays
target_workers = 'skills HAS "billing"'  # skills: ["billing", "technical"]

Tasks sit in queue forever with no error.

3. Reservation Timeout Cascade

When a reservation times out: 1. Worker moves to the timeout Activity (often "Offline") 2. Fewer workers available → other reservations also time out 3. Positive feedback loop → entire queue backs up

Fix: Set the timeout Activity to a short-duration state, not "Offline". Or implement a reservation timeout handler that keeps the worker available:

@app.route("/taskrouter-events", methods=["POST"])
def taskrouter_event():
    event_type = request.form["EventType"]
    if event_type == "reservation.timeout":
        worker_sid = request.form["WorkerSid"]
        # Keep worker available instead of moving to offline
        client.taskrouter.v1.workspaces(workspace_sid) \
            .workers(worker_sid) \
            .update(activity_sid=available_activity_sid)
    return "", 200

4. Activity Available Flag

Updating an Activity's available flag returns 200 OK but may not change the value if workers are currently in that activity. Create new activities instead of modifying existing ones.

---

CANNOT

  • Hyphens in attribute names break expressionsskill-level is treated as subtraction (skill minus level). Error 20001. Always use underscores: skill_level.
  • `HAS` on non-array silently matches nothingdepartment HAS "billing" on a string attribute is accepted at creation but never matches. Tasks sit in queue forever with no error.
  • Expression validation is syntactic only — Queue creation validates parse but NOT worker matching. Semantically wrong expressions create successfully with zero matching workers.
  • Activity `available` flag is silently immutable — Updating returns 200 OK but does not change the value. Must delete and recreate the Activity.
  • `multiTaskEnabled` cannot be reverted to false — Once enabled on a Workspace, cannot be disabled. One-way door.
  • Reservation timeout moves worker to timeout Activity — Worker automatically moved to Offline. Must manually set back. This cascades: fewer available workers → more timeouts → queue collapse. See Gotcha #3.
  • Workflow target timeout auto-cancels tasks — When all targets exhaust timeouts, task is canceled. Always include a default_filter as catch-all.
  • Worker `friendlyName` is case-insensitive unique — "alice" collides with "Alice".
  • `workflowSid` is required for task creation — API does not auto-select a default Workflow.
  • Cannot update task status and attributes in same request — Must be two separate API calls.
  • Assignment callback must respond in 5 seconds — If both primary and fallback URLs fail, reservation is canceled.
  • Tasks auto-cancel after 1,000 rejections — If a task cycles through 1,000 reservation rejections, it is automatically canceled.
  • `page` query param not supported — Use PageToken for pagination. page returns error 40153.
  • Cannot use malformed JSON in worker attributes — Silently breaks matching with no error
  • Cannot use regex in workflow expressions — Only supports ==, !=, <, >, HAS, IN, CONTAINS, AND, OR, NOT
  • Cannot exceed 50,000 Workers per Workspace — Hard limit
  • Cannot exceed 250 Task Queues per Workspace — Hard limit
  • Cannot delay reservation callback response beyond 15 seconds — Timeout results in reservation failure

---

Next Steps

  • Conference for transfers: twilio-conference-calls
  • Call recording: twilio-call-recordings
  • AI agent voice integration: twilio-voice-conversation-relay
  • Voice IVR before routing: twilio-voice-twiml

Related skills

FAQ

What does twilio-taskrouter-routing produce?

A TaskRouter workspace with Workers, Task Queues, Workflows, and assignment callback handlers for routed tasks.

When should I use twilio-taskrouter-routing?

When building skills-based contact center routing, support queues, or AI agent escalation to human agents.

Is twilio-taskrouter-routing safe to install?

Review the Security Audits panel on this page before installing in production.

Backend & APIsbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.