Skip to main content

Intraday adherence and agent requests

Planning-side WFM — forecasts, schedules, assignments — is only half of a contact center’s day. The day-of loop answers a different question: are the agents who are scheduled actually working the schedule right now, and when they are not, how do you decide whether a deviation is excused or counts against them? This guide walks that loop end-to-end: the live adherence surface, how breaches are scored, the exceptions queue that excuses them, and the two-sided agent requests that feed it (time-off, shift swaps, preferences). This guide assumes the schedule already exists — the schedule-side workflow (shift templates, skills, generation, assignments) is covered in Workforce-management workflows, and the full contract for every call below is on the WFM API reference. This page is the narrative for everything that happens after the schedule goes live.

1. The day-of loop

Once a schedule is published, four surfaces keep supervisors ahead of coverage, and they all live under Voice → Scheduling on the dashboard (the Intraday, Approval queue, and exceptions-queue tabs) or under /api/v1/wfm/* on the API:
  1. Intraday staffing — scheduled vs. required agents per channel for the operating date. A deficit is what a rebalance, an open shift, or an overtime offer fixes.
  2. Real-time adherence — which scheduled agent is off-schedule right now, scored every 15 seconds against the live agent-state feed.
  3. The breach feed — the subset of off-schedule agents whose deviation has run long enough to warrant attention (default: 5 continuous minutes).
  4. The exceptions queue — the approve/deny workflow that decides whether a deviation an agent files about gets excused from their adherence score, or continues to count against them.
Everything here is two-sided. Supervisors evaluate and decide; agents file exceptions and requests; the system credits or penalizes only once the two sides agree. Approving a time-off request, approving a shift swap, or approving an adherence exception all change how the same scoring engine treats the same agent on the same day — which is why they belong to one loop, not three separate features.

2. Prerequisites

Three things have to be true before any of the day-of surfaces report truthfully:
  • The schedule exists for the operating date. Adherence computes against wfm_schedule_assignments rows with status scheduled or swapped for the day being evaluated; if generation has not covered today, the dashboards return empty agent lists, not zeros.
  • A live agent-state feed is set. Adherence compares the schedule against what agents actually do in the ACD — online, on a call, on break, in training, logged out. Those states come from the agent activity (aux code) feed in the dialer or inbox. If agents never set their aux state, intraday adherence reads as blank (not “good”), the breach feed sees nothing, and exceptions are being asked to excuse deviations that were never measured. Fix the feed before approving any exceptions.
  • API access with the right scope. Reads (the dashboards, the breach feed, the request lists) need an API key with wfm:read; agent self-serve writes (filing an exception, a request, an accept-swap) execute under any authenticated role acting as themselves. Management decisions — approve, deny, award — require the owner or admin role. A supervisor-adjacent role (supervisor) can read the RTA stream and breach feed, but is filtered to its assigned queues.

3. Intraday telemetry — RTA stream + breach feed

Two live surfaces answer the same question at two different cadences, and the Intraday tab on the dashboard wires both, refreshing on 15-second intervals.

3a. The real-time stream (server-sent events)

For a supervisor who runs a wallboard or a custom manager dashboard, GET /api/v1/wfm/rta/stream is a server-sent event (SSE) stream that pushes adherence changes rather than requiring a poll. It opens with a connected event, then a full snapshot of every scheduled agent’s current adherence state, then forwards two event types live: rta.state_changed (an agent flipped from in-adherence to off-schedule, or back) and wfm.adherence_alert (an agent’s cumulative intraday ratio dropped below threshold). The stream stays open with a 30-second heartbeat; a queue-scoped supervisor sees only their queues, and a supervisor with no queue mappings sees an empty stream rather than the tenant-wide picture.
The stream queries accept a queue_id filter and a date override; the date defaults to the tenant’s operating day in its shift timezone. When SSE is not an option — a cron-style worker, a fetch-driven dashboard, an API client that cannot hold a long-lived socket — the same snapshot is available as a poll on GET /api/v1/wfm/adherence/intraday?date=… and the current breach subset on the endpoint below.

3b. The breach feed (who have I actually got a problem with)

An agent who has been off-schedule for 45 seconds because they are between calls is noise; an agent who has been off-schedule for 14 minutes is an incident. GET /api/v1/wfm/rta/breaches applies that duration threshold so the supervisor’s “who needs a nudge” list is short and actionable:
The response carries agents_evaluated, breach_count, and a breaches array of (agent_id, current_state, continuous_ooa_seconds, current_state_started_at) sorted longest-breach-first. threshold_minutes is the supervisor-tunable knob — default 5, clamped to 1–480 — so a stricter or a noisier team can tune the band without a redeploy. The op query switches the boundary semantics (gte by default; gt for “strictly over”). A supervisor role is filtered to the queues an owner or admin assigned them: a supervisor with no queue mappings gets an empty breach list, not the tenant-wide firehose.

4. How a breach is scored

Every surface above reads the same scoring engine, and the engine answers two questions per scheduled agent per tick:
  1. Where is the agent now? — the latest entry on their adherence-events timeline for the operating date (their current aux state and when it started).
  2. Should they be working? — whether the schedule has a scheduled or swapped assignment spanning right now. Pre-shift agents and post-shift agents are graded off_shift and never generate a breach; breaches only exist inside an active assignment window.
An agent is in adherence when their current aux state is one the shift treats as work (online, on a call, on a scheduled break or activity whose timing matches the shift template’s activities). An agent is off-schedule when their state says otherwise — logged out mid-shift, in an unscheduled aux state, on a break that ran 20 minutes past its timed segment. The continuous_ooa_seconds (out-of-adherence) counter is the elapsed time since the current off-schedule state began; it is what the breach threshold compares against. An approved exception does not delete the deviation — it marks it excused so the ratio recovers, and the raw and the adjusted score are both reported so the carve-out is auditable, never silent.

5. The exceptions queue — excuse or count

Adherence punishes agents for deviations they had no control over: a dialer outage, a mandatory all-hands, unplanned coaching a manager pulled them into. An adherence exception is the filed carve-out — while approved, those minutes stop counting as non-adherent. An agent (or a manager on their behalf) files one in pending:
exception_type is one of system_outage, emergency_meeting, unplanned_coaching, approved_absence, training, or other. Non-managers may only file for themselves (an attempt to file for another agent returns 403); managers may file on behalf of any agent. The ends_at must be strictly after starts_at — anything else returns 422 with a field location. A manager then works the queue. GET /wfm/adherence-exceptions filters by agent_id, status, exception_type, and a from/to window; non-manager callers only ever see their own rows, so an agent’s queue view never leaks a peer’s reason text:
The state machine is strict, and it is the part of the queue that makes it auditable: only pending rows can be approved or denied (a second decision returns 409 INVALID_TRANSITION, which is how a queue race between two managers resolves cleanly), and only the requester — or a manager, as a moderator action — can cancel a still-pending row with POST /wfm/adherence-exceptions/{id}/cancel. An approved exception credits the excused seconds back to the adherent total; a denied exception leaves the deviation counting against the agent. On the dashboard this queue sits under Voice → Scheduling next to the approval queue. For the management view over a period, GET /wfm/adherence-exceptions/trends?from=…&to=… returns counts and excused seconds grouped by exception type and status — a spike in system_outage points at infrastructure, a spike in emergency_meeting points at ops, and a spike in approved_absence for one team points at a manager habit. Non-managers calling trends get aggregates over their own rows only, so the per-team roll-up never leaks across teams.

6. Agent requests — time-off, swaps, preferences

Exceptions explain deviations after the fact; requests are how agents ask for changes to the schedule before the deviation happens, and how supervisors keep the loop two-sided. They queue on the Approval queue tab and on the API under /wfm/requests, as a discriminated union on type:
The three types behave differently, and the differences are where the two-sidedness lives:
  • Time-off enters pending immediately. If the tenant has an active pto leave policy, the submit response also surfaces the agent’s remaining balance and how many hours this request would consume — the balance is informative at submit and authoritative at approve: an approval that would overdraw the balance is blocked with 409 INSUFFICIENT_LEAVE_BALANCE, and a successful approval posts the debit atomically. Approving also marks the overlapping assignment rows time_off, so the adherence engine does not penalize the approved absence.
  • Shift swap enters awaiting_counterparty — the named counterparty agent never asked to swap, so ratifying without their consent is the unilateral-reassign defect this state machine prevents. Only the counterparty can move the request to pending, with POST /wfm/requests/{id}/accept-swap; approve and deny gate on pending, so a swap that has not been accepted cannot be ratified. On approval the two agents’ scheduled assignments are exchanged atomically so a half-swap is never observable.
  • Preference enters pending and stays free-form — a supervisor uses it as a signal when building the next schedule; nothing is mutated automatically.
Reviewers decide with POST /wfm/requests/{id}/approve or /deny (both take an optional note), and the requester can cancel from pending or awaiting_counterparty with POST /wfm/requests/{id}/cancel. Every list and read endpoint applies the same scope: managers see all rows; agents see only their own — and agents reading a peer’s request get a 404, not a 403, so the endpoint does not leak that the request exists.

7. Worked example — one 30-minute incident

It is a Saturday morning and the retail queue is scheduled with four agents; one of them, agent 12, is late after a bus breakdown. The supervisor is watching the intraday staffing tab and the breach feed. 09:12 — The breach feed surfaces agent 12 with continuous_ooa_seconds accumulating past the five-minute default threshold: GET /wfm/rta/breaches shows one agent, breach_count: 1, current_state: "offline". The supervisor gets the nudge list down to one name. 09:14 — The supervisor files an adherence exception on the agent’s behalf (managers may file for any agent; agents themselves can file the same request under their own identity):
09:18 — The queue holds one pending exception. The supervisor approves it with a note; the exception credits the off-schedule window back into adherence, so the late arrival does not drag the day:
09:31 — The agent arrives and sets their state to online. The next RTA tick clears the breach; the breach feed returns to zero; the exceptions queue has one resolved row with an auditable note; the day’s adherence ratio, computed with the approved exception credited, reflects the half hour as excused rather than as 30 minutes of unexplained absence. Without the exception, the same 30 minutes would read as non-adherent through the agent’s week-end review.

8. Operational playbook

Three habits keep the day-of loop running well, and each maps to one of the surfaces above:
  • Shrink the exceptions queue at handover. A pending exception is a deviation still marked non-adherent. Deciding every pending exception before a supervisor hands over — and again before a team’s week is locked for review — keeps per-agent numbers honest and keeps the trends view from drifting. The queue tolerates one pending decision per row, so two supervisors deciding in the same minute get a clean 409 on the loser rather than a double-credit.
  • Nudge on the breach feed, not the ratio. The intraday ratio is a lagging indicator; it moves after the deviation has been running. The breach feed is the leading one: it surfaces the first tick of an off-schedule state that crosses the duration threshold. Coach from the threshold-tick onward — a five-minute nudge prevents the twenty-minute absence — and save the ratio view for end-of-day review.
  • Measure shrinkage from the requests, not guesswork. Approved time-off and denied time-off both tell you which hours never land as productive work; approved exceptions tell you which deviations were management-caused. The shrinkage report (and its input to capacity planning) reads the same events the adherence engine scores, so excusing an exception or approving a time-off request changes the next forecast’s shrinkage figure the same day, not the next planning cycle.

9. Production checklist

Run this once when you stand the day-of loop up, and again any time the numbers look wrong:
  • Seeded schedule: at least one assignment in scheduled/swapped spans today. The dashboards evaluate the assignment list — nothing to score returns empty, not zero.
  • Live agent state feed: agents consistently set their ACD/aux state. Spot-check one agent’s intraday timeline against their schedule; if their aux feed is blank, fix the feed before approving any exceptions — you would be excusing unmeasured time.
  • Queue-scoped supervisors: each supervisor role has queue mappings. A supervisor with no mappings fails closed and sees an empty breach list and an empty stream.
  • Threshold is deliberate: the breach feed’s default 5-minute threshold suits most teams. If Monday’s queue is staffed on a tighter band, set threshold_minutes explicitly (1–480 accepted).
  • Notes on every decision: approve, deny, and cancel carry an optional note; leave it every time. The note is the six-month-later audit trail between “approved” and “why”.
  • Role split: the dashboards run on wfm:read, self-serve filings run under the caller’s own identity, and approve/deny/award actions run on an owner or admin key. Do not put a management key on an agent-facing client.

See also