> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent wellness and flight risk

> Read the passive wellness and attrition-risk surfaces: two lenses (wellness score vs the distress button), the five-strain inputs, every query parameter, band thresholds, the flight-risk pairing, a supervisor runbook that stays non-punitive, and a production checklist.

# Agent wellness and flight risk

Contact centers lose agents to burnout long before anyone files a resignation. The distress button — the one-tap panic control on the softphone — catches the acute moment an agent asks for help mid-call, but it is agent-initiated and binary: an agent sliding toward attrition over weeks rarely presses it. The wellness surface closes that gap by computing a per-agent strain score from data Orbit already captures, and the flight-risk surface takes the same idea one step further by tracking whether those signals are trending worse.

This guide is for supervisors and WFM managers. It walks the two lenses, the role gate that decides who sees what, the five strain inputs behind each score, every endpoint parameter, the band thresholds, and a supervisor runbook for acting on a nudge without turning a wellbeing signal into a performance flag. The full endpoint shapes live on the [WFM API](/api-reference/wfm) page — this guide is the narrative for the wellness and attrition half of that reference.

Neither surface stores anything. Both are derived, on-the-fly readings over tables your tenant already populates — call records, adherence events, shrinkage reports, distress alerts. There are no new biometric feeds, and nothing is captured about an agent that the platform was not already recording for operations.

## 1. The two lenses — wellness vs the distress button

The [agent distress alert model](/concepts/agent-distress-alert-model) defines the reactive lens: one press of the panic button persists a supervisor alert, forces the call into a recorded state, and pages the supervisor. It is instant, acute, and agent-initiated. Its role is safety in the live moment, not trendspotting.

The **wellness** lens is the passive counterpart. `GET /api/v1/wfm/agent-wellness` re-aggregates data Orbit already records — call load, after-call-work overrun, occupancy, adherence pressure, and any raised distress events — and runs the aggregate through a scoring kernel that returns a wellness score per agent. A supervisor reads a grid where the most strained agents sort to the top, with a recommendation keyed to the top driver: suggest a break, lighten routing, review the schedule, or check in one-on-one.

The **flight risk** lens widens the time horizon. `GET /api/v1/wfm/agent-flight-risk` splits a longer window into two halves — recent vs prior — and weights how much worse the recent half looks, because a worsening trajectory is the actual leading indicator of attrition. A busy agent who is flat is not a flight risk; an agent whose adherence, shrinkage, and break-state time are all climbing is.

Two rules hold across both lenses:

* **Wellness is non-punitive by design.** The score drives workload relief — breaks, lighter routing, a schedule-fit conversation — never discipline. The recommendation copy the API returns is written to be read aloud to the agent.
* **Distress events feed both surfaces.** A single distress-button press in the window already contributes meaningful strain to wellness and risk to flight-risk, so the passive read never ignores the reactive one.

## 2. Role gate — who sees what

Both endpoints admit `owner`, `admin`, and `supervisor` roles. Wellness also admits the per-agent (`developer` / `viewer`) seats, and the role gate is what separates them:

| Caller role                                           | Wellness grid      | Flight-risk grid |
| ----------------------------------------------------- | ------------------ | ---------------- |
| `owner`, `admin`, `supervisor`                        | Every agent        | Every agent      |
| Agent seat (`developer`, `viewer`, or any other role) | Their own row only | Empty grid       |

The asymmetry is deliberate. An agent seeing their own wellness score is a self-care signal — they can ask for a break before the supervisor notices. Attrition risk, by contrast, is a manager-retention conversation: letting an agent see their own "likely to leave" number would poison the very check-in the playbook recommends, so flight-risk returns nothing to restricted roles. A restricted caller whose identity cannot be resolved gets an empty wellness result too — the gate fails closed.

## 3. The five wellness inputs

Every wellness score decomposes into five strain signals, each normalised to 0–100 where higher means more strain. The weighted blend inverts to a 0–100 wellness score where higher is healthier. The five inputs:

