Lone Worker App Overview
Safety check-ins and one-tap SOS for frontline workers, built on a guaranteed escalation engine — wired into the shift app your team already carries.
What is the Lone Worker App?
Lone Worker makes safety a property of the app workers already use, instead of a separate panic-button app they have to remember to carry. A worker on a covered shift gets timed “I’m safe” check-ins and a one-tap SOS; a missed check-in or an SOS opens an alert that climbs a configured responder roster via push, SMS, and voice until a human acknowledges it — with a guaranteed dead-man’s switch if nobody does. Every step is written to an immutable audit trail.
Core Value Proposition:
- 🛡️ Guaranteed escalation — Every alert is owned by a human or surfaced as a loud, broadcast dead-man’s event. Never a silent drop.
- 📍 Right responders, right place — Alerts route to a site/team-scoped responder roster, not up an org chart that has nothing to do with who’s nearby.
- 🔗 Integrated, not bolted-on — Shifts knows who’s on, when, and where; Safety Hub receives incidents; the Inbox surfaces actionable alerts.
- 🧾 Compliance-grade trail — Every notification, acknowledgement, and resolution is recorded and exportable for EHS / regulator review.
Key Concepts (How It Works)
If you only read one section, read this — it explains the model behind the screens, and it’s what the in-app AI agent uses to answer “how does X actually work?”
The core loop: trigger → alert → escalate → acknowledge → resolve
Everything in Lone Worker is one small state machine. A trigger (an SOS tap, a missed check-in, or a reported floor issue) raises an alert. The alert climbs the tiers of a responder roster — paging each rung and waiting for a response — until a responder acknowledges it (takes ownership; the climb stops). A responder then resolves it with an outcome. If the alert climbs every tier and nobody acknowledges, it ends in exhausted and fires the dead-man’s switch.
Two invariants hold no matter what:
- Acknowledgement is mandatory — an alert is owned, not merely sent. Until someone acknowledges, it keeps climbing.
- No silent terminal state — every alert ends either
resolvedorexhausted, andexhaustedis loud.
(Grounded in LoneWorker::EscalationEngine and the LoneWorker::Alert state set: raised → notifying → acknowledged → resolved, or → exhausted.)
What makes a shift “covered” (why check-ins don’t start for everyone)
Turning the app on does not start prompting every worker. Timed check-ins arm for a worker on an active shift only when a responder roster resolves for that shift — i.e. an admin has configured who responds for that site, team, or shift. That roster is the deliberate opt-in: no roster, no check-in prompts. Clock-in arms the first check-in; clock-out cancels any armed one.
SOS is the exception — it is always available, on or off shift, even when no roster exists. If nothing resolves, an SOS routes straight to the org’s safety-admin “break-glass” set, so an emergency is never swallowed by a configuration gap.
(Grounded in LoneWorker::CheckInScheduler#ensure_armed — it returns early unless RosterResolver finds a roster — and EscalationEngine#rungs_for’s break-glass fallback.)
The three triggers are different, but escalate the same way
| Trigger | How it starts | Location | Notes |
|---|---|---|---|
| SOS | Worker taps it deliberately | Captured at trigger time (if enabled) | On or off shift |
| Missed check-in | Automatic — the worker didn’t answer an armed “I’m safe” prompt within its grace window | From the shift context | Detected by a guaranteed background job, independent of the app being open |
Floor issue (line_jam) |
Worker reports a shop-floor / equipment issue | None (they’re on premises) | Non-emergency; same roster escalation |
All three raise an alert that rides the same roster ladder. (geofence and no_checkout are reserved for a future release and are not yet active.)
What makes someone a responder, a manager, or a safety admin
This is the distinction most people get wrong. There are really three overlapping capabilities, and they’re determined differently:
- Any member (a “worker”) — anyone with access to the app. They can trigger SOS, answer their own check-ins, and see their own safety status and alerts. That’s it.
- Responder — not a job role; it’s membership on a roster tier. You become a responder by being added to a tier of a roster, regardless of your title. A responder can open, acknowledge, and resolve the alerts on rosters they belong to (which exposes the worker’s trigger-time location).
- Safety admin — an org Admin/Owner, or someone granted app-admin for Lone Worker. Safety admins see all alerts company-wide, configure everything, and receive the dead-man’s switch.
There’s also a tenant setting, “Who can manage rosters & escalation policy?” (admins_only / any_user). It gates who can configure rosters, check-in schedules, escalation policy, and analytics. It does NOT decide who can respond to alerts. Even set to any_user, it never grants access to an alert’s detail (and the worker’s live location) — responding is always gated on responder-membership or safety-admin, precisely so a “management” toggle can’t hand every worker’s whereabouts to the whole company.
(Grounded in LoneWorkerAppConfigurable#lone_worker_can_manage? vs Apps::LoneWorker::AlertsController#can_respond_to? — the code comments spell out that alert response deliberately does not key on who_can_manage.)
Acknowledge vs Resolve — and why a worker can’t acknowledge their own SOS
These are two separate steps, and they’re easy to conflate:
- Acknowledge = a responder takes ownership. The first ack wins, and it stops the climb. The emergency is now someone’s job.
- Resolve = closing the alert with an outcome:
safe,false_alarm, orincident. Resolving asincidentrequires a note and can open a Safety Hub incident record.
The worker who raised the alert cannot acknowledge it — doing so would silently halt escalation on their own emergency. They can, however, cancel their own alert as a false alarm (for an accidental SOS). The cancellation still writes an audit event; nothing is ever deleted.
(Grounded in AlertsController#authorize_acknowledge! / #authorize_resolve! and EscalationEngine#acknowledge / #resolve.)
Responder rosters vs check-in schedules — two separate configs
- A responder roster answers “who gets paged, in what order, on what channels?” — scoped to a site, team, or specific shift, holding ordered tiers of members (each tier has its channels and its acknowledgement timeout).
- A check-in schedule answers “how often do I prompt, and how long is the grace window?” — scoped to a site or team only (not a shift). When none is set, the per-tenant defaults apply.
For any given shift, the most specific active scope wins: a shift-specific override beats a team roster, which beats a site roster. If nothing resolves, alerts fall through to the org break-glass set.
(Grounded in LoneWorker::RosterResolver (shift → team → site) and CheckInScheduler#resolve_schedule (team → site).)
What “exhausted” means and the dead-man’s switch
If an alert climbs every tier and still nobody acknowledges, it ends in exhausted — and that is deliberately loud. A non-suppressible broadcast (push + email + SMS + voice) goes to every safety admin: “an alert exhausted the ladder with no acknowledgement — intervene now.” This is not a tenant toggle — an admin cannot turn the break-glass off. It is the concrete form of Invariant 2: an alert is never quietly dropped.
(Grounded in EscalationEngine#do_exhaust / #deliver_dead_mans, and the schema note that the dead-man’s switch is intentionally not configurable.)
Who can see the “who’s at risk right now” feed
The active-alert list reveals who across the company currently has an SOS or overdue check-in — a sensitive “who’s in distress now” feed. So it’s viewer-scoped: safety admins see all of it; everyone else sees only their own alerts plus alerts on rosters they respond to. The same scoping applies inside the AI agent — a bare member can’t enumerate the company-wide distress roster through Ask AI.
(Grounded in LoneWorkerAppConfigurable#scope_alerts_for_viewer and LoneWorkerAgent#visible_alerts.)
Location is captured at trigger time only
There is no continuous background GPS tracking. A single best-available fix (plus accuracy) is captured only when an SOS fires, and only if the tenant has location capture enabled. A malformed or out-of-range coordinate is simply dropped — it never blocks the SOS and never lands as junk in the audit trail or an SMS body.
(Grounded in LoneWorkerController#trigger_sos (sos_requires_location? + parse_coord) and EscalationEngine#normalize_coord.)
At a Glance
| 🔗 Integrations | 📱 Mobile Ready | 🤖 AI Agent | 🧾 Audit Trail |
|---|---|---|---|
| Shifts · Safety Hub · Inbox · Live Assist · Notifications | ✅ Yes (/m/ surface + REST API) |
✅ Read-only via Ask AI | ✅ Per-alert, exportable |
Perfect For:
- 🏭 Frontline & field workers who work alone or at risk — gas stations, field service, utilities, late-shift retail, security, home-health visits, manufacturing floors.
- 🦺 Safety / EHS admins who configure responder rosters, check-in cadence, and escalation policy, and review the exportable audit trail.
- 👤 On-site responders who acknowledge and resolve alerts for the rosters they’re on.
How It Works
Escalation flow
┌──────────────────────────────────────────────────────────────────────────┐
│ LONE WORKER ESCALATION │
├──────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ TRIGGER │──▶ │ ALERT RAISED│──▶ │ NOTIFY │ │
│ │ SOS / │ │ roster + │ │ Tier 1 │ │
│ │ missed / │ │ location │ │ push + SMS │ │
│ │ floor issue │ └─────────────┘ └──────┬──────┘ │
│ └─────────────┘ │ no ACK within timeout │
│ ▼ │
│ ┌─────────────┐ │
│ │ Tier 2…N │ push+SMS+voice │
│ └──────┬──────┘ │
│ ┌───────────────────┴─────────────┐ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ ACKNOWLEDGED│──▶ RESOLVED │ EXHAUSTED │ │
│ │ "I've got │ safe / false │ dead-man's │ │
│ │ this" │ alarm / incident │ switch → │ │
│ └─────────────┘ │ safety admin│ │
│ └─────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
Integration ecosystem
┌─────────────────┐
│ LONE WORKER │
└────────┬────────┘
│
┌────────────┬─────────────┬─────┴──────┬─────────────┬────────────┐
▼ ▼ ▼ ▼ ▼ ▼
┌───────────┐┌───────────┐┌───────────┐┌───────────┐┌───────────┐┌───────────┐
│ Shifts ││ Safety Hub││ Inbox ││ Notif. ││Live Assist││ Ask AI │
│ who's on, ││ incident ││ actionable││ push/SMS/ ││ SOS video ││ read-only │
│ when/where││ handoff ││ alerts ││ voice ││ to expert ││ agent │
└───────────┘└───────────┘└───────────┘└───────────┘└───────────┘└───────────┘
Key Features
🚨 One-Tap SOS
A worker can raise an SOS in one tap — on- or off-shift. Location is captured at trigger time only (a single best-available fix), and the worker’s screen shows the alert state so they know help is being notified.
| Feature | Description |
|---|---|
| One-tap trigger | SOS button on the worker surface, on or off shift |
| Location at trigger | Single fix + accuracy captured when SOS fires (no continuous tracking); malformed coordinates are dropped, never blocking the SOS |
| Cancel = false alarm | Cancelling still writes an audit event; resolved as false_alarm, never deleted |
Use Case: A field technician enters a customer’s basement, hits SOS when a panel arcs — responders are notified with the captured location while the worker decides whether to also call emergency services.
💡 Pro Tip: Location capture is configurable per tenant in Settings — leave it on for fastest responder dispatch.
Evidence: app/views/apps/lone_worker/my_safety.html.erb, Apps::LoneWorkerController#trigger_sos, LoneWorker::EscalationEngine#raise_alert.
🛠️ Report a Floor Issue
A worker-raised, non-emergency operational alert (line_jam) for a shop-floor or equipment problem. It rides the same responder escalation as an SOS, but skips the browser location prompt — the worker is on premises, so the shift/site context is what matters, and a geolocation permission dialog would just add friction. Resolving one as an incident opens an equipment-failure Safety Hub record (not a security one).
Use Case: A line operator sees a jam that needs a supervisor and a maintenance tech — one tap notifies the site’s responder tier without dialing an “emergency.”
Evidence: Apps::LoneWorkerController#trigger_floor_issue, my_safety.html.erb (Report a floor issue card), LoneWorker::Alert::TRIGGER_TYPES, EscalationEngine#create_incident.
⏱️ Timed Safety Check-Ins
When a worker is on a covered shift, the system arms timed “I’m safe” prompts on a configured interval. Answering is one tap; a check-in not answered within its grace window becomes missed and raises an alert — detected on a guaranteed cadence, independent of whether the app is in the foreground.
| Feature | Description |
|---|---|
| Configured cadence | Interval + grace per site/team, or per-tenant defaults |
| Covered shifts | A shift is covered when a responder roster resolves for it |
| Guaranteed detection | A dedicated background job sweeps overdue check-ins, then retires (never alerts) ones stale beyond 24h |
| Auto re-arm | Answering “I’m safe” schedules the next check-in; clock-out cancels armed ones |
Evidence: LoneWorker::CheckInScheduler, LoneWorker::CheckInSchedulerJob, LoneWorker::MissedDetectorJob, LoneWorker::CheckInResponder, LoneWorker::CheckInSchedule model.
📡 Guaranteed Escalation Engine
The heart of the app. Every trigger is just an input; what happens after is a real state machine. An alert climbs a roster’s tiers — each with its own channels and acknowledgement timeout — until a responder takes ownership.
| Feature | Description |
|---|---|
| Tiered ladder | Climbs Tier 1 → 2 → N, honoring per-tier channels (push/SMS/voice) and timeout |
| Mandatory acknowledgement | An alert is owned, not just sent — first ACK wins and stops the climb |
| Dead-man’s switch | If the ladder is exhausted with no ACK, a loud, non-suppressible event broadcasts to safety admins |
| Self-healing | A background driver runs on its own guaranteed cadence and re-primes any alert stuck without a live timer |
| Resolution | Closed as safe, false_alarm, or incident (incident requires a note) |
Reliability floor: push and the Inbox item are an accelerant; SMS and voice are the floor — sent directly so a suppressed in-app channel can never silently swallow a safety page.
Evidence: LoneWorker::EscalationEngine (raise/acknowledge/resolve/advance/recover), LoneWorker::EscalationDriverJob, LoneWorker::Alert / LoneWorker::AlertEvent models.
🗂️ Site/Team/Shift Responder Rosters
Responders are a configured, location-scoped roster — because your boss is rarely your nearest responder. Resolution at trigger time picks the most specific active scope (shift override → team → site); if nothing resolves, the alert routes straight to the org safety-admin break-glass set.
| Feature | Description |
|---|---|
| Scope by site / team / shift | Most-specific active scope wins |
| Ordered tiers + members | Each tier has channels, an ACK timeout, and its responders |
| Break-glass fallback | No roster → safety admins are paged; an alert is never left with nobody to notify |
Evidence: LoneWorker::RosterResolver, LoneWorker::Roster / RosterTier / RosterMember models, Apps::LoneWorker::RostersController.
🎥 Live Video to the Responder (Live Assist)
When enabled, acknowledging an alert can open a live video channel between the worker and the responder — the worker shares point-of-view while the responder assists — with a join link sent to the acknowledging responder. It’s best-effort and strictly additive: a video failure can never block the acknowledgement, and the recording attaches to the alert as evidence.
💡 Requires the Live Assist app + a configured provider, and the Open Live Video to Responder on SOS Acknowledgement toggle (off by default).
Evidence: LoneWorker::EscalationEngine#open_sos_video, LiveAssistable concern on LoneWorker::Alert, live_assist_sos_video config key.
📊 Analytics & Insights
Admins get a reliability-focused dashboard: total alerts, acknowledgement rate, average ACK latency, unresolved (exhausted) count, a 14-day alert-volume chart, and breakdowns by trigger, outcome, and check-in completion — all exportable as CSV.
Evidence: Apps::LoneWorker::AnalyticsController, app/views/apps/lone_worker/analytics/index.html.erb.
🧾 Immutable Audit Trail
Every alert carries an append-only event log: one row per state change, per-channel notification attempt (with provider result), acknowledgement, and resolution. Rows are read-only once written — the compliance-grade record EHS teams and regulators review, exportable as CSV from the Alerts list.
Evidence: LoneWorker::AlertEvent (readonly? guard), Apps::LoneWorker::AlertsController#export.
🔗 Integrations
| Integration | Capability |
|---|---|
| Shifts & Scheduling | Source of truth for who’s on, when, and where; clock-in/out arms and cancels check-ins |
| Safety Hub | Resolving an alert as incident opens a Safety Hub incident record with the alert’s context |
| Inbox | Each alert is an actionable Inbox item with an inline “I’ve got this” acknowledge action |
| Notifications | Push / SMS / voice fan-out, with SMS/voice as the reliability floor |
| Live Assist | Optional live video from worker to responder on acknowledgement |
| REST API | Native-app parity: safety status, trigger SOS, answer check-in |
Evidence: LoneWorker::EscalationEngine#create_incident, Inbox::Publisher calls, SmsService / SendVoiceNotificationJob, Api::V1::LoneWorker::SafetyController / AlertsController.
🤖 AI Agent (Ask AI)
A read-only operational assistant in Ask AI. Ask it who’s at risk right now, an alert’s escalation timeline and outcome, your own safety status, or responder-roster coverage. It can acknowledge an alert on your behalf — but that write is authorization-checked exactly like the responder surface (you must be a responder or admin), and the app shows its own confirmation.
- List active alerts — who’s notifying / acknowledged (viewer-scoped)
- Explain an alert — full escalation timeline and outcome
- My safety status — check-in due, active SOS
- Responder coverage — rosters by site/team (managers/admins only)
- Acknowledge — the one write; authorization-gated
It deliberately cannot trigger an SOS or resolve an incident from chat — those stay explicit human actions.
Evidence: Agents::LoneWorkerAgent, Agents::ToolRegistry::LoneWorker (RISKY_TOOLS = %w[acknowledge_lone_worker_alert]).
🔔 Notifications
| Type | Description |
|---|---|
| Tier notification | Push / SMS / voice to the current responder tier when an alert climbs |
| Acknowledgement | The alert state updates; climbing stops (and optional Live Assist video opens) |
| Dead-man’s broadcast | Safety admins are paged (push + email + SMS + voice) when escalation is exhausted |
User Roles & Permissions
| Role | Capabilities |
|---|---|
| Worker (any member) | Trigger SOS, report a floor issue, answer check-ins, view their own safety status and alerts, self-cancel their own alert as a false alarm |
| Responder (roster-tier member) | Open an alert they’re rostered for, acknowledge it, resolve it with any outcome |
| Manager | Respond to alerts; view the alert list; if granted management, configure rosters/schedules and see analytics |
| Admin / app admin (safety admin) | See all alerts, configure rosters, check-in schedules, and escalation policy; review analytics; manage settings; receive the dead-man’s switch |
Evidence: LoneWorkerAppConfigurable (who_can_manage gate, scope_alerts_for_viewer), LoneWorkerFeatureAccess (role-gated tabs), Apps::LoneWorker::AlertsController#authorize_view! / #authorize_acknowledge! / #authorize_resolve!.
How We Compare
Standalone lone-worker apps ship a panic button — but the worker carries them in addition to the shift/comms app they already use, and the responder list is generic. Lone Worker makes safety a property of the platform.
| Feature | MangoApps Workforce | OK Alone | StaySafe | Blackline Safety |
|---|---|---|---|---|
| One-tap SOS / panic | ✅ | ✅ | ✅ | ✅ |
| Timed check-ins + missed-check escalation | ✅ | ✅ | ✅ | ✅ |
| SMS/voice fallback when push fails | ✅ | ✅ | ✅ | ✅ |
| Shift-aware coverage (built-in scheduling) | ✅ | ❌ | ❌ | ❌ |
| Incident handoff to safety/EHS module | ✅ | ⚡ | ⚡ | ✅ |
| Live video from worker to responder | ✅ | ❌ | ⚡ | ⚡ |
| Automatic man-down / fall detection | ❌ | ✅ | ✅ | ✅ |
| Dedicated wearable / satellite device | ❌ | ⚡ | ❌ | ✅ |
| Legend: ✅ Included | ❌ Not Available | ⚡ Limited / add-on |
Why MangoApps Workforce?
- 🔗 Unified platform — Lone Worker rides the same Shifts, Notifications, and Safety Hub your team already runs, so safety isn’t a second app to carry.
- 📍 Routing that matches reality — Site/team responder rosters page who’s actually nearby and on-call.
- 🧾 Audit built in — A compliance-grade trail for every alert, exportable for EHS review.
⚠️ Honest note: Sensor-dependent features — automatic man-down and fall detection — are intentionally not included. They require hardware/OS behavior a stock phone can’t reliably deliver; we deferred them rather than over-promise. SOS and missed-check-in escalation cover the core.
Getting Started
For Workers
- Open Lone Worker → My Safety (or the
/m/mobile surface on a phone). - Answer the “I’m safe” check-in when prompted.
- Tap SOS any time you need help — on or off shift. Use Report a floor issue for a non-emergency equipment/line problem.
For Responders
- When an alert reaches you (push / SMS / voice / Inbox), open it.
- Tap “I’ve got this” to acknowledge and stop it climbing.
- Resolve it as Safe, False alarm, or Incident with a note.
For Administrators
- Responder Rosters — create a roster scoped to a site, team, or shift; add tiers (channels + ACK timeout); add responders.
- Check-in Schedules — set the interval and grace window for a site/team (or rely on the per-tenant defaults).
- Settings — tune escalation timeouts, SOS location capture, the “who can manage” permission, optional Live Assist video, and the Safety Hub handoff.
Best Practices
- ✅ Build at least a two-tier roster per covered site, with voice on the final tier.
- ✅ Keep rosters current — a tier whose members are all off-shift can’t respond.
- ✅ Remember that coverage = a roster — enabling the app alone won’t start check-ins; a site/team/shift roster must resolve.
- ✅ Decide your positioning with legal: market it as a “safety check-in tool,” not a replacement for emergency services.
- ✅ Use Load sample data in Settings to see a working roster + alert before you configure your own (sample data never fires real notifications).
Frequently Asked Questions
Q: Does Lone Worker replace 911 / emergency services?
A: No. It assists escalation to your own responders and shows the worker that help is being notified. It is not a PSAP and does not dial emergency services on the worker’s behalf.
Q: Does it track workers’ location continuously?
A: No. Location is captured only at trigger time (when SOS is tapped). There is no continuous background GPS tracking, and location capture is itself a per-tenant setting.
Q: I turned the app on but nobody’s getting check-ins — why?
A: Check-ins only arm on a covered shift, and a shift is covered only when a responder roster resolves for its site, team, or the shift itself. Create a roster for that site/team and check-ins will start arming at clock-in. (SOS, by contrast, works with no roster and break-glasses to safety admins.)
Q: What happens if no responder acknowledges an alert?
A: The alert climbs every configured tier; if the ladder is exhausted with no acknowledgement, a loud, non-suppressible dead-man’s-switch event is logged and broadcast (push + email + SMS + voice) to the org’s safety admins — it’s never silently dropped, and it can’t be toggled off.
Q: Can I acknowledge my own SOS?
A: No — acknowledging is a responder taking ownership, and letting the worker do it would silently stop escalation on their own emergency. You can cancel your own alert as a false alarm if you triggered it by accident.
Q: What does the app depend on?
A: Shifts & Scheduling provides who’s on, when, and where. Notifications use the platform’s push/SMS/voice channels. Resolving an alert as an incident hands off to Safety Hub. Optional live video uses Live Assist.
Related Resources
- Safety Hub App Overview — Incident management that receives Lone Worker handoffs
- Shifts & Scheduling App Overview — The coverage source Lone Worker builds on
- On-Call Management App Overview — Related responder-rotation tooling
Lone Worker — because the safest panic button is the one already in your worker’s pocket.