[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-twilio-twilio-taskrouter-routing":3,"mdc-d7ihmn-key":33,"related-org-twilio-twilio-taskrouter-routing":2801,"related-repo-twilio-twilio-taskrouter-routing":2979},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":31,"mdContent":32},"twilio-taskrouter-routing","route tasks using Twilio TaskRouter","Route tasks to agents using Twilio TaskRouter. Covers Workers, Task Queues, Workflows, Reservations, skills-based routing, and common gotchas (hyphen attributes, HAS operator, reservation cascade). Use this skill for any multi-agent contact center, support queue, or AI agent escalation routing.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"twilio","Twilio","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Ftwilio.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Operations","operations","tag",{"name":17,"slug":18,"type":15},"Automation","automation",{"name":20,"slug":21,"type":15},"Workflow Automation","workflow-automation",{"name":9,"slug":8,"type":15},25,"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Fai","2026-07-17T06:04:11.836766",null,7,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":26},[],"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Fai\u002Ftree\u002FHEAD\u002Fskills\u002Ftwilio\u002Ftwilio-taskrouter-routing","---\nname: twilio-taskrouter-routing\ndescription: >\n  Route tasks to agents using Twilio TaskRouter. Covers Workers, Task\n  Queues, Workflows, Reservations, skills-based routing, and common\n  gotchas (hyphen attributes, HAS operator, reservation cascade). Use this\n  skill for any multi-agent contact center, support queue, or AI agent\n  escalation routing.\n---\n\n## Overview\n\nTaskRouter 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.\n\n```\nIncoming Task → Workflow (routing rules) → Task Queue (skill match) → Worker (agent)\n                                                                        ↓\n                                                                   Reservation\n                                                                   (accept\u002Freject)\n```\n\n**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.\n\n---\n\n## Prerequisites\n\n- Twilio account — see `twilio-account-setup`\n- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`\n- SDK: `pip install twilio` \u002F `npm install twilio`\n- For voice routing: a Twilio phone number with webhook configured — see `twilio-voice-twiml`\n- For AI escalation: ConversationRelay with escalation tools — see `twilio-voice-conversation-relay`\n\n---\n\n## Quickstart\n\n**Step 1 — Create a Workspace**\n\nA Workspace is the top-level container for all TaskRouter resources.\n\n**Python**\n```python\nimport os\nfrom twilio.rest import Client\n\nclient = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n\nworkspace = client.taskrouter.v1.workspaces.create(\n    friendly_name=\"Support Center\",\n    event_callback_url=\"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\"\n)\n\nworkspace_sid = workspace.sid  # WSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nprint(workspace_sid)\n```\n\n**Node.js**\n```node\nconst twilio = require(\"twilio\");\nconst client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);\n\nconst workspace = await client.taskrouter.v1.workspaces.create({\n    friendlyName: \"Support Center\",\n    eventCallbackUrl: \"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\",\n});\n\nconst workspaceSid = workspace.sid;\n```\n\n**Step 2 — Create Activities (agent states)**\n\n**Python**\n```python\n# Available — worker can receive tasks\navailable = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"Available\", available=True\n)\n\n# Offline — worker cannot receive tasks\noffline = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"Offline\", available=False\n)\n\n# On a task — worker is busy\non_task = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"On Task\", available=False\n)\n```\n\n**Step 3 — Create Workers (agents)**\n\n> **Security:** Always use `json.dumps()` (Python) or `JSON.stringify()` (Node.js) to construct attribute payloads. String interpolation is vulnerable to JSON injection.\n\n**Python**\n```python\nworker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skills\": [\"billing\", \"technical\"], \"languages\": [\"en\", \"es\"], \"department\": \"support\"}'\n)\n```\n\n**Node.js**\n```node\nconst worker = await client.taskrouter.v1.workspaces(workspaceSid).workers.create({\n    friendlyName: \"Alice\",\n    attributes: JSON.stringify({\n        skills: [\"billing\", \"technical\"],\n        languages: [\"en\", \"es\"],\n        department: \"support\",\n    }),\n});\n```\n\n**Step 4 — Create Task Queues**\n\n**Python**\n```python\n# Billing queue — matches workers with \"billing\" skill\nbilling_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Billing\",\n    target_workers='skills HAS \"billing\"'\n)\n\n# Technical queue\ntech_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Technical\",\n    target_workers='skills HAS \"technical\"'\n)\n\n# Catch-all queue\ndefault_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Default\",\n    target_workers='1==1'  # matches all workers\n)\n```\n\n**Step 5 — Create a Workflow (routing rules)**\n\n**Python**\n```python\nimport json\n\nworkflow_config = {\n    \"task_routing\": {\n        \"filters\": [\n            {\n                \"filter_friendly_name\": \"Billing\",\n                \"expression\": \"department == 'billing'\",\n                \"targets\": [\n                    {\"queue\": billing_queue.sid, \"timeout\": 120}\n                ]\n            },\n            {\n                \"filter_friendly_name\": \"Technical\",\n                \"expression\": \"department == 'technical'\",\n                \"targets\": [\n                    {\"queue\": tech_queue.sid, \"timeout\": 120}\n                ]\n            }\n        ],\n        \"default_filter\": {\n            \"queue\": default_queue.sid\n        }\n    }\n}\n\nworkflow = client.taskrouter.v1.workspaces(workspace_sid).workflows.create(\n    friendly_name=\"Support Routing\",\n    configuration=json.dumps(workflow_config),\n    assignment_callback_url=\"https:\u002F\u002Fyourapp.com\u002Fassignment\"\n)\n```\n\n**Step 6 — Create a Task (from an incoming call)**\n\n**Python**\n```python\ntask = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n    attributes='{\"department\": \"billing\", \"caller\": \"+15558675310\", \"priority\": 1}',\n    workflow_sid=workflow.sid\n)\n```\n\n**Step 7 — Handle the Assignment Callback**\n\nWhen TaskRouter finds a matching worker, it POSTs to your `assignment_callback_url`:\n\n**Python (Flask)**\n```python\n@app.route(\"\u002Fassignment\", methods=[\"POST\"])\ndef assignment():\n    task_sid = request.form[\"TaskSid\"]\n    worker_sid = request.form[\"WorkerSid\"]\n    reservation_sid = request.form[\"ReservationSid\"]\n\n    # Option A: Dequeue to the worker's phone\n    return jsonify({\n        \"instruction\": \"dequeue\",\n        \"from\": \"+15551234567\",  # your Twilio number\n        \"post_work_activity_sid\": available_activity_sid\n    })\n\n    # Option B: Conference the caller and agent\n    # return jsonify({\n    #     \"instruction\": \"conference\",\n    #     \"from\": \"+15551234567\",\n    #     \"post_work_activity_sid\": available_activity_sid\n    # })\n```\n\n**Node.js (Express)**\n```node\napp.post(\"\u002Fassignment\", (req, res) => {\n    res.json({\n        instruction: \"dequeue\",\n        from: \"+15551234567\",\n        post_work_activity_sid: availableActivitySid,\n    });\n});\n```\n\n---\n\n## Key Patterns\n\n### Skills-Based Routing\n\nMatch tasks to workers based on attributes:\n\n| Worker expression | Matches |\n|-------------------|---------|\n| `skills HAS \"billing\"` | Workers whose `skills` array contains \"billing\" |\n| `languages HAS \"es\"` | Spanish-speaking workers |\n| `department == \"support\"` | Workers in support department |\n| `experience > 5` | Workers with 5+ years experience |\n| `skills HAS \"billing\" AND languages HAS \"es\"` | Spanish-speaking billing agents |\n\n### Priority Routing\n\nTasks with higher priority are assigned first:\n\n```python\n# VIP customer — priority 10 (higher = first)\ntask = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n    attributes='{\"department\": \"billing\", \"priority\": 10, \"vip\": true}',\n    workflow_sid=workflow.sid,\n    priority=10\n)\n```\n\n### AI Agent Escalation\n\nWhen an AI agent (via TAC) escalates to a human, create a TaskRouter task with the AI's context:\n\n```python\n# From your escalation webhook handler\ndef handle_escalation(escalation_data):\n    task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n        attributes=json.dumps({\n            \"department\": escalation_data[\"reason_code\"],\n            \"conversation_id\": escalation_data[\"conversation_id\"],\n            \"profile_id\": escalation_data[\"profile_id\"],\n            \"ai_summary\": escalation_data[\"summary\"],\n            \"priority\": 5\n        }),\n        workflow_sid=workflow.sid\n    )\n```\n\nThe human agent receives the AI's conversation summary and customer profile.\n\n### Workflow with Timeout Escalation\n\nRoute to specialized queue first, then overflow to general:\n\n```python\nworkflow_config = {\n    \"task_routing\": {\n        \"filters\": [\n            {\n                \"filter_friendly_name\": \"Billing Specialist First\",\n                \"expression\": \"department == 'billing'\",\n                \"targets\": [\n                    {\"queue\": billing_queue.sid, \"timeout\": 60},      # Try billing queue for 60s\n                    {\"queue\": default_queue.sid, \"timeout\": 120}      # Overflow to general\n                ]\n            }\n        ],\n        \"default_filter\": {\n            \"queue\": default_queue.sid\n        }\n    }\n}\n```\n\n### Worker Activity Management\n\n```python\n# Set worker to available\nclient.taskrouter.v1.workspaces(workspace_sid) \\\n    .workers(worker_sid) \\\n    .update(activity_sid=available_activity_sid)\n\n# Get real-time worker statistics\nstats = client.taskrouter.v1.workspaces(workspace_sid) \\\n    .workers \\\n    .statistics() \\\n    .fetch()\n\nprint(f\"Available: {stats.realtime['total_available_workers']}\")\n```\n\n---\n\n## Scale Guidance\n\n| Agents | Architecture | Notes |\n|--------|-------------|-------|\n| \u003C 10 | Single workflow, one queue per skill | No Flex needed — agents use phone |\n| 10-50 | Multi-queue workflows, skills-based routing | Flex recommended for desktop |\n| 50+ | Multi-tier workflows, priority routing, real-time monitoring | Full Flex + supervisor tools |\n\n---\n\n## Gotchas\n\n### 1. Hyphens in Attribute Names Break Silently\n\n```python\n# WRONG — hyphens in attribute keys break workflow expressions\nworker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skill-level\": 5}'  # hyphen breaks expression evaluation\n)\n\n# RIGHT — use underscores or camelCase\nworker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skill_level\": 5}'\n)\n```\n\nNo error — the expression silently fails to match.\n\n### 2. HAS Operator on Non-Array Attributes\n\n```python\n# WRONG — \"billing\" is a string, not an array. HAS silently matches nothing.\ntarget_workers = 'department HAS \"billing\"'\n\n# RIGHT — use == for string attributes\ntarget_workers = 'department == \"billing\"'\n\n# RIGHT — use HAS only for arrays\ntarget_workers = 'skills HAS \"billing\"'  # skills: [\"billing\", \"technical\"]\n```\n\nTasks sit in queue forever with no error.\n\n### 3. Reservation Timeout Cascade\n\nWhen a reservation times out:\n1. Worker moves to the timeout Activity (often \"Offline\")\n2. Fewer workers available → other reservations also time out\n3. Positive feedback loop → entire queue backs up\n\n**Fix:** Set the timeout Activity to a short-duration state, not \"Offline\". Or implement a reservation timeout handler that keeps the worker available:\n\n```python\n@app.route(\"\u002Ftaskrouter-events\", methods=[\"POST\"])\ndef taskrouter_event():\n    event_type = request.form[\"EventType\"]\n    if event_type == \"reservation.timeout\":\n        worker_sid = request.form[\"WorkerSid\"]\n        # Keep worker available instead of moving to offline\n        client.taskrouter.v1.workspaces(workspace_sid) \\\n            .workers(worker_sid) \\\n            .update(activity_sid=available_activity_sid)\n    return \"\", 200\n```\n\n### 4. Activity Available Flag\n\nUpdating 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.\n\n---\n\n## CANNOT\n\n- **Hyphens in attribute names break expressions** — `skill-level` is treated as subtraction (`skill` minus `level`). Error 20001. Always use underscores: `skill_level`.\n- **`HAS` on non-array silently matches nothing** — `department HAS \"billing\"` on a string attribute is accepted at creation but never matches. Tasks sit in queue forever with no error.\n- **Expression validation is syntactic only** — Queue creation validates parse but NOT worker matching. Semantically wrong expressions create successfully with zero matching workers.\n- **Activity `available` flag is silently immutable** — Updating returns 200 OK but does not change the value. Must delete and recreate the Activity.\n- **`multiTaskEnabled` cannot be reverted to false** — Once enabled on a Workspace, cannot be disabled. One-way door.\n- **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.\n- **Workflow target timeout auto-cancels tasks** — When all targets exhaust timeouts, task is canceled. Always include a `default_filter` as catch-all.\n- **Worker `friendlyName` is case-insensitive unique** — \"alice\" collides with \"Alice\".\n- **`workflowSid` is required for task creation** — API does not auto-select a default Workflow.\n- **Cannot update task status and attributes in same request** — Must be two separate API calls.\n- **Assignment callback must respond in 5 seconds** — If both primary and fallback URLs fail, reservation is canceled.\n- **Tasks auto-cancel after 1,000 rejections** — If a task cycles through 1,000 reservation rejections, it is automatically canceled.\n- **`page` query param not supported** — Use `PageToken` for pagination. `page` returns error 40153.\n- **Cannot use malformed JSON in worker attributes** — Silently breaks matching with no error\n- **Cannot use regex in workflow expressions** — Only supports ==, !=, \u003C, >, HAS, IN, CONTAINS, AND, OR, NOT\n- **Cannot exceed 50,000 Workers per Workspace** — Hard limit\n- **Cannot exceed 250 Task Queues per Workspace** — Hard limit\n- **Cannot delay reservation callback response beyond 15 seconds** — Timeout results in reservation failure\n\n---\n\n## Next Steps\n\n- **Conference for transfers:** `twilio-conference-calls`\n- **Call recording:** `twilio-call-recordings`\n- **AI agent voice integration:** `twilio-voice-conversation-relay`\n- **Voice IVR before routing:** `twilio-voice-twiml`\n",{"data":34,"body":35},{"name":4,"description":6},{"type":36,"children":37},"root",[38,47,53,66,77,81,87,169,172,178,186,191,199,316,324,403,411,418,534,542,572,579,617,624,694,702,709,850,858,865,1127,1135,1142,1180,1188,1201,1209,1366,1374,1436,1439,1445,1452,1457,1578,1584,1589,1642,1648,1653,1756,1761,1767,1772,1901,1907,2008,2011,2017,2098,2101,2107,2113,2201,2206,2212,2281,2286,2292,2297,2316,2326,2413,2419,2432,2435,2441,2724,2727,2733,2795],{"type":39,"tag":40,"props":41,"children":43},"element","h2",{"id":42},"overview",[44],{"type":45,"value":46},"text","Overview",{"type":39,"tag":48,"props":49,"children":50},"p",{},[51],{"type":45,"value":52},"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.",{"type":39,"tag":54,"props":55,"children":59},"pre",{"className":56,"code":58,"language":45},[57],"language-text","Incoming Task → Workflow (routing rules) → Task Queue (skill match) → Worker (agent)\n                                                                        ↓\n                                                                   Reservation\n                                                                   (accept\u002Freject)\n",[60],{"type":39,"tag":61,"props":62,"children":64},"code",{"__ignoreMap":63},"",[65],{"type":45,"value":58},{"type":39,"tag":48,"props":67,"children":68},{},[69,75],{"type":39,"tag":70,"props":71,"children":72},"strong",{},[73],{"type":45,"value":74},"Common mistake:",{"type":45,"value":76}," Developers reinvent TaskRouter in custom Node.js — don't. If you're building skills-based routing, queue management, or agent assignment, use TaskRouter.",{"type":39,"tag":78,"props":79,"children":80},"hr",{},[],{"type":39,"tag":40,"props":82,"children":84},{"id":83},"prerequisites",[85],{"type":45,"value":86},"Prerequisites",{"type":39,"tag":88,"props":89,"children":90},"ul",{},[91,103,128,147,158],{"type":39,"tag":92,"props":93,"children":94},"li",{},[95,97],{"type":45,"value":96},"Twilio account — see ",{"type":39,"tag":61,"props":98,"children":100},{"className":99},[],[101],{"type":45,"value":102},"twilio-account-setup",{"type":39,"tag":92,"props":104,"children":105},{},[106,112,114,120,122],{"type":39,"tag":61,"props":107,"children":109},{"className":108},[],[110],{"type":45,"value":111},"TWILIO_ACCOUNT_SID",{"type":45,"value":113}," and ",{"type":39,"tag":61,"props":115,"children":117},{"className":116},[],[118],{"type":45,"value":119},"TWILIO_AUTH_TOKEN",{"type":45,"value":121}," — see ",{"type":39,"tag":61,"props":123,"children":125},{"className":124},[],[126],{"type":45,"value":127},"twilio-iam-auth-setup",{"type":39,"tag":92,"props":129,"children":130},{},[131,133,139,141],{"type":45,"value":132},"SDK: ",{"type":39,"tag":61,"props":134,"children":136},{"className":135},[],[137],{"type":45,"value":138},"pip install twilio",{"type":45,"value":140}," \u002F ",{"type":39,"tag":61,"props":142,"children":144},{"className":143},[],[145],{"type":45,"value":146},"npm install twilio",{"type":39,"tag":92,"props":148,"children":149},{},[150,152],{"type":45,"value":151},"For voice routing: a Twilio phone number with webhook configured — see ",{"type":39,"tag":61,"props":153,"children":155},{"className":154},[],[156],{"type":45,"value":157},"twilio-voice-twiml",{"type":39,"tag":92,"props":159,"children":160},{},[161,163],{"type":45,"value":162},"For AI escalation: ConversationRelay with escalation tools — see ",{"type":39,"tag":61,"props":164,"children":166},{"className":165},[],[167],{"type":45,"value":168},"twilio-voice-conversation-relay",{"type":39,"tag":78,"props":170,"children":171},{},[],{"type":39,"tag":40,"props":173,"children":175},{"id":174},"quickstart",[176],{"type":45,"value":177},"Quickstart",{"type":39,"tag":48,"props":179,"children":180},{},[181],{"type":39,"tag":70,"props":182,"children":183},{},[184],{"type":45,"value":185},"Step 1 — Create a Workspace",{"type":39,"tag":48,"props":187,"children":188},{},[189],{"type":45,"value":190},"A Workspace is the top-level container for all TaskRouter resources.",{"type":39,"tag":48,"props":192,"children":193},{},[194],{"type":39,"tag":70,"props":195,"children":196},{},[197],{"type":45,"value":198},"Python",{"type":39,"tag":54,"props":200,"children":204},{"className":201,"code":202,"language":203,"meta":63,"style":63},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import os\nfrom twilio.rest import Client\n\nclient = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n\nworkspace = client.taskrouter.v1.workspaces.create(\n    friendly_name=\"Support Center\",\n    event_callback_url=\"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\"\n)\n\nworkspace_sid = workspace.sid  # WSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nprint(workspace_sid)\n","python",[205],{"type":39,"tag":61,"props":206,"children":207},{"__ignoreMap":63},[208,219,228,238,247,255,264,272,281,290,298,307],{"type":39,"tag":209,"props":210,"children":213},"span",{"class":211,"line":212},"line",1,[214],{"type":39,"tag":209,"props":215,"children":216},{},[217],{"type":45,"value":218},"import os\n",{"type":39,"tag":209,"props":220,"children":222},{"class":211,"line":221},2,[223],{"type":39,"tag":209,"props":224,"children":225},{},[226],{"type":45,"value":227},"from twilio.rest import Client\n",{"type":39,"tag":209,"props":229,"children":231},{"class":211,"line":230},3,[232],{"type":39,"tag":209,"props":233,"children":235},{"emptyLinePlaceholder":234},true,[236],{"type":45,"value":237},"\n",{"type":39,"tag":209,"props":239,"children":241},{"class":211,"line":240},4,[242],{"type":39,"tag":209,"props":243,"children":244},{},[245],{"type":45,"value":246},"client = Client(os.environ[\"TWILIO_ACCOUNT_SID\"], os.environ[\"TWILIO_AUTH_TOKEN\"])\n",{"type":39,"tag":209,"props":248,"children":250},{"class":211,"line":249},5,[251],{"type":39,"tag":209,"props":252,"children":253},{"emptyLinePlaceholder":234},[254],{"type":45,"value":237},{"type":39,"tag":209,"props":256,"children":258},{"class":211,"line":257},6,[259],{"type":39,"tag":209,"props":260,"children":261},{},[262],{"type":45,"value":263},"workspace = client.taskrouter.v1.workspaces.create(\n",{"type":39,"tag":209,"props":265,"children":266},{"class":211,"line":27},[267],{"type":39,"tag":209,"props":268,"children":269},{},[270],{"type":45,"value":271},"    friendly_name=\"Support Center\",\n",{"type":39,"tag":209,"props":273,"children":275},{"class":211,"line":274},8,[276],{"type":39,"tag":209,"props":277,"children":278},{},[279],{"type":45,"value":280},"    event_callback_url=\"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\"\n",{"type":39,"tag":209,"props":282,"children":284},{"class":211,"line":283},9,[285],{"type":39,"tag":209,"props":286,"children":287},{},[288],{"type":45,"value":289},")\n",{"type":39,"tag":209,"props":291,"children":293},{"class":211,"line":292},10,[294],{"type":39,"tag":209,"props":295,"children":296},{"emptyLinePlaceholder":234},[297],{"type":45,"value":237},{"type":39,"tag":209,"props":299,"children":301},{"class":211,"line":300},11,[302],{"type":39,"tag":209,"props":303,"children":304},{},[305],{"type":45,"value":306},"workspace_sid = workspace.sid  # WSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n",{"type":39,"tag":209,"props":308,"children":310},{"class":211,"line":309},12,[311],{"type":39,"tag":209,"props":312,"children":313},{},[314],{"type":45,"value":315},"print(workspace_sid)\n",{"type":39,"tag":48,"props":317,"children":318},{},[319],{"type":39,"tag":70,"props":320,"children":321},{},[322],{"type":45,"value":323},"Node.js",{"type":39,"tag":54,"props":325,"children":329},{"className":326,"code":327,"language":328,"meta":63,"style":63},"language-node shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const twilio = require(\"twilio\");\nconst client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);\n\nconst workspace = await client.taskrouter.v1.workspaces.create({\n    friendlyName: \"Support Center\",\n    eventCallbackUrl: \"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\",\n});\n\nconst workspaceSid = workspace.sid;\n","node",[330],{"type":39,"tag":61,"props":331,"children":332},{"__ignoreMap":63},[333,341,349,356,364,372,380,388,395],{"type":39,"tag":209,"props":334,"children":335},{"class":211,"line":212},[336],{"type":39,"tag":209,"props":337,"children":338},{},[339],{"type":45,"value":340},"const twilio = require(\"twilio\");\n",{"type":39,"tag":209,"props":342,"children":343},{"class":211,"line":221},[344],{"type":39,"tag":209,"props":345,"children":346},{},[347],{"type":45,"value":348},"const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);\n",{"type":39,"tag":209,"props":350,"children":351},{"class":211,"line":230},[352],{"type":39,"tag":209,"props":353,"children":354},{"emptyLinePlaceholder":234},[355],{"type":45,"value":237},{"type":39,"tag":209,"props":357,"children":358},{"class":211,"line":240},[359],{"type":39,"tag":209,"props":360,"children":361},{},[362],{"type":45,"value":363},"const workspace = await client.taskrouter.v1.workspaces.create({\n",{"type":39,"tag":209,"props":365,"children":366},{"class":211,"line":249},[367],{"type":39,"tag":209,"props":368,"children":369},{},[370],{"type":45,"value":371},"    friendlyName: \"Support Center\",\n",{"type":39,"tag":209,"props":373,"children":374},{"class":211,"line":257},[375],{"type":39,"tag":209,"props":376,"children":377},{},[378],{"type":45,"value":379},"    eventCallbackUrl: \"https:\u002F\u002Fyourapp.com\u002Ftaskrouter-events\",\n",{"type":39,"tag":209,"props":381,"children":382},{"class":211,"line":27},[383],{"type":39,"tag":209,"props":384,"children":385},{},[386],{"type":45,"value":387},"});\n",{"type":39,"tag":209,"props":389,"children":390},{"class":211,"line":274},[391],{"type":39,"tag":209,"props":392,"children":393},{"emptyLinePlaceholder":234},[394],{"type":45,"value":237},{"type":39,"tag":209,"props":396,"children":397},{"class":211,"line":283},[398],{"type":39,"tag":209,"props":399,"children":400},{},[401],{"type":45,"value":402},"const workspaceSid = workspace.sid;\n",{"type":39,"tag":48,"props":404,"children":405},{},[406],{"type":39,"tag":70,"props":407,"children":408},{},[409],{"type":45,"value":410},"Step 2 — Create Activities (agent states)",{"type":39,"tag":48,"props":412,"children":413},{},[414],{"type":39,"tag":70,"props":415,"children":416},{},[417],{"type":45,"value":198},{"type":39,"tag":54,"props":419,"children":421},{"className":201,"code":420,"language":203,"meta":63,"style":63},"# Available — worker can receive tasks\navailable = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"Available\", available=True\n)\n\n# Offline — worker cannot receive tasks\noffline = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"Offline\", available=False\n)\n\n# On a task — worker is busy\non_task = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n    friendly_name=\"On Task\", available=False\n)\n",[422],{"type":39,"tag":61,"props":423,"children":424},{"__ignoreMap":63},[425,433,441,449,456,463,471,479,487,494,501,509,517,526],{"type":39,"tag":209,"props":426,"children":427},{"class":211,"line":212},[428],{"type":39,"tag":209,"props":429,"children":430},{},[431],{"type":45,"value":432},"# Available — worker can receive tasks\n",{"type":39,"tag":209,"props":434,"children":435},{"class":211,"line":221},[436],{"type":39,"tag":209,"props":437,"children":438},{},[439],{"type":45,"value":440},"available = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n",{"type":39,"tag":209,"props":442,"children":443},{"class":211,"line":230},[444],{"type":39,"tag":209,"props":445,"children":446},{},[447],{"type":45,"value":448},"    friendly_name=\"Available\", available=True\n",{"type":39,"tag":209,"props":450,"children":451},{"class":211,"line":240},[452],{"type":39,"tag":209,"props":453,"children":454},{},[455],{"type":45,"value":289},{"type":39,"tag":209,"props":457,"children":458},{"class":211,"line":249},[459],{"type":39,"tag":209,"props":460,"children":461},{"emptyLinePlaceholder":234},[462],{"type":45,"value":237},{"type":39,"tag":209,"props":464,"children":465},{"class":211,"line":257},[466],{"type":39,"tag":209,"props":467,"children":468},{},[469],{"type":45,"value":470},"# Offline — worker cannot receive tasks\n",{"type":39,"tag":209,"props":472,"children":473},{"class":211,"line":27},[474],{"type":39,"tag":209,"props":475,"children":476},{},[477],{"type":45,"value":478},"offline = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n",{"type":39,"tag":209,"props":480,"children":481},{"class":211,"line":274},[482],{"type":39,"tag":209,"props":483,"children":484},{},[485],{"type":45,"value":486},"    friendly_name=\"Offline\", available=False\n",{"type":39,"tag":209,"props":488,"children":489},{"class":211,"line":283},[490],{"type":39,"tag":209,"props":491,"children":492},{},[493],{"type":45,"value":289},{"type":39,"tag":209,"props":495,"children":496},{"class":211,"line":292},[497],{"type":39,"tag":209,"props":498,"children":499},{"emptyLinePlaceholder":234},[500],{"type":45,"value":237},{"type":39,"tag":209,"props":502,"children":503},{"class":211,"line":300},[504],{"type":39,"tag":209,"props":505,"children":506},{},[507],{"type":45,"value":508},"# On a task — worker is busy\n",{"type":39,"tag":209,"props":510,"children":511},{"class":211,"line":309},[512],{"type":39,"tag":209,"props":513,"children":514},{},[515],{"type":45,"value":516},"on_task = client.taskrouter.v1.workspaces(workspace_sid).activities.create(\n",{"type":39,"tag":209,"props":518,"children":520},{"class":211,"line":519},13,[521],{"type":39,"tag":209,"props":522,"children":523},{},[524],{"type":45,"value":525},"    friendly_name=\"On Task\", available=False\n",{"type":39,"tag":209,"props":527,"children":529},{"class":211,"line":528},14,[530],{"type":39,"tag":209,"props":531,"children":532},{},[533],{"type":45,"value":289},{"type":39,"tag":48,"props":535,"children":536},{},[537],{"type":39,"tag":70,"props":538,"children":539},{},[540],{"type":45,"value":541},"Step 3 — Create Workers (agents)",{"type":39,"tag":543,"props":544,"children":545},"blockquote",{},[546],{"type":39,"tag":48,"props":547,"children":548},{},[549,554,556,562,564,570],{"type":39,"tag":70,"props":550,"children":551},{},[552],{"type":45,"value":553},"Security:",{"type":45,"value":555}," Always use ",{"type":39,"tag":61,"props":557,"children":559},{"className":558},[],[560],{"type":45,"value":561},"json.dumps()",{"type":45,"value":563}," (Python) or ",{"type":39,"tag":61,"props":565,"children":567},{"className":566},[],[568],{"type":45,"value":569},"JSON.stringify()",{"type":45,"value":571}," (Node.js) to construct attribute payloads. String interpolation is vulnerable to JSON injection.",{"type":39,"tag":48,"props":573,"children":574},{},[575],{"type":39,"tag":70,"props":576,"children":577},{},[578],{"type":45,"value":198},{"type":39,"tag":54,"props":580,"children":582},{"className":201,"code":581,"language":203,"meta":63,"style":63},"worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skills\": [\"billing\", \"technical\"], \"languages\": [\"en\", \"es\"], \"department\": \"support\"}'\n)\n",[583],{"type":39,"tag":61,"props":584,"children":585},{"__ignoreMap":63},[586,594,602,610],{"type":39,"tag":209,"props":587,"children":588},{"class":211,"line":212},[589],{"type":39,"tag":209,"props":590,"children":591},{},[592],{"type":45,"value":593},"worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n",{"type":39,"tag":209,"props":595,"children":596},{"class":211,"line":221},[597],{"type":39,"tag":209,"props":598,"children":599},{},[600],{"type":45,"value":601},"    friendly_name=\"Alice\",\n",{"type":39,"tag":209,"props":603,"children":604},{"class":211,"line":230},[605],{"type":39,"tag":209,"props":606,"children":607},{},[608],{"type":45,"value":609},"    attributes='{\"skills\": [\"billing\", \"technical\"], \"languages\": [\"en\", \"es\"], \"department\": \"support\"}'\n",{"type":39,"tag":209,"props":611,"children":612},{"class":211,"line":240},[613],{"type":39,"tag":209,"props":614,"children":615},{},[616],{"type":45,"value":289},{"type":39,"tag":48,"props":618,"children":619},{},[620],{"type":39,"tag":70,"props":621,"children":622},{},[623],{"type":45,"value":323},{"type":39,"tag":54,"props":625,"children":627},{"className":326,"code":626,"language":328,"meta":63,"style":63},"const worker = await client.taskrouter.v1.workspaces(workspaceSid).workers.create({\n    friendlyName: \"Alice\",\n    attributes: JSON.stringify({\n        skills: [\"billing\", \"technical\"],\n        languages: [\"en\", \"es\"],\n        department: \"support\",\n    }),\n});\n",[628],{"type":39,"tag":61,"props":629,"children":630},{"__ignoreMap":63},[631,639,647,655,663,671,679,687],{"type":39,"tag":209,"props":632,"children":633},{"class":211,"line":212},[634],{"type":39,"tag":209,"props":635,"children":636},{},[637],{"type":45,"value":638},"const worker = await client.taskrouter.v1.workspaces(workspaceSid).workers.create({\n",{"type":39,"tag":209,"props":640,"children":641},{"class":211,"line":221},[642],{"type":39,"tag":209,"props":643,"children":644},{},[645],{"type":45,"value":646},"    friendlyName: \"Alice\",\n",{"type":39,"tag":209,"props":648,"children":649},{"class":211,"line":230},[650],{"type":39,"tag":209,"props":651,"children":652},{},[653],{"type":45,"value":654},"    attributes: JSON.stringify({\n",{"type":39,"tag":209,"props":656,"children":657},{"class":211,"line":240},[658],{"type":39,"tag":209,"props":659,"children":660},{},[661],{"type":45,"value":662},"        skills: [\"billing\", \"technical\"],\n",{"type":39,"tag":209,"props":664,"children":665},{"class":211,"line":249},[666],{"type":39,"tag":209,"props":667,"children":668},{},[669],{"type":45,"value":670},"        languages: [\"en\", \"es\"],\n",{"type":39,"tag":209,"props":672,"children":673},{"class":211,"line":257},[674],{"type":39,"tag":209,"props":675,"children":676},{},[677],{"type":45,"value":678},"        department: \"support\",\n",{"type":39,"tag":209,"props":680,"children":681},{"class":211,"line":27},[682],{"type":39,"tag":209,"props":683,"children":684},{},[685],{"type":45,"value":686},"    }),\n",{"type":39,"tag":209,"props":688,"children":689},{"class":211,"line":274},[690],{"type":39,"tag":209,"props":691,"children":692},{},[693],{"type":45,"value":387},{"type":39,"tag":48,"props":695,"children":696},{},[697],{"type":39,"tag":70,"props":698,"children":699},{},[700],{"type":45,"value":701},"Step 4 — Create Task Queues",{"type":39,"tag":48,"props":703,"children":704},{},[705],{"type":39,"tag":70,"props":706,"children":707},{},[708],{"type":45,"value":198},{"type":39,"tag":54,"props":710,"children":712},{"className":201,"code":711,"language":203,"meta":63,"style":63},"# Billing queue — matches workers with \"billing\" skill\nbilling_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Billing\",\n    target_workers='skills HAS \"billing\"'\n)\n\n# Technical queue\ntech_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Technical\",\n    target_workers='skills HAS \"technical\"'\n)\n\n# Catch-all queue\ndefault_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n    friendly_name=\"Default\",\n    target_workers='1==1'  # matches all workers\n)\n",[713],{"type":39,"tag":61,"props":714,"children":715},{"__ignoreMap":63},[716,724,732,740,748,755,762,770,778,786,794,801,808,816,824,833,842],{"type":39,"tag":209,"props":717,"children":718},{"class":211,"line":212},[719],{"type":39,"tag":209,"props":720,"children":721},{},[722],{"type":45,"value":723},"# Billing queue — matches workers with \"billing\" skill\n",{"type":39,"tag":209,"props":725,"children":726},{"class":211,"line":221},[727],{"type":39,"tag":209,"props":728,"children":729},{},[730],{"type":45,"value":731},"billing_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n",{"type":39,"tag":209,"props":733,"children":734},{"class":211,"line":230},[735],{"type":39,"tag":209,"props":736,"children":737},{},[738],{"type":45,"value":739},"    friendly_name=\"Billing\",\n",{"type":39,"tag":209,"props":741,"children":742},{"class":211,"line":240},[743],{"type":39,"tag":209,"props":744,"children":745},{},[746],{"type":45,"value":747},"    target_workers='skills HAS \"billing\"'\n",{"type":39,"tag":209,"props":749,"children":750},{"class":211,"line":249},[751],{"type":39,"tag":209,"props":752,"children":753},{},[754],{"type":45,"value":289},{"type":39,"tag":209,"props":756,"children":757},{"class":211,"line":257},[758],{"type":39,"tag":209,"props":759,"children":760},{"emptyLinePlaceholder":234},[761],{"type":45,"value":237},{"type":39,"tag":209,"props":763,"children":764},{"class":211,"line":27},[765],{"type":39,"tag":209,"props":766,"children":767},{},[768],{"type":45,"value":769},"# Technical queue\n",{"type":39,"tag":209,"props":771,"children":772},{"class":211,"line":274},[773],{"type":39,"tag":209,"props":774,"children":775},{},[776],{"type":45,"value":777},"tech_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n",{"type":39,"tag":209,"props":779,"children":780},{"class":211,"line":283},[781],{"type":39,"tag":209,"props":782,"children":783},{},[784],{"type":45,"value":785},"    friendly_name=\"Technical\",\n",{"type":39,"tag":209,"props":787,"children":788},{"class":211,"line":292},[789],{"type":39,"tag":209,"props":790,"children":791},{},[792],{"type":45,"value":793},"    target_workers='skills HAS \"technical\"'\n",{"type":39,"tag":209,"props":795,"children":796},{"class":211,"line":300},[797],{"type":39,"tag":209,"props":798,"children":799},{},[800],{"type":45,"value":289},{"type":39,"tag":209,"props":802,"children":803},{"class":211,"line":309},[804],{"type":39,"tag":209,"props":805,"children":806},{"emptyLinePlaceholder":234},[807],{"type":45,"value":237},{"type":39,"tag":209,"props":809,"children":810},{"class":211,"line":519},[811],{"type":39,"tag":209,"props":812,"children":813},{},[814],{"type":45,"value":815},"# Catch-all queue\n",{"type":39,"tag":209,"props":817,"children":818},{"class":211,"line":528},[819],{"type":39,"tag":209,"props":820,"children":821},{},[822],{"type":45,"value":823},"default_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(\n",{"type":39,"tag":209,"props":825,"children":827},{"class":211,"line":826},15,[828],{"type":39,"tag":209,"props":829,"children":830},{},[831],{"type":45,"value":832},"    friendly_name=\"Default\",\n",{"type":39,"tag":209,"props":834,"children":836},{"class":211,"line":835},16,[837],{"type":39,"tag":209,"props":838,"children":839},{},[840],{"type":45,"value":841},"    target_workers='1==1'  # matches all workers\n",{"type":39,"tag":209,"props":843,"children":845},{"class":211,"line":844},17,[846],{"type":39,"tag":209,"props":847,"children":848},{},[849],{"type":45,"value":289},{"type":39,"tag":48,"props":851,"children":852},{},[853],{"type":39,"tag":70,"props":854,"children":855},{},[856],{"type":45,"value":857},"Step 5 — Create a Workflow (routing rules)",{"type":39,"tag":48,"props":859,"children":860},{},[861],{"type":39,"tag":70,"props":862,"children":863},{},[864],{"type":45,"value":198},{"type":39,"tag":54,"props":866,"children":868},{"className":201,"code":867,"language":203,"meta":63,"style":63},"import json\n\nworkflow_config = {\n    \"task_routing\": {\n        \"filters\": [\n            {\n                \"filter_friendly_name\": \"Billing\",\n                \"expression\": \"department == 'billing'\",\n                \"targets\": [\n                    {\"queue\": billing_queue.sid, \"timeout\": 120}\n                ]\n            },\n            {\n                \"filter_friendly_name\": \"Technical\",\n                \"expression\": \"department == 'technical'\",\n                \"targets\": [\n                    {\"queue\": tech_queue.sid, \"timeout\": 120}\n                ]\n            }\n        ],\n        \"default_filter\": {\n            \"queue\": default_queue.sid\n        }\n    }\n}\n\nworkflow = client.taskrouter.v1.workspaces(workspace_sid).workflows.create(\n    friendly_name=\"Support Routing\",\n    configuration=json.dumps(workflow_config),\n    assignment_callback_url=\"https:\u002F\u002Fyourapp.com\u002Fassignment\"\n)\n",[869],{"type":39,"tag":61,"props":870,"children":871},{"__ignoreMap":63},[872,880,887,895,903,911,919,927,935,943,951,959,967,974,982,990,997,1005,1013,1022,1031,1040,1049,1058,1067,1075,1083,1092,1101,1110,1119],{"type":39,"tag":209,"props":873,"children":874},{"class":211,"line":212},[875],{"type":39,"tag":209,"props":876,"children":877},{},[878],{"type":45,"value":879},"import json\n",{"type":39,"tag":209,"props":881,"children":882},{"class":211,"line":221},[883],{"type":39,"tag":209,"props":884,"children":885},{"emptyLinePlaceholder":234},[886],{"type":45,"value":237},{"type":39,"tag":209,"props":888,"children":889},{"class":211,"line":230},[890],{"type":39,"tag":209,"props":891,"children":892},{},[893],{"type":45,"value":894},"workflow_config = {\n",{"type":39,"tag":209,"props":896,"children":897},{"class":211,"line":240},[898],{"type":39,"tag":209,"props":899,"children":900},{},[901],{"type":45,"value":902},"    \"task_routing\": {\n",{"type":39,"tag":209,"props":904,"children":905},{"class":211,"line":249},[906],{"type":39,"tag":209,"props":907,"children":908},{},[909],{"type":45,"value":910},"        \"filters\": [\n",{"type":39,"tag":209,"props":912,"children":913},{"class":211,"line":257},[914],{"type":39,"tag":209,"props":915,"children":916},{},[917],{"type":45,"value":918},"            {\n",{"type":39,"tag":209,"props":920,"children":921},{"class":211,"line":27},[922],{"type":39,"tag":209,"props":923,"children":924},{},[925],{"type":45,"value":926},"                \"filter_friendly_name\": \"Billing\",\n",{"type":39,"tag":209,"props":928,"children":929},{"class":211,"line":274},[930],{"type":39,"tag":209,"props":931,"children":932},{},[933],{"type":45,"value":934},"                \"expression\": \"department == 'billing'\",\n",{"type":39,"tag":209,"props":936,"children":937},{"class":211,"line":283},[938],{"type":39,"tag":209,"props":939,"children":940},{},[941],{"type":45,"value":942},"                \"targets\": [\n",{"type":39,"tag":209,"props":944,"children":945},{"class":211,"line":292},[946],{"type":39,"tag":209,"props":947,"children":948},{},[949],{"type":45,"value":950},"                    {\"queue\": billing_queue.sid, \"timeout\": 120}\n",{"type":39,"tag":209,"props":952,"children":953},{"class":211,"line":300},[954],{"type":39,"tag":209,"props":955,"children":956},{},[957],{"type":45,"value":958},"                ]\n",{"type":39,"tag":209,"props":960,"children":961},{"class":211,"line":309},[962],{"type":39,"tag":209,"props":963,"children":964},{},[965],{"type":45,"value":966},"            },\n",{"type":39,"tag":209,"props":968,"children":969},{"class":211,"line":519},[970],{"type":39,"tag":209,"props":971,"children":972},{},[973],{"type":45,"value":918},{"type":39,"tag":209,"props":975,"children":976},{"class":211,"line":528},[977],{"type":39,"tag":209,"props":978,"children":979},{},[980],{"type":45,"value":981},"                \"filter_friendly_name\": \"Technical\",\n",{"type":39,"tag":209,"props":983,"children":984},{"class":211,"line":826},[985],{"type":39,"tag":209,"props":986,"children":987},{},[988],{"type":45,"value":989},"                \"expression\": \"department == 'technical'\",\n",{"type":39,"tag":209,"props":991,"children":992},{"class":211,"line":835},[993],{"type":39,"tag":209,"props":994,"children":995},{},[996],{"type":45,"value":942},{"type":39,"tag":209,"props":998,"children":999},{"class":211,"line":844},[1000],{"type":39,"tag":209,"props":1001,"children":1002},{},[1003],{"type":45,"value":1004},"                    {\"queue\": tech_queue.sid, \"timeout\": 120}\n",{"type":39,"tag":209,"props":1006,"children":1008},{"class":211,"line":1007},18,[1009],{"type":39,"tag":209,"props":1010,"children":1011},{},[1012],{"type":45,"value":958},{"type":39,"tag":209,"props":1014,"children":1016},{"class":211,"line":1015},19,[1017],{"type":39,"tag":209,"props":1018,"children":1019},{},[1020],{"type":45,"value":1021},"            }\n",{"type":39,"tag":209,"props":1023,"children":1025},{"class":211,"line":1024},20,[1026],{"type":39,"tag":209,"props":1027,"children":1028},{},[1029],{"type":45,"value":1030},"        ],\n",{"type":39,"tag":209,"props":1032,"children":1034},{"class":211,"line":1033},21,[1035],{"type":39,"tag":209,"props":1036,"children":1037},{},[1038],{"type":45,"value":1039},"        \"default_filter\": {\n",{"type":39,"tag":209,"props":1041,"children":1043},{"class":211,"line":1042},22,[1044],{"type":39,"tag":209,"props":1045,"children":1046},{},[1047],{"type":45,"value":1048},"            \"queue\": default_queue.sid\n",{"type":39,"tag":209,"props":1050,"children":1052},{"class":211,"line":1051},23,[1053],{"type":39,"tag":209,"props":1054,"children":1055},{},[1056],{"type":45,"value":1057},"        }\n",{"type":39,"tag":209,"props":1059,"children":1061},{"class":211,"line":1060},24,[1062],{"type":39,"tag":209,"props":1063,"children":1064},{},[1065],{"type":45,"value":1066},"    }\n",{"type":39,"tag":209,"props":1068,"children":1069},{"class":211,"line":23},[1070],{"type":39,"tag":209,"props":1071,"children":1072},{},[1073],{"type":45,"value":1074},"}\n",{"type":39,"tag":209,"props":1076,"children":1078},{"class":211,"line":1077},26,[1079],{"type":39,"tag":209,"props":1080,"children":1081},{"emptyLinePlaceholder":234},[1082],{"type":45,"value":237},{"type":39,"tag":209,"props":1084,"children":1086},{"class":211,"line":1085},27,[1087],{"type":39,"tag":209,"props":1088,"children":1089},{},[1090],{"type":45,"value":1091},"workflow = client.taskrouter.v1.workspaces(workspace_sid).workflows.create(\n",{"type":39,"tag":209,"props":1093,"children":1095},{"class":211,"line":1094},28,[1096],{"type":39,"tag":209,"props":1097,"children":1098},{},[1099],{"type":45,"value":1100},"    friendly_name=\"Support Routing\",\n",{"type":39,"tag":209,"props":1102,"children":1104},{"class":211,"line":1103},29,[1105],{"type":39,"tag":209,"props":1106,"children":1107},{},[1108],{"type":45,"value":1109},"    configuration=json.dumps(workflow_config),\n",{"type":39,"tag":209,"props":1111,"children":1113},{"class":211,"line":1112},30,[1114],{"type":39,"tag":209,"props":1115,"children":1116},{},[1117],{"type":45,"value":1118},"    assignment_callback_url=\"https:\u002F\u002Fyourapp.com\u002Fassignment\"\n",{"type":39,"tag":209,"props":1120,"children":1122},{"class":211,"line":1121},31,[1123],{"type":39,"tag":209,"props":1124,"children":1125},{},[1126],{"type":45,"value":289},{"type":39,"tag":48,"props":1128,"children":1129},{},[1130],{"type":39,"tag":70,"props":1131,"children":1132},{},[1133],{"type":45,"value":1134},"Step 6 — Create a Task (from an incoming call)",{"type":39,"tag":48,"props":1136,"children":1137},{},[1138],{"type":39,"tag":70,"props":1139,"children":1140},{},[1141],{"type":45,"value":198},{"type":39,"tag":54,"props":1143,"children":1145},{"className":201,"code":1144,"language":203,"meta":63,"style":63},"task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n    attributes='{\"department\": \"billing\", \"caller\": \"+15558675310\", \"priority\": 1}',\n    workflow_sid=workflow.sid\n)\n",[1146],{"type":39,"tag":61,"props":1147,"children":1148},{"__ignoreMap":63},[1149,1157,1165,1173],{"type":39,"tag":209,"props":1150,"children":1151},{"class":211,"line":212},[1152],{"type":39,"tag":209,"props":1153,"children":1154},{},[1155],{"type":45,"value":1156},"task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n",{"type":39,"tag":209,"props":1158,"children":1159},{"class":211,"line":221},[1160],{"type":39,"tag":209,"props":1161,"children":1162},{},[1163],{"type":45,"value":1164},"    attributes='{\"department\": \"billing\", \"caller\": \"+15558675310\", \"priority\": 1}',\n",{"type":39,"tag":209,"props":1166,"children":1167},{"class":211,"line":230},[1168],{"type":39,"tag":209,"props":1169,"children":1170},{},[1171],{"type":45,"value":1172},"    workflow_sid=workflow.sid\n",{"type":39,"tag":209,"props":1174,"children":1175},{"class":211,"line":240},[1176],{"type":39,"tag":209,"props":1177,"children":1178},{},[1179],{"type":45,"value":289},{"type":39,"tag":48,"props":1181,"children":1182},{},[1183],{"type":39,"tag":70,"props":1184,"children":1185},{},[1186],{"type":45,"value":1187},"Step 7 — Handle the Assignment Callback",{"type":39,"tag":48,"props":1189,"children":1190},{},[1191,1193,1199],{"type":45,"value":1192},"When TaskRouter finds a matching worker, it POSTs to your ",{"type":39,"tag":61,"props":1194,"children":1196},{"className":1195},[],[1197],{"type":45,"value":1198},"assignment_callback_url",{"type":45,"value":1200},":",{"type":39,"tag":48,"props":1202,"children":1203},{},[1204],{"type":39,"tag":70,"props":1205,"children":1206},{},[1207],{"type":45,"value":1208},"Python (Flask)",{"type":39,"tag":54,"props":1210,"children":1212},{"className":201,"code":1211,"language":203,"meta":63,"style":63},"@app.route(\"\u002Fassignment\", methods=[\"POST\"])\ndef assignment():\n    task_sid = request.form[\"TaskSid\"]\n    worker_sid = request.form[\"WorkerSid\"]\n    reservation_sid = request.form[\"ReservationSid\"]\n\n    # Option A: Dequeue to the worker's phone\n    return jsonify({\n        \"instruction\": \"dequeue\",\n        \"from\": \"+15551234567\",  # your Twilio number\n        \"post_work_activity_sid\": available_activity_sid\n    })\n\n    # Option B: Conference the caller and agent\n    # return jsonify({\n    #     \"instruction\": \"conference\",\n    #     \"from\": \"+15551234567\",\n    #     \"post_work_activity_sid\": available_activity_sid\n    # })\n",[1213],{"type":39,"tag":61,"props":1214,"children":1215},{"__ignoreMap":63},[1216,1224,1232,1240,1248,1256,1263,1271,1279,1287,1295,1303,1311,1318,1326,1334,1342,1350,1358],{"type":39,"tag":209,"props":1217,"children":1218},{"class":211,"line":212},[1219],{"type":39,"tag":209,"props":1220,"children":1221},{},[1222],{"type":45,"value":1223},"@app.route(\"\u002Fassignment\", methods=[\"POST\"])\n",{"type":39,"tag":209,"props":1225,"children":1226},{"class":211,"line":221},[1227],{"type":39,"tag":209,"props":1228,"children":1229},{},[1230],{"type":45,"value":1231},"def assignment():\n",{"type":39,"tag":209,"props":1233,"children":1234},{"class":211,"line":230},[1235],{"type":39,"tag":209,"props":1236,"children":1237},{},[1238],{"type":45,"value":1239},"    task_sid = request.form[\"TaskSid\"]\n",{"type":39,"tag":209,"props":1241,"children":1242},{"class":211,"line":240},[1243],{"type":39,"tag":209,"props":1244,"children":1245},{},[1246],{"type":45,"value":1247},"    worker_sid = request.form[\"WorkerSid\"]\n",{"type":39,"tag":209,"props":1249,"children":1250},{"class":211,"line":249},[1251],{"type":39,"tag":209,"props":1252,"children":1253},{},[1254],{"type":45,"value":1255},"    reservation_sid = request.form[\"ReservationSid\"]\n",{"type":39,"tag":209,"props":1257,"children":1258},{"class":211,"line":257},[1259],{"type":39,"tag":209,"props":1260,"children":1261},{"emptyLinePlaceholder":234},[1262],{"type":45,"value":237},{"type":39,"tag":209,"props":1264,"children":1265},{"class":211,"line":27},[1266],{"type":39,"tag":209,"props":1267,"children":1268},{},[1269],{"type":45,"value":1270},"    # Option A: Dequeue to the worker's phone\n",{"type":39,"tag":209,"props":1272,"children":1273},{"class":211,"line":274},[1274],{"type":39,"tag":209,"props":1275,"children":1276},{},[1277],{"type":45,"value":1278},"    return jsonify({\n",{"type":39,"tag":209,"props":1280,"children":1281},{"class":211,"line":283},[1282],{"type":39,"tag":209,"props":1283,"children":1284},{},[1285],{"type":45,"value":1286},"        \"instruction\": \"dequeue\",\n",{"type":39,"tag":209,"props":1288,"children":1289},{"class":211,"line":292},[1290],{"type":39,"tag":209,"props":1291,"children":1292},{},[1293],{"type":45,"value":1294},"        \"from\": \"+15551234567\",  # your Twilio number\n",{"type":39,"tag":209,"props":1296,"children":1297},{"class":211,"line":300},[1298],{"type":39,"tag":209,"props":1299,"children":1300},{},[1301],{"type":45,"value":1302},"        \"post_work_activity_sid\": available_activity_sid\n",{"type":39,"tag":209,"props":1304,"children":1305},{"class":211,"line":309},[1306],{"type":39,"tag":209,"props":1307,"children":1308},{},[1309],{"type":45,"value":1310},"    })\n",{"type":39,"tag":209,"props":1312,"children":1313},{"class":211,"line":519},[1314],{"type":39,"tag":209,"props":1315,"children":1316},{"emptyLinePlaceholder":234},[1317],{"type":45,"value":237},{"type":39,"tag":209,"props":1319,"children":1320},{"class":211,"line":528},[1321],{"type":39,"tag":209,"props":1322,"children":1323},{},[1324],{"type":45,"value":1325},"    # Option B: Conference the caller and agent\n",{"type":39,"tag":209,"props":1327,"children":1328},{"class":211,"line":826},[1329],{"type":39,"tag":209,"props":1330,"children":1331},{},[1332],{"type":45,"value":1333},"    # return jsonify({\n",{"type":39,"tag":209,"props":1335,"children":1336},{"class":211,"line":835},[1337],{"type":39,"tag":209,"props":1338,"children":1339},{},[1340],{"type":45,"value":1341},"    #     \"instruction\": \"conference\",\n",{"type":39,"tag":209,"props":1343,"children":1344},{"class":211,"line":844},[1345],{"type":39,"tag":209,"props":1346,"children":1347},{},[1348],{"type":45,"value":1349},"    #     \"from\": \"+15551234567\",\n",{"type":39,"tag":209,"props":1351,"children":1352},{"class":211,"line":1007},[1353],{"type":39,"tag":209,"props":1354,"children":1355},{},[1356],{"type":45,"value":1357},"    #     \"post_work_activity_sid\": available_activity_sid\n",{"type":39,"tag":209,"props":1359,"children":1360},{"class":211,"line":1015},[1361],{"type":39,"tag":209,"props":1362,"children":1363},{},[1364],{"type":45,"value":1365},"    # })\n",{"type":39,"tag":48,"props":1367,"children":1368},{},[1369],{"type":39,"tag":70,"props":1370,"children":1371},{},[1372],{"type":45,"value":1373},"Node.js (Express)",{"type":39,"tag":54,"props":1375,"children":1377},{"className":326,"code":1376,"language":328,"meta":63,"style":63},"app.post(\"\u002Fassignment\", (req, res) => {\n    res.json({\n        instruction: \"dequeue\",\n        from: \"+15551234567\",\n        post_work_activity_sid: availableActivitySid,\n    });\n});\n",[1378],{"type":39,"tag":61,"props":1379,"children":1380},{"__ignoreMap":63},[1381,1389,1397,1405,1413,1421,1429],{"type":39,"tag":209,"props":1382,"children":1383},{"class":211,"line":212},[1384],{"type":39,"tag":209,"props":1385,"children":1386},{},[1387],{"type":45,"value":1388},"app.post(\"\u002Fassignment\", (req, res) => {\n",{"type":39,"tag":209,"props":1390,"children":1391},{"class":211,"line":221},[1392],{"type":39,"tag":209,"props":1393,"children":1394},{},[1395],{"type":45,"value":1396},"    res.json({\n",{"type":39,"tag":209,"props":1398,"children":1399},{"class":211,"line":230},[1400],{"type":39,"tag":209,"props":1401,"children":1402},{},[1403],{"type":45,"value":1404},"        instruction: \"dequeue\",\n",{"type":39,"tag":209,"props":1406,"children":1407},{"class":211,"line":240},[1408],{"type":39,"tag":209,"props":1409,"children":1410},{},[1411],{"type":45,"value":1412},"        from: \"+15551234567\",\n",{"type":39,"tag":209,"props":1414,"children":1415},{"class":211,"line":249},[1416],{"type":39,"tag":209,"props":1417,"children":1418},{},[1419],{"type":45,"value":1420},"        post_work_activity_sid: availableActivitySid,\n",{"type":39,"tag":209,"props":1422,"children":1423},{"class":211,"line":257},[1424],{"type":39,"tag":209,"props":1425,"children":1426},{},[1427],{"type":45,"value":1428},"    });\n",{"type":39,"tag":209,"props":1430,"children":1431},{"class":211,"line":27},[1432],{"type":39,"tag":209,"props":1433,"children":1434},{},[1435],{"type":45,"value":387},{"type":39,"tag":78,"props":1437,"children":1438},{},[],{"type":39,"tag":40,"props":1440,"children":1442},{"id":1441},"key-patterns",[1443],{"type":45,"value":1444},"Key Patterns",{"type":39,"tag":1446,"props":1447,"children":1449},"h3",{"id":1448},"skills-based-routing",[1450],{"type":45,"value":1451},"Skills-Based Routing",{"type":39,"tag":48,"props":1453,"children":1454},{},[1455],{"type":45,"value":1456},"Match tasks to workers based on attributes:",{"type":39,"tag":1458,"props":1459,"children":1460},"table",{},[1461,1480],{"type":39,"tag":1462,"props":1463,"children":1464},"thead",{},[1465],{"type":39,"tag":1466,"props":1467,"children":1468},"tr",{},[1469,1475],{"type":39,"tag":1470,"props":1471,"children":1472},"th",{},[1473],{"type":45,"value":1474},"Worker expression",{"type":39,"tag":1470,"props":1476,"children":1477},{},[1478],{"type":45,"value":1479},"Matches",{"type":39,"tag":1481,"props":1482,"children":1483},"tbody",{},[1484,1510,1527,1544,1561],{"type":39,"tag":1466,"props":1485,"children":1486},{},[1487,1497],{"type":39,"tag":1488,"props":1489,"children":1490},"td",{},[1491],{"type":39,"tag":61,"props":1492,"children":1494},{"className":1493},[],[1495],{"type":45,"value":1496},"skills HAS \"billing\"",{"type":39,"tag":1488,"props":1498,"children":1499},{},[1500,1502,1508],{"type":45,"value":1501},"Workers whose ",{"type":39,"tag":61,"props":1503,"children":1505},{"className":1504},[],[1506],{"type":45,"value":1507},"skills",{"type":45,"value":1509}," array contains \"billing\"",{"type":39,"tag":1466,"props":1511,"children":1512},{},[1513,1522],{"type":39,"tag":1488,"props":1514,"children":1515},{},[1516],{"type":39,"tag":61,"props":1517,"children":1519},{"className":1518},[],[1520],{"type":45,"value":1521},"languages HAS \"es\"",{"type":39,"tag":1488,"props":1523,"children":1524},{},[1525],{"type":45,"value":1526},"Spanish-speaking workers",{"type":39,"tag":1466,"props":1528,"children":1529},{},[1530,1539],{"type":39,"tag":1488,"props":1531,"children":1532},{},[1533],{"type":39,"tag":61,"props":1534,"children":1536},{"className":1535},[],[1537],{"type":45,"value":1538},"department == \"support\"",{"type":39,"tag":1488,"props":1540,"children":1541},{},[1542],{"type":45,"value":1543},"Workers in support department",{"type":39,"tag":1466,"props":1545,"children":1546},{},[1547,1556],{"type":39,"tag":1488,"props":1548,"children":1549},{},[1550],{"type":39,"tag":61,"props":1551,"children":1553},{"className":1552},[],[1554],{"type":45,"value":1555},"experience > 5",{"type":39,"tag":1488,"props":1557,"children":1558},{},[1559],{"type":45,"value":1560},"Workers with 5+ years experience",{"type":39,"tag":1466,"props":1562,"children":1563},{},[1564,1573],{"type":39,"tag":1488,"props":1565,"children":1566},{},[1567],{"type":39,"tag":61,"props":1568,"children":1570},{"className":1569},[],[1571],{"type":45,"value":1572},"skills HAS \"billing\" AND languages HAS \"es\"",{"type":39,"tag":1488,"props":1574,"children":1575},{},[1576],{"type":45,"value":1577},"Spanish-speaking billing agents",{"type":39,"tag":1446,"props":1579,"children":1581},{"id":1580},"priority-routing",[1582],{"type":45,"value":1583},"Priority Routing",{"type":39,"tag":48,"props":1585,"children":1586},{},[1587],{"type":45,"value":1588},"Tasks with higher priority are assigned first:",{"type":39,"tag":54,"props":1590,"children":1592},{"className":201,"code":1591,"language":203,"meta":63,"style":63},"# VIP customer — priority 10 (higher = first)\ntask = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n    attributes='{\"department\": \"billing\", \"priority\": 10, \"vip\": true}',\n    workflow_sid=workflow.sid,\n    priority=10\n)\n",[1593],{"type":39,"tag":61,"props":1594,"children":1595},{"__ignoreMap":63},[1596,1604,1611,1619,1627,1635],{"type":39,"tag":209,"props":1597,"children":1598},{"class":211,"line":212},[1599],{"type":39,"tag":209,"props":1600,"children":1601},{},[1602],{"type":45,"value":1603},"# VIP customer — priority 10 (higher = first)\n",{"type":39,"tag":209,"props":1605,"children":1606},{"class":211,"line":221},[1607],{"type":39,"tag":209,"props":1608,"children":1609},{},[1610],{"type":45,"value":1156},{"type":39,"tag":209,"props":1612,"children":1613},{"class":211,"line":230},[1614],{"type":39,"tag":209,"props":1615,"children":1616},{},[1617],{"type":45,"value":1618},"    attributes='{\"department\": \"billing\", \"priority\": 10, \"vip\": true}',\n",{"type":39,"tag":209,"props":1620,"children":1621},{"class":211,"line":240},[1622],{"type":39,"tag":209,"props":1623,"children":1624},{},[1625],{"type":45,"value":1626},"    workflow_sid=workflow.sid,\n",{"type":39,"tag":209,"props":1628,"children":1629},{"class":211,"line":249},[1630],{"type":39,"tag":209,"props":1631,"children":1632},{},[1633],{"type":45,"value":1634},"    priority=10\n",{"type":39,"tag":209,"props":1636,"children":1637},{"class":211,"line":257},[1638],{"type":39,"tag":209,"props":1639,"children":1640},{},[1641],{"type":45,"value":289},{"type":39,"tag":1446,"props":1643,"children":1645},{"id":1644},"ai-agent-escalation",[1646],{"type":45,"value":1647},"AI Agent Escalation",{"type":39,"tag":48,"props":1649,"children":1650},{},[1651],{"type":45,"value":1652},"When an AI agent (via TAC) escalates to a human, create a TaskRouter task with the AI's context:",{"type":39,"tag":54,"props":1654,"children":1656},{"className":201,"code":1655,"language":203,"meta":63,"style":63},"# From your escalation webhook handler\ndef handle_escalation(escalation_data):\n    task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n        attributes=json.dumps({\n            \"department\": escalation_data[\"reason_code\"],\n            \"conversation_id\": escalation_data[\"conversation_id\"],\n            \"profile_id\": escalation_data[\"profile_id\"],\n            \"ai_summary\": escalation_data[\"summary\"],\n            \"priority\": 5\n        }),\n        workflow_sid=workflow.sid\n    )\n",[1657],{"type":39,"tag":61,"props":1658,"children":1659},{"__ignoreMap":63},[1660,1668,1676,1684,1692,1700,1708,1716,1724,1732,1740,1748],{"type":39,"tag":209,"props":1661,"children":1662},{"class":211,"line":212},[1663],{"type":39,"tag":209,"props":1664,"children":1665},{},[1666],{"type":45,"value":1667},"# From your escalation webhook handler\n",{"type":39,"tag":209,"props":1669,"children":1670},{"class":211,"line":221},[1671],{"type":39,"tag":209,"props":1672,"children":1673},{},[1674],{"type":45,"value":1675},"def handle_escalation(escalation_data):\n",{"type":39,"tag":209,"props":1677,"children":1678},{"class":211,"line":230},[1679],{"type":39,"tag":209,"props":1680,"children":1681},{},[1682],{"type":45,"value":1683},"    task = client.taskrouter.v1.workspaces(workspace_sid).tasks.create(\n",{"type":39,"tag":209,"props":1685,"children":1686},{"class":211,"line":240},[1687],{"type":39,"tag":209,"props":1688,"children":1689},{},[1690],{"type":45,"value":1691},"        attributes=json.dumps({\n",{"type":39,"tag":209,"props":1693,"children":1694},{"class":211,"line":249},[1695],{"type":39,"tag":209,"props":1696,"children":1697},{},[1698],{"type":45,"value":1699},"            \"department\": escalation_data[\"reason_code\"],\n",{"type":39,"tag":209,"props":1701,"children":1702},{"class":211,"line":257},[1703],{"type":39,"tag":209,"props":1704,"children":1705},{},[1706],{"type":45,"value":1707},"            \"conversation_id\": escalation_data[\"conversation_id\"],\n",{"type":39,"tag":209,"props":1709,"children":1710},{"class":211,"line":27},[1711],{"type":39,"tag":209,"props":1712,"children":1713},{},[1714],{"type":45,"value":1715},"            \"profile_id\": escalation_data[\"profile_id\"],\n",{"type":39,"tag":209,"props":1717,"children":1718},{"class":211,"line":274},[1719],{"type":39,"tag":209,"props":1720,"children":1721},{},[1722],{"type":45,"value":1723},"            \"ai_summary\": escalation_data[\"summary\"],\n",{"type":39,"tag":209,"props":1725,"children":1726},{"class":211,"line":283},[1727],{"type":39,"tag":209,"props":1728,"children":1729},{},[1730],{"type":45,"value":1731},"            \"priority\": 5\n",{"type":39,"tag":209,"props":1733,"children":1734},{"class":211,"line":292},[1735],{"type":39,"tag":209,"props":1736,"children":1737},{},[1738],{"type":45,"value":1739},"        }),\n",{"type":39,"tag":209,"props":1741,"children":1742},{"class":211,"line":300},[1743],{"type":39,"tag":209,"props":1744,"children":1745},{},[1746],{"type":45,"value":1747},"        workflow_sid=workflow.sid\n",{"type":39,"tag":209,"props":1749,"children":1750},{"class":211,"line":309},[1751],{"type":39,"tag":209,"props":1752,"children":1753},{},[1754],{"type":45,"value":1755},"    )\n",{"type":39,"tag":48,"props":1757,"children":1758},{},[1759],{"type":45,"value":1760},"The human agent receives the AI's conversation summary and customer profile.",{"type":39,"tag":1446,"props":1762,"children":1764},{"id":1763},"workflow-with-timeout-escalation",[1765],{"type":45,"value":1766},"Workflow with Timeout Escalation",{"type":39,"tag":48,"props":1768,"children":1769},{},[1770],{"type":45,"value":1771},"Route to specialized queue first, then overflow to general:",{"type":39,"tag":54,"props":1773,"children":1775},{"className":201,"code":1774,"language":203,"meta":63,"style":63},"workflow_config = {\n    \"task_routing\": {\n        \"filters\": [\n            {\n                \"filter_friendly_name\": \"Billing Specialist First\",\n                \"expression\": \"department == 'billing'\",\n                \"targets\": [\n                    {\"queue\": billing_queue.sid, \"timeout\": 60},      # Try billing queue for 60s\n                    {\"queue\": default_queue.sid, \"timeout\": 120}      # Overflow to general\n                ]\n            }\n        ],\n        \"default_filter\": {\n            \"queue\": default_queue.sid\n        }\n    }\n}\n",[1776],{"type":39,"tag":61,"props":1777,"children":1778},{"__ignoreMap":63},[1779,1786,1793,1800,1807,1815,1822,1829,1837,1845,1852,1859,1866,1873,1880,1887,1894],{"type":39,"tag":209,"props":1780,"children":1781},{"class":211,"line":212},[1782],{"type":39,"tag":209,"props":1783,"children":1784},{},[1785],{"type":45,"value":894},{"type":39,"tag":209,"props":1787,"children":1788},{"class":211,"line":221},[1789],{"type":39,"tag":209,"props":1790,"children":1791},{},[1792],{"type":45,"value":902},{"type":39,"tag":209,"props":1794,"children":1795},{"class":211,"line":230},[1796],{"type":39,"tag":209,"props":1797,"children":1798},{},[1799],{"type":45,"value":910},{"type":39,"tag":209,"props":1801,"children":1802},{"class":211,"line":240},[1803],{"type":39,"tag":209,"props":1804,"children":1805},{},[1806],{"type":45,"value":918},{"type":39,"tag":209,"props":1808,"children":1809},{"class":211,"line":249},[1810],{"type":39,"tag":209,"props":1811,"children":1812},{},[1813],{"type":45,"value":1814},"                \"filter_friendly_name\": \"Billing Specialist First\",\n",{"type":39,"tag":209,"props":1816,"children":1817},{"class":211,"line":257},[1818],{"type":39,"tag":209,"props":1819,"children":1820},{},[1821],{"type":45,"value":934},{"type":39,"tag":209,"props":1823,"children":1824},{"class":211,"line":27},[1825],{"type":39,"tag":209,"props":1826,"children":1827},{},[1828],{"type":45,"value":942},{"type":39,"tag":209,"props":1830,"children":1831},{"class":211,"line":274},[1832],{"type":39,"tag":209,"props":1833,"children":1834},{},[1835],{"type":45,"value":1836},"                    {\"queue\": billing_queue.sid, \"timeout\": 60},      # Try billing queue for 60s\n",{"type":39,"tag":209,"props":1838,"children":1839},{"class":211,"line":283},[1840],{"type":39,"tag":209,"props":1841,"children":1842},{},[1843],{"type":45,"value":1844},"                    {\"queue\": default_queue.sid, \"timeout\": 120}      # Overflow to general\n",{"type":39,"tag":209,"props":1846,"children":1847},{"class":211,"line":292},[1848],{"type":39,"tag":209,"props":1849,"children":1850},{},[1851],{"type":45,"value":958},{"type":39,"tag":209,"props":1853,"children":1854},{"class":211,"line":300},[1855],{"type":39,"tag":209,"props":1856,"children":1857},{},[1858],{"type":45,"value":1021},{"type":39,"tag":209,"props":1860,"children":1861},{"class":211,"line":309},[1862],{"type":39,"tag":209,"props":1863,"children":1864},{},[1865],{"type":45,"value":1030},{"type":39,"tag":209,"props":1867,"children":1868},{"class":211,"line":519},[1869],{"type":39,"tag":209,"props":1870,"children":1871},{},[1872],{"type":45,"value":1039},{"type":39,"tag":209,"props":1874,"children":1875},{"class":211,"line":528},[1876],{"type":39,"tag":209,"props":1877,"children":1878},{},[1879],{"type":45,"value":1048},{"type":39,"tag":209,"props":1881,"children":1882},{"class":211,"line":826},[1883],{"type":39,"tag":209,"props":1884,"children":1885},{},[1886],{"type":45,"value":1057},{"type":39,"tag":209,"props":1888,"children":1889},{"class":211,"line":835},[1890],{"type":39,"tag":209,"props":1891,"children":1892},{},[1893],{"type":45,"value":1066},{"type":39,"tag":209,"props":1895,"children":1896},{"class":211,"line":844},[1897],{"type":39,"tag":209,"props":1898,"children":1899},{},[1900],{"type":45,"value":1074},{"type":39,"tag":1446,"props":1902,"children":1904},{"id":1903},"worker-activity-management",[1905],{"type":45,"value":1906},"Worker Activity Management",{"type":39,"tag":54,"props":1908,"children":1910},{"className":201,"code":1909,"language":203,"meta":63,"style":63},"# Set worker to available\nclient.taskrouter.v1.workspaces(workspace_sid) \\\n    .workers(worker_sid) \\\n    .update(activity_sid=available_activity_sid)\n\n# Get real-time worker statistics\nstats = client.taskrouter.v1.workspaces(workspace_sid) \\\n    .workers \\\n    .statistics() \\\n    .fetch()\n\nprint(f\"Available: {stats.realtime['total_available_workers']}\")\n",[1911],{"type":39,"tag":61,"props":1912,"children":1913},{"__ignoreMap":63},[1914,1922,1930,1938,1946,1953,1961,1969,1977,1985,1993,2000],{"type":39,"tag":209,"props":1915,"children":1916},{"class":211,"line":212},[1917],{"type":39,"tag":209,"props":1918,"children":1919},{},[1920],{"type":45,"value":1921},"# Set worker to available\n",{"type":39,"tag":209,"props":1923,"children":1924},{"class":211,"line":221},[1925],{"type":39,"tag":209,"props":1926,"children":1927},{},[1928],{"type":45,"value":1929},"client.taskrouter.v1.workspaces(workspace_sid) \\\n",{"type":39,"tag":209,"props":1931,"children":1932},{"class":211,"line":230},[1933],{"type":39,"tag":209,"props":1934,"children":1935},{},[1936],{"type":45,"value":1937},"    .workers(worker_sid) \\\n",{"type":39,"tag":209,"props":1939,"children":1940},{"class":211,"line":240},[1941],{"type":39,"tag":209,"props":1942,"children":1943},{},[1944],{"type":45,"value":1945},"    .update(activity_sid=available_activity_sid)\n",{"type":39,"tag":209,"props":1947,"children":1948},{"class":211,"line":249},[1949],{"type":39,"tag":209,"props":1950,"children":1951},{"emptyLinePlaceholder":234},[1952],{"type":45,"value":237},{"type":39,"tag":209,"props":1954,"children":1955},{"class":211,"line":257},[1956],{"type":39,"tag":209,"props":1957,"children":1958},{},[1959],{"type":45,"value":1960},"# Get real-time worker statistics\n",{"type":39,"tag":209,"props":1962,"children":1963},{"class":211,"line":27},[1964],{"type":39,"tag":209,"props":1965,"children":1966},{},[1967],{"type":45,"value":1968},"stats = client.taskrouter.v1.workspaces(workspace_sid) \\\n",{"type":39,"tag":209,"props":1970,"children":1971},{"class":211,"line":274},[1972],{"type":39,"tag":209,"props":1973,"children":1974},{},[1975],{"type":45,"value":1976},"    .workers \\\n",{"type":39,"tag":209,"props":1978,"children":1979},{"class":211,"line":283},[1980],{"type":39,"tag":209,"props":1981,"children":1982},{},[1983],{"type":45,"value":1984},"    .statistics() \\\n",{"type":39,"tag":209,"props":1986,"children":1987},{"class":211,"line":292},[1988],{"type":39,"tag":209,"props":1989,"children":1990},{},[1991],{"type":45,"value":1992},"    .fetch()\n",{"type":39,"tag":209,"props":1994,"children":1995},{"class":211,"line":300},[1996],{"type":39,"tag":209,"props":1997,"children":1998},{"emptyLinePlaceholder":234},[1999],{"type":45,"value":237},{"type":39,"tag":209,"props":2001,"children":2002},{"class":211,"line":309},[2003],{"type":39,"tag":209,"props":2004,"children":2005},{},[2006],{"type":45,"value":2007},"print(f\"Available: {stats.realtime['total_available_workers']}\")\n",{"type":39,"tag":78,"props":2009,"children":2010},{},[],{"type":39,"tag":40,"props":2012,"children":2014},{"id":2013},"scale-guidance",[2015],{"type":45,"value":2016},"Scale Guidance",{"type":39,"tag":1458,"props":2018,"children":2019},{},[2020,2041],{"type":39,"tag":1462,"props":2021,"children":2022},{},[2023],{"type":39,"tag":1466,"props":2024,"children":2025},{},[2026,2031,2036],{"type":39,"tag":1470,"props":2027,"children":2028},{},[2029],{"type":45,"value":2030},"Agents",{"type":39,"tag":1470,"props":2032,"children":2033},{},[2034],{"type":45,"value":2035},"Architecture",{"type":39,"tag":1470,"props":2037,"children":2038},{},[2039],{"type":45,"value":2040},"Notes",{"type":39,"tag":1481,"props":2042,"children":2043},{},[2044,2062,2080],{"type":39,"tag":1466,"props":2045,"children":2046},{},[2047,2052,2057],{"type":39,"tag":1488,"props":2048,"children":2049},{},[2050],{"type":45,"value":2051},"\u003C 10",{"type":39,"tag":1488,"props":2053,"children":2054},{},[2055],{"type":45,"value":2056},"Single workflow, one queue per skill",{"type":39,"tag":1488,"props":2058,"children":2059},{},[2060],{"type":45,"value":2061},"No Flex needed — agents use phone",{"type":39,"tag":1466,"props":2063,"children":2064},{},[2065,2070,2075],{"type":39,"tag":1488,"props":2066,"children":2067},{},[2068],{"type":45,"value":2069},"10-50",{"type":39,"tag":1488,"props":2071,"children":2072},{},[2073],{"type":45,"value":2074},"Multi-queue workflows, skills-based routing",{"type":39,"tag":1488,"props":2076,"children":2077},{},[2078],{"type":45,"value":2079},"Flex recommended for desktop",{"type":39,"tag":1466,"props":2081,"children":2082},{},[2083,2088,2093],{"type":39,"tag":1488,"props":2084,"children":2085},{},[2086],{"type":45,"value":2087},"50+",{"type":39,"tag":1488,"props":2089,"children":2090},{},[2091],{"type":45,"value":2092},"Multi-tier workflows, priority routing, real-time monitoring",{"type":39,"tag":1488,"props":2094,"children":2095},{},[2096],{"type":45,"value":2097},"Full Flex + supervisor tools",{"type":39,"tag":78,"props":2099,"children":2100},{},[],{"type":39,"tag":40,"props":2102,"children":2104},{"id":2103},"gotchas",[2105],{"type":45,"value":2106},"Gotchas",{"type":39,"tag":1446,"props":2108,"children":2110},{"id":2109},"_1-hyphens-in-attribute-names-break-silently",[2111],{"type":45,"value":2112},"1. Hyphens in Attribute Names Break Silently",{"type":39,"tag":54,"props":2114,"children":2116},{"className":201,"code":2115,"language":203,"meta":63,"style":63},"# WRONG — hyphens in attribute keys break workflow expressions\nworker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skill-level\": 5}'  # hyphen breaks expression evaluation\n)\n\n# RIGHT — use underscores or camelCase\nworker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(\n    friendly_name=\"Alice\",\n    attributes='{\"skill_level\": 5}'\n)\n",[2117],{"type":39,"tag":61,"props":2118,"children":2119},{"__ignoreMap":63},[2120,2128,2135,2142,2150,2157,2164,2172,2179,2186,2194],{"type":39,"tag":209,"props":2121,"children":2122},{"class":211,"line":212},[2123],{"type":39,"tag":209,"props":2124,"children":2125},{},[2126],{"type":45,"value":2127},"# WRONG — hyphens in attribute keys break workflow expressions\n",{"type":39,"tag":209,"props":2129,"children":2130},{"class":211,"line":221},[2131],{"type":39,"tag":209,"props":2132,"children":2133},{},[2134],{"type":45,"value":593},{"type":39,"tag":209,"props":2136,"children":2137},{"class":211,"line":230},[2138],{"type":39,"tag":209,"props":2139,"children":2140},{},[2141],{"type":45,"value":601},{"type":39,"tag":209,"props":2143,"children":2144},{"class":211,"line":240},[2145],{"type":39,"tag":209,"props":2146,"children":2147},{},[2148],{"type":45,"value":2149},"    attributes='{\"skill-level\": 5}'  # hyphen breaks expression evaluation\n",{"type":39,"tag":209,"props":2151,"children":2152},{"class":211,"line":249},[2153],{"type":39,"tag":209,"props":2154,"children":2155},{},[2156],{"type":45,"value":289},{"type":39,"tag":209,"props":2158,"children":2159},{"class":211,"line":257},[2160],{"type":39,"tag":209,"props":2161,"children":2162},{"emptyLinePlaceholder":234},[2163],{"type":45,"value":237},{"type":39,"tag":209,"props":2165,"children":2166},{"class":211,"line":27},[2167],{"type":39,"tag":209,"props":2168,"children":2169},{},[2170],{"type":45,"value":2171},"# RIGHT — use underscores or camelCase\n",{"type":39,"tag":209,"props":2173,"children":2174},{"class":211,"line":274},[2175],{"type":39,"tag":209,"props":2176,"children":2177},{},[2178],{"type":45,"value":593},{"type":39,"tag":209,"props":2180,"children":2181},{"class":211,"line":283},[2182],{"type":39,"tag":209,"props":2183,"children":2184},{},[2185],{"type":45,"value":601},{"type":39,"tag":209,"props":2187,"children":2188},{"class":211,"line":292},[2189],{"type":39,"tag":209,"props":2190,"children":2191},{},[2192],{"type":45,"value":2193},"    attributes='{\"skill_level\": 5}'\n",{"type":39,"tag":209,"props":2195,"children":2196},{"class":211,"line":300},[2197],{"type":39,"tag":209,"props":2198,"children":2199},{},[2200],{"type":45,"value":289},{"type":39,"tag":48,"props":2202,"children":2203},{},[2204],{"type":45,"value":2205},"No error — the expression silently fails to match.",{"type":39,"tag":1446,"props":2207,"children":2209},{"id":2208},"_2-has-operator-on-non-array-attributes",[2210],{"type":45,"value":2211},"2. HAS Operator on Non-Array Attributes",{"type":39,"tag":54,"props":2213,"children":2215},{"className":201,"code":2214,"language":203,"meta":63,"style":63},"# WRONG — \"billing\" is a string, not an array. HAS silently matches nothing.\ntarget_workers = 'department HAS \"billing\"'\n\n# RIGHT — use == for string attributes\ntarget_workers = 'department == \"billing\"'\n\n# RIGHT — use HAS only for arrays\ntarget_workers = 'skills HAS \"billing\"'  # skills: [\"billing\", \"technical\"]\n",[2216],{"type":39,"tag":61,"props":2217,"children":2218},{"__ignoreMap":63},[2219,2227,2235,2242,2250,2258,2265,2273],{"type":39,"tag":209,"props":2220,"children":2221},{"class":211,"line":212},[2222],{"type":39,"tag":209,"props":2223,"children":2224},{},[2225],{"type":45,"value":2226},"# WRONG — \"billing\" is a string, not an array. HAS silently matches nothing.\n",{"type":39,"tag":209,"props":2228,"children":2229},{"class":211,"line":221},[2230],{"type":39,"tag":209,"props":2231,"children":2232},{},[2233],{"type":45,"value":2234},"target_workers = 'department HAS \"billing\"'\n",{"type":39,"tag":209,"props":2236,"children":2237},{"class":211,"line":230},[2238],{"type":39,"tag":209,"props":2239,"children":2240},{"emptyLinePlaceholder":234},[2241],{"type":45,"value":237},{"type":39,"tag":209,"props":2243,"children":2244},{"class":211,"line":240},[2245],{"type":39,"tag":209,"props":2246,"children":2247},{},[2248],{"type":45,"value":2249},"# RIGHT — use == for string attributes\n",{"type":39,"tag":209,"props":2251,"children":2252},{"class":211,"line":249},[2253],{"type":39,"tag":209,"props":2254,"children":2255},{},[2256],{"type":45,"value":2257},"target_workers = 'department == \"billing\"'\n",{"type":39,"tag":209,"props":2259,"children":2260},{"class":211,"line":257},[2261],{"type":39,"tag":209,"props":2262,"children":2263},{"emptyLinePlaceholder":234},[2264],{"type":45,"value":237},{"type":39,"tag":209,"props":2266,"children":2267},{"class":211,"line":27},[2268],{"type":39,"tag":209,"props":2269,"children":2270},{},[2271],{"type":45,"value":2272},"# RIGHT — use HAS only for arrays\n",{"type":39,"tag":209,"props":2274,"children":2275},{"class":211,"line":274},[2276],{"type":39,"tag":209,"props":2277,"children":2278},{},[2279],{"type":45,"value":2280},"target_workers = 'skills HAS \"billing\"'  # skills: [\"billing\", \"technical\"]\n",{"type":39,"tag":48,"props":2282,"children":2283},{},[2284],{"type":45,"value":2285},"Tasks sit in queue forever with no error.",{"type":39,"tag":1446,"props":2287,"children":2289},{"id":2288},"_3-reservation-timeout-cascade",[2290],{"type":45,"value":2291},"3. Reservation Timeout Cascade",{"type":39,"tag":48,"props":2293,"children":2294},{},[2295],{"type":45,"value":2296},"When a reservation times out:",{"type":39,"tag":2298,"props":2299,"children":2300},"ol",{},[2301,2306,2311],{"type":39,"tag":92,"props":2302,"children":2303},{},[2304],{"type":45,"value":2305},"Worker moves to the timeout Activity (often \"Offline\")",{"type":39,"tag":92,"props":2307,"children":2308},{},[2309],{"type":45,"value":2310},"Fewer workers available → other reservations also time out",{"type":39,"tag":92,"props":2312,"children":2313},{},[2314],{"type":45,"value":2315},"Positive feedback loop → entire queue backs up",{"type":39,"tag":48,"props":2317,"children":2318},{},[2319,2324],{"type":39,"tag":70,"props":2320,"children":2321},{},[2322],{"type":45,"value":2323},"Fix:",{"type":45,"value":2325}," Set the timeout Activity to a short-duration state, not \"Offline\". Or implement a reservation timeout handler that keeps the worker available:",{"type":39,"tag":54,"props":2327,"children":2329},{"className":201,"code":2328,"language":203,"meta":63,"style":63},"@app.route(\"\u002Ftaskrouter-events\", methods=[\"POST\"])\ndef taskrouter_event():\n    event_type = request.form[\"EventType\"]\n    if event_type == \"reservation.timeout\":\n        worker_sid = request.form[\"WorkerSid\"]\n        # Keep worker available instead of moving to offline\n        client.taskrouter.v1.workspaces(workspace_sid) \\\n            .workers(worker_sid) \\\n            .update(activity_sid=available_activity_sid)\n    return \"\", 200\n",[2330],{"type":39,"tag":61,"props":2331,"children":2332},{"__ignoreMap":63},[2333,2341,2349,2357,2365,2373,2381,2389,2397,2405],{"type":39,"tag":209,"props":2334,"children":2335},{"class":211,"line":212},[2336],{"type":39,"tag":209,"props":2337,"children":2338},{},[2339],{"type":45,"value":2340},"@app.route(\"\u002Ftaskrouter-events\", methods=[\"POST\"])\n",{"type":39,"tag":209,"props":2342,"children":2343},{"class":211,"line":221},[2344],{"type":39,"tag":209,"props":2345,"children":2346},{},[2347],{"type":45,"value":2348},"def taskrouter_event():\n",{"type":39,"tag":209,"props":2350,"children":2351},{"class":211,"line":230},[2352],{"type":39,"tag":209,"props":2353,"children":2354},{},[2355],{"type":45,"value":2356},"    event_type = request.form[\"EventType\"]\n",{"type":39,"tag":209,"props":2358,"children":2359},{"class":211,"line":240},[2360],{"type":39,"tag":209,"props":2361,"children":2362},{},[2363],{"type":45,"value":2364},"    if event_type == \"reservation.timeout\":\n",{"type":39,"tag":209,"props":2366,"children":2367},{"class":211,"line":249},[2368],{"type":39,"tag":209,"props":2369,"children":2370},{},[2371],{"type":45,"value":2372},"        worker_sid = request.form[\"WorkerSid\"]\n",{"type":39,"tag":209,"props":2374,"children":2375},{"class":211,"line":257},[2376],{"type":39,"tag":209,"props":2377,"children":2378},{},[2379],{"type":45,"value":2380},"        # Keep worker available instead of moving to offline\n",{"type":39,"tag":209,"props":2382,"children":2383},{"class":211,"line":27},[2384],{"type":39,"tag":209,"props":2385,"children":2386},{},[2387],{"type":45,"value":2388},"        client.taskrouter.v1.workspaces(workspace_sid) \\\n",{"type":39,"tag":209,"props":2390,"children":2391},{"class":211,"line":274},[2392],{"type":39,"tag":209,"props":2393,"children":2394},{},[2395],{"type":45,"value":2396},"            .workers(worker_sid) \\\n",{"type":39,"tag":209,"props":2398,"children":2399},{"class":211,"line":283},[2400],{"type":39,"tag":209,"props":2401,"children":2402},{},[2403],{"type":45,"value":2404},"            .update(activity_sid=available_activity_sid)\n",{"type":39,"tag":209,"props":2406,"children":2407},{"class":211,"line":292},[2408],{"type":39,"tag":209,"props":2409,"children":2410},{},[2411],{"type":45,"value":2412},"    return \"\", 200\n",{"type":39,"tag":1446,"props":2414,"children":2416},{"id":2415},"_4-activity-available-flag",[2417],{"type":45,"value":2418},"4. Activity Available Flag",{"type":39,"tag":48,"props":2420,"children":2421},{},[2422,2424,2430],{"type":45,"value":2423},"Updating an Activity's ",{"type":39,"tag":61,"props":2425,"children":2427},{"className":2426},[],[2428],{"type":45,"value":2429},"available",{"type":45,"value":2431}," 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.",{"type":39,"tag":78,"props":2433,"children":2434},{},[],{"type":39,"tag":40,"props":2436,"children":2438},{"id":2437},"cannot",[2439],{"type":45,"value":2440},"CANNOT",{"type":39,"tag":88,"props":2442,"children":2443},{},[2444,2486,2509,2519,2536,2552,2562,2580,2598,2614,2624,2634,2644,2675,2685,2695,2705,2714],{"type":39,"tag":92,"props":2445,"children":2446},{},[2447,2452,2454,2460,2462,2468,2470,2476,2478,2484],{"type":39,"tag":70,"props":2448,"children":2449},{},[2450],{"type":45,"value":2451},"Hyphens in attribute names break expressions",{"type":45,"value":2453}," — ",{"type":39,"tag":61,"props":2455,"children":2457},{"className":2456},[],[2458],{"type":45,"value":2459},"skill-level",{"type":45,"value":2461}," is treated as subtraction (",{"type":39,"tag":61,"props":2463,"children":2465},{"className":2464},[],[2466],{"type":45,"value":2467},"skill",{"type":45,"value":2469}," minus ",{"type":39,"tag":61,"props":2471,"children":2473},{"className":2472},[],[2474],{"type":45,"value":2475},"level",{"type":45,"value":2477},"). Error 20001. Always use underscores: ",{"type":39,"tag":61,"props":2479,"children":2481},{"className":2480},[],[2482],{"type":45,"value":2483},"skill_level",{"type":45,"value":2485},".",{"type":39,"tag":92,"props":2487,"children":2488},{},[2489,2500,2501,2507],{"type":39,"tag":70,"props":2490,"children":2491},{},[2492,2498],{"type":39,"tag":61,"props":2493,"children":2495},{"className":2494},[],[2496],{"type":45,"value":2497},"HAS",{"type":45,"value":2499}," on non-array silently matches nothing",{"type":45,"value":2453},{"type":39,"tag":61,"props":2502,"children":2504},{"className":2503},[],[2505],{"type":45,"value":2506},"department HAS \"billing\"",{"type":45,"value":2508}," on a string attribute is accepted at creation but never matches. Tasks sit in queue forever with no error.",{"type":39,"tag":92,"props":2510,"children":2511},{},[2512,2517],{"type":39,"tag":70,"props":2513,"children":2514},{},[2515],{"type":45,"value":2516},"Expression validation is syntactic only",{"type":45,"value":2518}," — Queue creation validates parse but NOT worker matching. Semantically wrong expressions create successfully with zero matching workers.",{"type":39,"tag":92,"props":2520,"children":2521},{},[2522,2534],{"type":39,"tag":70,"props":2523,"children":2524},{},[2525,2527,2532],{"type":45,"value":2526},"Activity ",{"type":39,"tag":61,"props":2528,"children":2530},{"className":2529},[],[2531],{"type":45,"value":2429},{"type":45,"value":2533}," flag is silently immutable",{"type":45,"value":2535}," — Updating returns 200 OK but does not change the value. Must delete and recreate the Activity.",{"type":39,"tag":92,"props":2537,"children":2538},{},[2539,2550],{"type":39,"tag":70,"props":2540,"children":2541},{},[2542,2548],{"type":39,"tag":61,"props":2543,"children":2545},{"className":2544},[],[2546],{"type":45,"value":2547},"multiTaskEnabled",{"type":45,"value":2549}," cannot be reverted to false",{"type":45,"value":2551}," — Once enabled on a Workspace, cannot be disabled. One-way door.",{"type":39,"tag":92,"props":2553,"children":2554},{},[2555,2560],{"type":39,"tag":70,"props":2556,"children":2557},{},[2558],{"type":45,"value":2559},"Reservation timeout moves worker to timeout Activity",{"type":45,"value":2561}," — Worker automatically moved to Offline. Must manually set back. This cascades: fewer available workers → more timeouts → queue collapse. See Gotcha #3.",{"type":39,"tag":92,"props":2563,"children":2564},{},[2565,2570,2572,2578],{"type":39,"tag":70,"props":2566,"children":2567},{},[2568],{"type":45,"value":2569},"Workflow target timeout auto-cancels tasks",{"type":45,"value":2571}," — When all targets exhaust timeouts, task is canceled. Always include a ",{"type":39,"tag":61,"props":2573,"children":2575},{"className":2574},[],[2576],{"type":45,"value":2577},"default_filter",{"type":45,"value":2579}," as catch-all.",{"type":39,"tag":92,"props":2581,"children":2582},{},[2583,2596],{"type":39,"tag":70,"props":2584,"children":2585},{},[2586,2588,2594],{"type":45,"value":2587},"Worker ",{"type":39,"tag":61,"props":2589,"children":2591},{"className":2590},[],[2592],{"type":45,"value":2593},"friendlyName",{"type":45,"value":2595}," is case-insensitive unique",{"type":45,"value":2597}," — \"alice\" collides with \"Alice\".",{"type":39,"tag":92,"props":2599,"children":2600},{},[2601,2612],{"type":39,"tag":70,"props":2602,"children":2603},{},[2604,2610],{"type":39,"tag":61,"props":2605,"children":2607},{"className":2606},[],[2608],{"type":45,"value":2609},"workflowSid",{"type":45,"value":2611}," is required for task creation",{"type":45,"value":2613}," — API does not auto-select a default Workflow.",{"type":39,"tag":92,"props":2615,"children":2616},{},[2617,2622],{"type":39,"tag":70,"props":2618,"children":2619},{},[2620],{"type":45,"value":2621},"Cannot update task status and attributes in same request",{"type":45,"value":2623}," — Must be two separate API calls.",{"type":39,"tag":92,"props":2625,"children":2626},{},[2627,2632],{"type":39,"tag":70,"props":2628,"children":2629},{},[2630],{"type":45,"value":2631},"Assignment callback must respond in 5 seconds",{"type":45,"value":2633}," — If both primary and fallback URLs fail, reservation is canceled.",{"type":39,"tag":92,"props":2635,"children":2636},{},[2637,2642],{"type":39,"tag":70,"props":2638,"children":2639},{},[2640],{"type":45,"value":2641},"Tasks auto-cancel after 1,000 rejections",{"type":45,"value":2643}," — If a task cycles through 1,000 reservation rejections, it is automatically canceled.",{"type":39,"tag":92,"props":2645,"children":2646},{},[2647,2658,2660,2666,2668,2673],{"type":39,"tag":70,"props":2648,"children":2649},{},[2650,2656],{"type":39,"tag":61,"props":2651,"children":2653},{"className":2652},[],[2654],{"type":45,"value":2655},"page",{"type":45,"value":2657}," query param not supported",{"type":45,"value":2659}," — Use ",{"type":39,"tag":61,"props":2661,"children":2663},{"className":2662},[],[2664],{"type":45,"value":2665},"PageToken",{"type":45,"value":2667}," for pagination. ",{"type":39,"tag":61,"props":2669,"children":2671},{"className":2670},[],[2672],{"type":45,"value":2655},{"type":45,"value":2674}," returns error 40153.",{"type":39,"tag":92,"props":2676,"children":2677},{},[2678,2683],{"type":39,"tag":70,"props":2679,"children":2680},{},[2681],{"type":45,"value":2682},"Cannot use malformed JSON in worker attributes",{"type":45,"value":2684}," — Silently breaks matching with no error",{"type":39,"tag":92,"props":2686,"children":2687},{},[2688,2693],{"type":39,"tag":70,"props":2689,"children":2690},{},[2691],{"type":45,"value":2692},"Cannot use regex in workflow expressions",{"type":45,"value":2694}," — Only supports ==, !=, \u003C, >, HAS, IN, CONTAINS, AND, OR, NOT",{"type":39,"tag":92,"props":2696,"children":2697},{},[2698,2703],{"type":39,"tag":70,"props":2699,"children":2700},{},[2701],{"type":45,"value":2702},"Cannot exceed 50,000 Workers per Workspace",{"type":45,"value":2704}," — Hard limit",{"type":39,"tag":92,"props":2706,"children":2707},{},[2708,2713],{"type":39,"tag":70,"props":2709,"children":2710},{},[2711],{"type":45,"value":2712},"Cannot exceed 250 Task Queues per Workspace",{"type":45,"value":2704},{"type":39,"tag":92,"props":2715,"children":2716},{},[2717,2722],{"type":39,"tag":70,"props":2718,"children":2719},{},[2720],{"type":45,"value":2721},"Cannot delay reservation callback response beyond 15 seconds",{"type":45,"value":2723}," — Timeout results in reservation failure",{"type":39,"tag":78,"props":2725,"children":2726},{},[],{"type":39,"tag":40,"props":2728,"children":2730},{"id":2729},"next-steps",[2731],{"type":45,"value":2732},"Next Steps",{"type":39,"tag":88,"props":2734,"children":2735},{},[2736,2752,2767,2781],{"type":39,"tag":92,"props":2737,"children":2738},{},[2739,2744,2746],{"type":39,"tag":70,"props":2740,"children":2741},{},[2742],{"type":45,"value":2743},"Conference for transfers:",{"type":45,"value":2745}," ",{"type":39,"tag":61,"props":2747,"children":2749},{"className":2748},[],[2750],{"type":45,"value":2751},"twilio-conference-calls",{"type":39,"tag":92,"props":2753,"children":2754},{},[2755,2760,2761],{"type":39,"tag":70,"props":2756,"children":2757},{},[2758],{"type":45,"value":2759},"Call recording:",{"type":45,"value":2745},{"type":39,"tag":61,"props":2762,"children":2764},{"className":2763},[],[2765],{"type":45,"value":2766},"twilio-call-recordings",{"type":39,"tag":92,"props":2768,"children":2769},{},[2770,2775,2776],{"type":39,"tag":70,"props":2771,"children":2772},{},[2773],{"type":45,"value":2774},"AI agent voice integration:",{"type":45,"value":2745},{"type":39,"tag":61,"props":2777,"children":2779},{"className":2778},[],[2780],{"type":45,"value":168},{"type":39,"tag":92,"props":2782,"children":2783},{},[2784,2789,2790],{"type":39,"tag":70,"props":2785,"children":2786},{},[2787],{"type":45,"value":2788},"Voice IVR before routing:",{"type":45,"value":2745},{"type":39,"tag":61,"props":2791,"children":2793},{"className":2792},[],[2794],{"type":45,"value":157},{"type":39,"tag":2796,"props":2797,"children":2798},"style",{},[2799],{"type":45,"value":2800},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2802,"total":2978},[2803,2818,2837,2848,2859,2873,2888,2904,2920,2932,2948,2966],{"slug":102,"name":102,"fn":2804,"description":2805,"org":2806,"tags":2807,"stars":23,"repoUrl":24,"updatedAt":2817},"configure Twilio accounts and credentials","Create and configure a Twilio account from scratch. Covers free trial signup, trial limitations, getting credentials (Account SID and Auth Token), buying a phone number, verifying recipient numbers for trial use, SDK installation, first API call, subaccount management (creation, inheritance, credential isolation, limits), and enabling specific products (AI Assistants, Conversations, Verify, ConversationRelay, WhatsApp). Use this skill before any other Twilio skill if you do not yet have a Twilio account or need to enable a product. For Organization-level governance (SSO, SCIM, multi-team), see `twilio-organizations-setup`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2808,2811,2814],{"name":2809,"slug":2810,"type":15},"API Development","api-development",{"name":2812,"slug":2813,"type":15},"Communications","communications",{"name":2815,"slug":2816,"type":15},"SMS","sms","2026-08-01T05:43:28.968968",{"slug":2819,"name":2819,"fn":2820,"description":2821,"org":2822,"tags":2823,"stars":23,"repoUrl":24,"updatedAt":2836},"twilio-agent-augmentation-architect","augment human agents with AI intelligence","Planning skill for augmenting human agents with real-time AI intelligence. Qualifies the developer's use case across coaching, compliance, QA, and routing to recommend the right Conversation Intelligence + Conversation Memory + TaskRouter architecture. Handles both \"I want to add AI coaching to my call center\" and \"configure Conversation Intelligence operators for script adherence.\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2824,2826,2829,2832,2835],{"name":2030,"slug":2825,"type":15},"agents",{"name":2827,"slug":2828,"type":15},"AI","ai",{"name":2830,"slug":2831,"type":15},"Coaching","coaching",{"name":2833,"slug":2834,"type":15},"QA","qa",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:58.250609",{"slug":2838,"name":2838,"fn":2839,"description":2840,"org":2841,"tags":2842,"stars":23,"repoUrl":24,"updatedAt":2847},"twilio-agent-connect","connect AI agents to Twilio channels","Connect third-party AI agents (OpenAI, Bedrock, LangChain, Microsoft Foundry) to Twilio's communication channels using the Twilio Agent Connect SDK. Covers identity resolution, memory and context management via Conversation Memory, conversation orchestration via Conversation Orchestrator, multi-channel handling (Voice, SMS, RCS, WhatsApp, Chat), and AI-to-human escalation. Use this skill when integrating an existing LLM agent with Twilio services.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2843,2844,2845,2846],{"name":2030,"slug":2825,"type":15},{"name":2809,"slug":2810,"type":15},{"name":2812,"slug":2813,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T06:06:05.217098",{"slug":2849,"name":2849,"fn":2850,"description":2851,"org":2852,"tags":2853,"stars":23,"repoUrl":24,"updatedAt":2858},"twilio-ai-agent-architect","plan Twilio conversational AI agents","Planning skill for AI-powered conversational agents. Qualifies the developer's use case across outcome sophistication, entry point, and customer profile to recommend the right Twilio Conversations architecture and implementation skills. Handles both high-level requests (\"build me a voice AI assistant\") and specific ones (\"integrate ConversationRelay with my OpenAI backend\").\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2854,2855,2857],{"name":2030,"slug":2825,"type":15},{"name":2035,"slug":2856,"type":15},"architecture",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:48.883723",{"slug":2766,"name":2766,"fn":2860,"description":2861,"org":2862,"tags":2863,"stars":23,"repoUrl":24,"updatedAt":2872},"record and manage Twilio voice calls","Record Twilio voice calls correctly. Covers the critical distinction between Record verb (voicemail) and Dial record (call recording), dual-channel for QA, mid-call pause for PCI, Conference recording, and the ConversationRelay workaround. Use this skill whenever you need to capture call audio for compliance, QA, or analytics.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2864,2867,2870,2871],{"name":2865,"slug":2866,"type":15},"Audio","audio",{"name":2868,"slug":2869,"type":15},"Compliance","compliance",{"name":2833,"slug":2834,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.268412",{"slug":2874,"name":2874,"fn":2875,"description":2876,"org":2877,"tags":2878,"stars":23,"repoUrl":24,"updatedAt":2887},"twilio-cli-reference","manage Twilio resources via CLI","Twilio CLI reference for managing Twilio resources from the terminal. Covers installation, credential profiles, phone number provisioning, sending SMS and email, webhook configuration, local development with a tunneling service, debugging with watch and logs, serverless deployment, and plugin ecosystem. Use when the developer asks to \"just do it\", \"set this up\", \"run a command\", mentions \"CLI\", \"command line\", or \"terminal\", or when an AI agent can execute a task directly instead of writing application code.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2879,2882,2885,2886],{"name":2880,"slug":2881,"type":15},"CLI","cli",{"name":2883,"slug":2884,"type":15},"Local Development","local-development",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T06:07:54.925664",{"slug":2889,"name":2889,"fn":2890,"description":2891,"org":2892,"tags":2893,"stars":23,"repoUrl":24,"updatedAt":2903},"twilio-compliance-onboarding","manage Twilio messaging and voice compliance","Registrations required BEFORE Twilio traffic works. Covers messaging programs (A2P 10DLC, toll-free verification, WhatsApp WABA, RCS, short code, alphanumeric sender) and voice trust programs (STIR\u002FSHAKEN, Voice Integrity, Branded Calling, CNAM). Each number\u002Fsender type has its own program — registration blocks traffic until complete.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2894,2895,2898,2899,2900],{"name":2868,"slug":2869,"type":15},{"name":2896,"slug":2897,"type":15},"Messaging","messaging",{"name":2815,"slug":2816,"type":15},{"name":9,"slug":8,"type":15},{"name":2901,"slug":2902,"type":15},"WhatsApp","whatsapp","2026-07-17T06:05:47.897229",{"slug":2905,"name":2905,"fn":2906,"description":2907,"org":2908,"tags":2909,"stars":23,"repoUrl":24,"updatedAt":2919},"twilio-compliance-traffic","ensure compliance for Twilio messaging traffic","Rules you must follow for Twilio messaging and voice traffic. Covers TCPA (consent tiers, quiet hours, DNC), GDPR (EU consent, right to deletion), PCI DSS (payment recording, Pay verb), HIPAA (BAA, PHI), FDCPA (debt collection limits), CAN-SPAM, WhatsApp policies, SHAKEN\u002FSTIR, and consent management patterns. Use this skill proactively when developers have working traffic to ensure they follow the rules.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2910,2911,2912,2915,2918],{"name":2868,"slug":2869,"type":15},{"name":2896,"slug":2897,"type":15},{"name":2913,"slug":2914,"type":15},"Regulatory Compliance","regulatory-compliance",{"name":2916,"slug":2917,"type":15},"Security","security",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.952779",{"slug":2751,"name":2751,"fn":2921,"description":2922,"org":2923,"tags":2924,"stars":23,"repoUrl":24,"updatedAt":2931},"build multi-party calls with Twilio Conference","Build multi-party calls using Twilio Conference. Covers warm transfer, cold transfer, coaching (whisper), hold vs mute, participant modes, and supervisor barge. Use this skill for any contact center, support line, or scenario requiring transfers, holds, or multi-party calls.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2925,2926,2927,2930],{"name":2865,"slug":2866,"type":15},{"name":2812,"slug":2813,"type":15},{"name":2928,"slug":2929,"type":15},"Meetings","meetings",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:55.603708",{"slug":2933,"name":2933,"fn":2934,"description":2935,"org":2936,"tags":2937,"stars":23,"repoUrl":24,"updatedAt":2947},"twilio-content-template-builder","create and send message templates with Twilio","Create, manage, and send message templates using Twilio's Content API. Covers template creation for WhatsApp, SMS, RCS, and MMS; variable usage; WhatsApp Meta approval; and sending templates via ContentSid. Use this skill when building structured messages that require pre-approval or consistent formatting across channels.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2938,2941,2942,2943,2946],{"name":2939,"slug":2940,"type":15},"Email","email",{"name":2896,"slug":2897,"type":15},{"name":2815,"slug":2816,"type":15},{"name":2944,"slug":2945,"type":15},"Templates","templates",{"name":9,"slug":8,"type":15},"2026-07-17T06:04:26.637309",{"slug":2949,"name":2949,"fn":2950,"description":2951,"org":2952,"tags":2953,"stars":23,"repoUrl":24,"updatedAt":2965},"twilio-conversation-intelligence","build conversation intelligence pipelines","Twilio Conversation Intelligence development guide. Use when building real-time or post-call conversation analysis, language operator pipelines, sentiment analysis, agent assist, cross-channel analytics, or querying aggregated conversation insights (sentiment trends, escalation rates, dashboards).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2954,2955,2958,2961,2964],{"name":2030,"slug":2825,"type":15},{"name":2956,"slug":2957,"type":15},"Analytics","analytics",{"name":2959,"slug":2960,"type":15},"Monitoring","monitoring",{"name":2962,"slug":2963,"type":15},"NLP","nlp",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:52.545387",{"slug":2967,"name":2967,"fn":2968,"description":2969,"org":2970,"tags":2971,"stars":23,"repoUrl":24,"updatedAt":2977},"twilio-conversation-memory","manage conversation memory with Twilio","Store and retrieve conversation context using Twilio Conversation Memory. Covers Memory Store provisioning, profile management, traits, observations, conversation summaries, and semantic Recall. Use this skill to give AI agents or human agents persistent memory of conversations across sessions and channels.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2972,2973,2976],{"name":2030,"slug":2825,"type":15},{"name":2974,"slug":2975,"type":15},"Memory","memory",{"name":9,"slug":8,"type":15},"2026-07-17T06:04:19.526724",57,{"items":2980,"total":2978},[2981,2987,2995,3002,3008,3015,3022],{"slug":102,"name":102,"fn":2804,"description":2805,"org":2982,"tags":2983,"stars":23,"repoUrl":24,"updatedAt":2817},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2984,2985,2986],{"name":2809,"slug":2810,"type":15},{"name":2812,"slug":2813,"type":15},{"name":2815,"slug":2816,"type":15},{"slug":2819,"name":2819,"fn":2820,"description":2821,"org":2988,"tags":2989,"stars":23,"repoUrl":24,"updatedAt":2836},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2990,2991,2992,2993,2994],{"name":2030,"slug":2825,"type":15},{"name":2827,"slug":2828,"type":15},{"name":2830,"slug":2831,"type":15},{"name":2833,"slug":2834,"type":15},{"name":9,"slug":8,"type":15},{"slug":2838,"name":2838,"fn":2839,"description":2840,"org":2996,"tags":2997,"stars":23,"repoUrl":24,"updatedAt":2847},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2998,2999,3000,3001],{"name":2030,"slug":2825,"type":15},{"name":2809,"slug":2810,"type":15},{"name":2812,"slug":2813,"type":15},{"name":9,"slug":8,"type":15},{"slug":2849,"name":2849,"fn":2850,"description":2851,"org":3003,"tags":3004,"stars":23,"repoUrl":24,"updatedAt":2858},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3005,3006,3007],{"name":2030,"slug":2825,"type":15},{"name":2035,"slug":2856,"type":15},{"name":9,"slug":8,"type":15},{"slug":2766,"name":2766,"fn":2860,"description":2861,"org":3009,"tags":3010,"stars":23,"repoUrl":24,"updatedAt":2872},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3011,3012,3013,3014],{"name":2865,"slug":2866,"type":15},{"name":2868,"slug":2869,"type":15},{"name":2833,"slug":2834,"type":15},{"name":9,"slug":8,"type":15},{"slug":2874,"name":2874,"fn":2875,"description":2876,"org":3016,"tags":3017,"stars":23,"repoUrl":24,"updatedAt":2887},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3018,3019,3020,3021],{"name":2880,"slug":2881,"type":15},{"name":2883,"slug":2884,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":2889,"name":2889,"fn":2890,"description":2891,"org":3023,"tags":3024,"stars":23,"repoUrl":24,"updatedAt":2903},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3025,3026,3027,3028,3029],{"name":2868,"slug":2869,"type":15},{"name":2896,"slug":2897,"type":15},{"name":2815,"slug":2816,"type":15},{"name":9,"slug":8,"type":15},{"name":2901,"slug":2902,"type":15}]