* **Call load** — answered calls, total talk time, and back-to-back density (answered calls separated by less than `short_recovery_gap_seconds`) in the window. Blended as 50% volume, 30% talk-time, 20% back-to-back share against the per-day baselines.
* **ACW overrun** — the share of `wrap_up` adherence events whose duration exceeded `acw_ceiling_seconds`. Sustained overrun points at tooling or escalation blockers, not at a slow agent.
* **Occupancy** — occupied time (`on_call` + `wrap_up`) over signed-on time, accruing strain only above `occupancy_healthy_ceiling` (default 0.85). Occupancy below the ceiling contributes zero strain — a busy-but-recovering agent is not flagged.
* **Adherence pressure** — the share of evaluated adherence events marked non-adherent. This is treated as a workload-fit signal, never a performance flag.
* **Distress** — distress-button events raised in the window. High-signal, low-frequency: a single press lands at 50 strain and saturates by the third.

Flight risk uses a different five — **shrinkage** (mean unscheduled-absence ratio), **adherence** breaches, **aux escape** (signed-on time in unavailable/break/lunch states), **burnout** (occupancy above the healthy floor, or any distress event), and **trend** (recent half vs prior half of the first three). Only worsening deltas accrue trend risk — a flat or improving trajectory contributes zero.

## 4. The wellness endpoint in full

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/wfm/agent-wellness?window_days=7" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Query parameters, all optional:

| Parameter                     | Default | Bounds | Effect                                                                     |
| ----------------------------- | ------- | ------ | -------------------------------------------------------------------------- |
| `window_days`                 | 7       | 1–30   | Rolling window the counters are aggregated over.                           |
| `acw_ceiling_seconds`         | 120     | 1–3600 | Wrap-up duration above which an event counts as ACW overrun.               |
| `short_recovery_gap_seconds`  | 15      | 0–600  | Gap below which two consecutive answered calls count as back-to-back.      |
| `nudge_threshold`             | 55      | 0–100  | Wellness score below which the `needs_nudge` flag and recommendation fire. |
| `occupancy_healthy_ceiling`   | 0.85    | 0–1    | Occupancy ratio above which strain starts accruing.                        |
| `calls_per_day_baseline`      | 40      | 1–1000 | "Full but healthy" answered calls per day for the call-load ratio.         |
| `talk_hours_per_day_baseline` | 5       | 0.5–24 | "Full but healthy" talk hours per day.                                     |
| `weight_call_load`            | 0.25    | 0–1    | Blend weight for call-load strain.                                         |
| `weight_acw_overrun`          | 0.2     | 0–1    | Blend weight for ACW overrun strain.                                       |
| `weight_occupancy`            | 0.2     | 0–1    | Blend weight for occupancy strain.                                         |
| `weight_adherence_pressure`   | 0.15    | 0–1    | Blend weight for adherence-pressure strain.                                |
| `weight_distress`             | 0.2     | 0–1    | Blend weight for distress strain.                                          |
| `limit`                       | 100     | 1–500  | Page size — one row per active agent.                                      |
| `cursor`                      | —       | —      | Opaque page token; pass the previous response's `next_cursor`.             |

Weights re-normalise internally, so passing one weight alone re-balances that signal against the others without you re-supplying all five. The response envelope carries `rows` (one per agent: identity, raw counters, and the score block), `counts` (agents per band plus `needs_nudge`), `config` (the resolved coefficients — pass it back to reproduce the same math), `window` (`days`, `since`, pagination state), `next_cursor`, and `generated_at`. Rows sort worst-first, so the supervisor's triage list is the top of the first page.

A fuller wellness read over a 7-day window, tuned to a queue where 90 seconds of wrap-up is the norm and occupancy past 80% hurts:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/wfm/agent-wellness?window_days=7&acw_ceiling_seconds=90&occupancy_healthy_ceiling=0.8&nudge_threshold=60&limit=50" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Each row in `rows` carries:

```json theme={null}
{
  "agent_id": "user_agent_12",
  "display_name": "Amira Okafor",
  "wellness_score": 48,
  "strain_score": 52,
  "band": "elevated",
  "needs_nudge": true,
  "signals": {
    "call_load": 61.2,
    "acw_overrun": 44.0,
    "occupancy": 38.5,
    "adherence_pressure": 12.0,
    "distress": 0
  },
  "drivers": [
    { "signal": "call_load", "strain": 61.2, "weight": 0.25, "contribution": 15.3 }
  ],
  "recommendation": {
    "action": "suggest_break",
    "message": "Sustained back-to-back call load — suggest a smart break and steer new contacts to other agents."
  },
  "occupancy_ratio": 0.88
}
```

