Worker (WK…)
The agent's identity in TaskRouter — activity state (Available, Reserved, WrapUp), attributes, skills.
Lesson 9 of 10
Same support fundamentals — HTTP, auth, events — running inside a richer state machine: workers, tasks, and reservations that can each fail independently.
@twilio/flex-sdk gives a custom app the same building blocks the stock Flex UI is built on.
The agent's identity in TaskRouter — activity state (Available, Reserved, WrapUp), attributes, skills.
A unit of work waiting to be routed — a call, a chat, an email. Carries attributes a Workflow uses to route it.
One worker's offer to handle one task. Its status — pending, accepted, rejected, timeout, canceled — is where most "agent can't accept" bugs actually live.
The Conversations-SDK-backed thread behind a chat/email task — participants, transcript, and its own independent lifecycle from the task that spawned it.
The embedded Voice SDK connection carrying call audio and controls — a task can be "accepted" in TaskRouter while this is still silently broken.
Each of these looks like a different bug from the outside — knowing which layer owns it is most of the diagnosis.
For voice tasks, you must register a VoiceClientEvent listener before calling AcceptTask. Skip it and acceptance can succeed while the agent gets no audio or call controls.
The reservation only clears when the client actually calls CompleteTask (and WrapUpTask, if wrap-up is configured). A call that errors silently — or never fires — parks the worker indefinitely.
Error 45775 — the refresh token is malformed, expired, or clock-skewed. Fixing validateToken/refreshToken locally isn't enough: the session stays stale until the client actually calls client.updateToken with the new pair.
If TaskRouter, Conversations, Voice, or Sync fails to initialize, Flex loads anyway in a reduced-capability "degraded" state. A degraded Voice client next to a healthy TaskRouter client reads like a routing bug, not a connectivity one.
Several distinct causes, not one bug: a declined Interaction invite cancels the task but leaves the conversation open; inviting a participant already in another open conversation fails silently; an unhandled workflow.timeout/task.canceled/task.deleted leaves nothing tracking the conversation at all.
Read the sanitized reservation payload and console excerpt below, then work through both exercises.
{
"reservation": {
"sid": "WRxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"worker_sid": "WKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"task_sid": "WTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"reservation_status": "wrapping",
"date_created": "2026-07-29T18:02:11Z",
"date_updated": "2026-07-29T18:14:47Z"
},
"worker": {
"activity_sid": "WAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"activity_name": "WrapUp",
"available": false
}
}
16:14:03 | log | SessionState: setting degraded to false
16:14:47 | warn | AcceptTask resolved but no VoiceClientEvent listener was registered
16:14:52 | error | 45775: Failed to refresh token. Invalid token provided.Answer in your head first, then click a question to reveal the answer.
A worker is stuck in WrapUp after a call ended. Work the checklist and check each item off. Progress is saved in your browser.
These primers are a starting point. Read the primary sources to build real fluency.
What building this project taught me.
Events covers webhooks/retries/idempotency in the abstract; SSO & Identity Edge Cases covers enterprise federation. This lesson is where both show up inside one stateful client SDK — a reservation is basically an event you have to act on, and a Flex token refresh is SSO's token-exchange problem with a shorter clock.
The failure modes here — error 45775, the VoiceClientEvent listener requirement, the three distinct Conversations-orphaning causes — came from the twilio-docs MCP, the same sourcing discipline the Support Triage Assistant's grounding packs use.