Agents & Presence
An agent is a sip_user with is_agent = 1. Whether an agent receives queue calls is governed by presence: live, derived state kept in the per-account PresenceDO.
Status vs. state
Section titled “Status vs. state”The PresenceDO tracks two orthogonal things per agent:
statusis what the agent wants:offline,available, oron_break(paused).stateis what the agent is doing:waiting,offering(a call is ringing them),in_call, orwrap_up.
A third signal, reachable, is fed independently by the SIP signaling layer register/qualify feed, and it reflects whether the agent’s device actually has a live SIP registration. Login and reachability are separate on purpose: an agent can be “available” in the app but unreachable if their phone dropped its registration.
To be offered a call, an agent must be available + waiting + reachable + not on an external call + not in wrap-up. See the reserve fence for how that predicate is enforced atomically.
Multi-queue membership
Section titled “Multi-queue membership”An agent can belong to many queues, each with its own skill tier (agent_queue_assignment.tier_level) and position. When an agent frees up, the brain looks across all their queues, in tier order, to find the next caller to push. This is how you model agents who handle several lines with a priority among them. How an agent comes to be in a queue (admin-assigned, self-selected, or supervisor-managed) is governed by the membership mode.
The agent control API
Section titled “The agent control API”An agent app (softphone, desktop, or your own UI) drives presence through the /agent endpoint. To bring an agent online and into queues:
curl -X POST https://nodes.sip.io/agent \ -H 'content-type: application/json' \ -d '{ "accountId": "acc_01jf18ah3jeb5w6dfp27sgjsbt", "userId": 1001, "event": "available", "queues": [ { "queueId": "q_01j160r23gw5zkpfjme3fwzs5k", "level": 1 }, { "queueId": "q_01jx67hmyhnks8yq7m76g5qrrj", "level": 2 } ] }'Common event values: login, logout, available, pause (with a reason), unpause. The optional queues array sets the agent’s queue membership (and per-queue tier) in the same call.
Read an agent’s live presence:
curl 'https://nodes.sip.io/agent?accountId=acc_01jf18ah3jeb5w6dfp27sgjsbt&userId=1001'…and the whole account roster (for a dashboard) via the presence list endpoint, which merges the configured sip_user roster with live state so never-registered extensions still show as offline.
See the Control-Plane API for the full surface.
Pause reasons
Section titled “Pause reasons”Pauses can carry a reason (pause_reason), and a reason can declare whether inbound and/or outbound calls still flow while the agent is paused:
{ "id": "pr_01jy2jaazhf1kxbnpepe22atz1", "account_id": "acc_01jf18ah3jeb5w6dfp27sgjsbt", "name": "Lunch", "allow_inbound": 0, "allow_outbound": 1 }This lets you distinguish “on a break, don’t ring me” from “doing after-call work, but you can still reach me.”
Agent live-status buckets
Section titled “Agent live-status buckets”For dashboards, the PresenceDO collapses status + state + reachability into a single bucket per agent, in priority order:
external call › in call › offline › unreachable › ringing › paused › wrap-up › ready › idle
…and the dashboard view rolls these into tiles: available, on_call, ringing, paused, wrap_up, offline. Every change emits a delta to the live outbox so wallboards update in near-real-time.
Reachability and CAC
Section titled “Reachability and CAC”Because reachability comes from the registrar feed, the same signal that decides “can this agent be offered a call” also keeps presence honest when phones come and go. External (non-queue) calls an agent makes or receives are tracked too, so the queue won’t offer a call to an agent who’s already busy on a direct call.
Roadmap
Section titled “Roadmap”- Sticky / last-agent routing: repeat callers preferred back to their previous agent is built as a per-queue option; see Sticky / last-agent routing.
- BLF / SIP presence (NOTIFY): driving busy-lamp-field subscriptions from the same delta stream is a planned second consumer of the live event envelope.