`drivers` is the per-signal breakdown sorted by contribution — that is the supervisor's answer to "why is this agent flagged." `inputs` echoes the raw counters behind the signals when you want to sanity-check a score.

## 5. Band thresholds and the `nudge_threshold`

The wellness score lands in one of four bands:

| Band       | Wellness score | Reading                                            |
| ---------- | -------------- | -------------------------------------------------- |
| `healthy`  | 70–100         | No strain pattern — leave the agent alone.         |
| `monitor`  | 50–69          | Mild strain; watch the trend, no intervention.     |
| `elevated` | 30–49          | Strain is real; a supportive action is worth it.   |
| `at_risk`  | 0–29           | Sustained strain; act this week, not this quarter. |

The `nudge_threshold` sits on top of the bands and decides which rows carry `needs_nudge: true` plus a recommendation. The default of 55 means the bottom of the `monitor` band and anything worse nudges; raising it to 60 tightens the trigger to only reliably-strained agents, lowering it to 40 makes the nudge rare. The shared example below runs the same roster with the shared example value `nudge_threshold=60`:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/wfm/agent-wellness?window_days=7&nudge_threshold=60" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Because the band boundaries are fixed (70 / 50 / 30) and the nudge threshold is a per-request knob, you can compare thresholds across supervisors by simply re-calling with a different value — the scoring math is deterministic, and `config` in the response tells you exactly which coefficients produced it.

The flight-risk sibling uses its own bands — `low` (0–29), `watch` (30–49), `elevated` (50–69), `high` (70–100) on the flight-risk score — with `alert_threshold` (default 60) gating `needs_alert`, plus one wellness has no analogue of: a data-sufficiency floor. `min_observations` (default 20 evaluated adherence events) marks rows `reliable: false` when the window is too thin, and no alert fires on thin data — false alarms are how attrition models lose supervisor trust.

## 6. Flight-risk pairing

Wellness tells you who is struggling now; flight risk tells you who is slipping over time. Run them together — wellness for the daily stand-up, flight risk weekly as the leading indicator:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/wfm/agent-flight-risk?window_days=30" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Query parameters, all optional:

| Parameter                                                                                         | Default                       | Bounds           | Effect                                                                                                      |
| ------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
| `window_days`                                                                                     | 30                            | 14–90            | Window split into recent vs prior halves. Attrition is slow-burn; under 14 days the halves are meaningless. |
| `alert_threshold`                                                                                 | 60                            | 0–100            | Flight-risk score at or above which `needs_alert` fires.                                                    |
| `min_observations`                                                                                | 20                            | 0+               | Evaluated events below which the row is unreliable and never alerts.                                        |
| `shrinkage_ceiling`                                                                               | 0.35                          | 0.01–1           | Mean shrinkage ratio at which shrinkage risk saturates.                                                     |
| `adherence_breach_ceiling`                                                                        | 0.3                           | 0.01–1           | Breach share at which adherence risk saturates.                                                             |
| `aux_escape_ceiling`                                                                              | 0.4                           | 0.01–1           | Aux-state share at which aux-escape risk saturates.                                                         |
| `occupancy_burnout_floor`                                                                         | 0.85                          | 0–1              | Occupancy above which burnout risk starts accruing.                                                         |
| `weight_shrinkage` / `weight_adherence` / `weight_aux_escape` / `weight_burnout` / `weight_trend` | 0.25 / 0.2 / 0.2 / 0.15 / 0.2 | 0–1              | Blend weights; re-normalised internally.                                                                    |
| `limit` / `cursor`                                                                                | 100 / —                       | same as wellness | Pagination.                                                                                                 |

Each row adds `trajectory_delta` — the signed composite of recent-vs-prior deltas, −100 to 100. Negative is improving, positive is worsening, and zero means flat. The playbook acknowledges improvement too: a reliably low-risk agent at `trajectory_delta <= -10` gets a recognition prompt, because retention is reinforced as much by catching good trajectories as by catching bad ones.

A 30-day pass alongside the wellness read:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/wfm/agent-flight-risk?window_days=30&alert_threshold=55&min_observations=30" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Interpreting the pairing: an agent `at_risk` on wellness but `low` on flight risk is having a bad week — fix the workload, not the retention plan. An agent `monitor` on wellness but `high` on flight risk is the expensive case the wellness lens alone misses — the trajectory says the wheel is coming off even if this week looks survivable. Elevated on both is the same finding confirmed twice.

## 7. Supervisor runbook — what a nudge means

A `needs_nudge` row is an instruction to the supervisor to relieve workload, and the `recommendation.action` narrows the instruction:

* **`suggest_break`** — top driver is call load or occupancy: route new contacts elsewhere and get the agent a real break. Today, not at the next schedule cycle.
* **`lighter_routing`** — ACW overrun is high: check for an escalation blocker or a tooling issue first. Wrap-up overrun means the work after the call is not finishing; it is rarely the agent's fault.
* **`review_schedule`** — adherence pressure: look at schedule fit. Adherence breaches drifting up across a whole week are a roster mismatch signal, and the recommendation copy says so.
* **`check_in`** — distress events in the window or flight-risk trend worsening: a supportive one-on-one. Not a performance conversation.
* **`none`** — wellness in a healthy range.

On the flight risk side, `playbook.action` carries the same intent with longer-horizon moves — `schedule_relief`, `coaching`, `workload_rebalance`, `check_in`, or `recognition` for the low-risk improver.

The framing matters and the API enforces it: messages are written to be read aloud to the agent. Treating wellness scores as a performance ranking is the fastest way to make agents never press the distress button, which destroys the one high-signal input both models depend on. A supervisor who acts on a nudge by relieving the workload makes the next nudge trustworthy; one who acts on it with a write-up makes the whole surface dishonest.

## 8. Production checklist

Before you rely on either surface operationally, walk this once:

* **Privacy posture stated to the team.** Wellness and flight risk read data the platform already records for operations — adherence events, call records, distress alerts — and compute on the fly with nothing persisted. Agents can see their own wellness score; flight risk is manager-only by design. State both facts in your team handbook before a supervisor reads any score aloud.
* **Non-punitive framing reviewed.** The recommendation and playbook copy are deliberately supportive. If your internal scorecards discuss these numbers, the wording should match the API's — workload relief, schedule fit, coaching, recognition.
* **Role gates audited.** Confirm `owner`/`admin`/`supervisor` intake is deliberate on your tenant — these roles see every agent. Agents (`developer`/`viewer` seats) see only their own wellness row and nothing on flight risk; a restricted caller with no resolved identity fails closed.
* **Baselines tuned once.** The defaults (40 calls/day, 5 talk hours/day, 85% occupancy ceiling) are a starting point. Tune `calls_per_day_baseline`, `talk_hours_per_day_baseline`, and `occupancy_healthy_ceiling` to your queue's reality, then pass the same values on every call — `config` in the response is your record of what you tuned to.
* **Thin-data discipline on flight risk.** Never act on a `reliable: false` row, and never lower `min_observations` into single digits. An attrition alert with twelve evaluated events behind it is noise with a name attached.
* **Adherence feed healthy.** Both surfaces lean on adherence events for occupancy and adherence-pressure signals. If agents do not set their aux state in the dialer or inbox, occupancy reads near zero and adherence pressure reads blank — fix the feed before drawing conclusions, the same prerequisite the [WFM workflows guide](/guides/wfm-workflows) calls out for scheduling.

## See also

* [WFM API](/api-reference/wfm) — endpoint reference for both surfaces
* [The WFM model](/concepts/wfm-model) — the six-domain concept map wellness sits inside
* [Agent distress alert model](/concepts/agent-distress-alert-model) — the reactive panic-button lens this guide's passive reading complements
* [Workforce-management workflows](/guides/wfm-workflows) — the planning-side guide (forecasts, schedules, intraday loop) the wellness surface rides on
* [Quality management program](/guides/quality-management-program) — performance scoring, kept separate from wellbeing by design
* [Error codes](/api-reference/error-codes) — the `422 VALIDATION_ERROR` shape on out-of-range parameters
