Skip to main content

Hunt and ring topologies: ring groups, paging, and find-me/follow-me

Answering “which person or device should ring for this inbound call” is a distribution problem with four distinct shapes in Orbit voice: a ring group (a named set of destinations dialed together under one strategy), a paging group (a one-way announcement fanned out to deskphones and app users), find-me/follow-me (an ordered per-user hunt chain that tries your devices one at a time), and a plain sequential hunt (call-forwarding’s flat fallback list). This page models each shape, explains how the resolver picks one member from a group, shows how registered-device presence prunes the dial list before strategy selection ever runs, and closes with a worked comparison of two strategies on the same group. For where these shapes plug into the wider call path, see Inbound voice routing; for the queue-side distribution of contact-center work, see The ACD queue model.

Ring-group distribution policies

A ring group is a reusable named set of ring destinations stored per organization, referenced from an inbound route or an IVR node. Each member is one of three kinds:
  • sip_username — a registered SIP device (deskphone or softphone) drawn from your SIP credentials.
  • pstn — an external E.164 phone number, always stored with the leading +.
  • ring_group — another ring group, so groups nest into trees (a team inside a department inside a business unit).
The group’s strategy decides how the dial engine picks among members: The three distribution strategies beyond simultaneous/sequential keep their fairness state in a shared, cross-pod store, so every API replica that handles a call against the same group sees the same ordering position:
  • Round-robin advances one cursor per group. Two calls placed in the same millisecond get different positions, so no two concurrent callers land on the same first ring target when avoidable.
  • Longest-idle records a last-selected timestamp per member. The next call picks the smallest timestamp; a member who has never been picked counts as idle since the beginning of time, so new members join the rotation immediately.
  • Fewest-calls keeps a per-member counter that is incremented only when a dial is actually emitted to that member. The next call picks the lowest count, with ties broken deterministically so replicas converge on the same pick.
All three degrade gracefully: if the shared state store is briefly unreachable, the picker falls back to the group’s first member rather than refusing to answer the inbound call. State expires after a day of inactivity, so lightly-used groups do not accumulate stale counters.

Members of zero, and empty-after-filtering

A group whose members all being filtered out (see presence below) leaves nothing to dial, and the route falls through to its fallback — typically voicemail — instead of ringing nobody and hanging up. Strategy selection only ever runs on members that survive the presence filter.

Nesting: how the resolver flattens a tree

When a group member is itself a group, the resolver expands it at dial time into leaf destinations (sip_username / pstn). Two guards keep a malformed tree safe:
  1. Cycle detection. Each expansion branch tracks which group ids it already visited; re-entering a visited group is logged and skipped, so a legacy circular config degrades to a partial dial list rather than an infinite loop.
  2. Depth cap. Expansion stops five levels deep. Operator-built groups cluster at one to three levels (team → department → business unit), and deeper than that is almost always a config mistake.
The same walk runs at write time in reject-the-save mode: when you create or update a group whose members would loop, the API responds 422 naming the looping chain, and the dashboard’s pre-save check can flag the cycle before you commit. A pre-flight endpoint (POST /voice/ring-groups/validate-cycle) lets the editor disable Save with an inline error naming the loop, instead of a post-submit failure. Duplicate destinations are warned about, not rejected, because overlaps are sometimes intentional: a home number shared across groups (sales-after-hours and support-after-hours both ringing the on-call cell), or the same number twice inside one group. Create and update responses carry a non-blocking warnings array naming the overlap so you can confirm or unwind it; a pre-flight endpoint (POST /voice/ring-groups/validate-warnings) surfaces the same list before the save lands.

Paging groups

A paging group broadcasts a one-way announcement — the classic “parking level three, gate closed” overhead page — to two member classes at once:
  • user_id members receive an in-app notification the softphone renders as “Incoming page from <group>”.
  • sip_username members are rung directly: each verified, enabled deskphone receives a server-initiated internal call that plays an optional chime, speaks the announcement, and hangs up. Deskphones have no app-user mapping (a raw SIP credential belongs to no user), so ringing is the only reachable path.
The deskphone leg is deliberately an internal user-to-user SIP call on Orbit’s own edge — no carrier trunk and no PSTN egress, exactly the same target form a ring group emits. The INVITE carries the widely-deployed auto-answer headers (Call-Info with answer-after=0, and Alert-Info: info=alert-autoanswer), so phones that honor either convention play the announcement out of the speaker hands-free; phones that honor neither simply ring until someone answers. The ring window defaults to 20 seconds per leg and is bounded between 5 and 120. Scope rules that separate page from call-offer:
  • One delivery per member. Fan-out runs both channels in parallel and tolerates partial failure: a deskphone leg that fails (voice plane blip, device offline) is counted and logged but never blocks the other legs, and the response reports targeted/paged/failed counts.
  • Zero recipients is only an alarm when something was attempted. An empty group, or a group whose deskphone members were all filtered by the enabled-credential check, is designed-benign operator state — no alarm. If at least one delivery was attempted and every attempt failed, that is a genuine fault and is logged as such.
  • Duplex falls back to simplex. A group configured for two-way intercom still rings every member and plays the announcement until the conference-intercom path ships; no member is silently dropped.
Membership is capped (Zod-bounded at write time, and the fan-out re-bounds defensively at page time), and every page trigger is audit-logged so the “who paged the warehouse at 2am” question has an answer.

Find-me/follow-me and generic hunt

Where a ring group is a team construct (“ring the support desk”), find-me/follow-me is a personal construct: an ordered hunt chain that says where to find me. You configure an ordered ladder of steps — each a device class (desk, mobile, softphone) or an explicit target (an E.164 pstn number or a sip: URI) — with a per-step ring window. The planner resolves the ladder into a schedule of legs: step 0 rings first for its window; on no-answer the chain advances to step 1; and so on. Bounds keep a bad ladder from stranding a caller:
  • At most five steps per sequence.
  • Each step rings between 5 and 120 seconds (20 by default).
  • The sum of all windows cannot exceed 180 seconds, after which the sequence’s terminal fallback fires — your voicemail box by default, or the route-level default when voicemail fallback is disabled.
Device-class steps resolve to your registered binding at dial time; an unbound class step (no desk device registered) is skipped rather than failing the chain. Explicit pstn steps are validated as E.164 at write time, and sip: steps must start with the sip: scheme. Plain sequential hunt — call-forwarding’s sequential mode — is the simpler sibling: one flat list of destinations sharing a single ring timeout, without per-step order/window control. Use it when the ladder’s per-step granularity is unnecessary; use find-me/follow-me when desk-for-12s-then-mobile-for-20s matters. Outbound legs in all of these shapes are placed over Orbit’s own voice path. None of them ever originate onto an external carrier trunk of your choosing — the platform’s termination model is the single route out, so a hunt chain can’t become an accidental toll-fraud vector.

Presence and availability interact before strategy

Distribution strategies pick among the members that are actually ringable right now. Before round-robin, longest-idle, or fewest-calls runs, the resolved dial list passes a presence filter over the SIP REGISTER heartbeat:
  • A SIP credential whose device has REGISTERed within the freshness window (five minutes — comfortably two refresh cycles for a well-behaved softphone) stays in the list.
  • A credential whose REGISTER has gone stale is dropped: the softswitch still holds the old device binding pointed at a moved or dead address, so ringing it just burns the caller’s ring-timeout in silence.
  • A credential that has never registered is kept — with no binding at all, the softswitch returns an instant “temporarily unavailable” instead of a slow timeout, so the parallel fork either resolves to a registered sibling or falls to the route fallback within a second.
  • A missing credential row (hard-deleted between config and dial) is dropped — the dial target would be invalid.
  • PSTN members pass straight through: an external number has no REGISTER signal, and its carrier handles its own busy/no-answer.
The presence check is deliberately fail-open: if the credentials lookup errors, the resolver behaves as it did before presence existed (ring everyone) rather than dropping the inbound call. Agent-level presence in the contact-center sense — the available/busy/wrapup/paused/offline machine that ACD dispatch consults — is a separate layer on top, covered by Agent presence and aux-code lifecycle; the REGISTER heartbeat described here is the device-level gate that applies to ring-group fan-out to any device, agent or not. The platform’s federated calendar/IM presence feeds (Teams, calendars) can also feed availability — see Inbound voice routing and the presence federation surfaces — but the device heartbeat is the floor that every shape above runs through.

Worked sample: round-robin vs longest-idle

Same group, four members, evaluated under each strategy. The group mixes a deskphone and softphones: Under round_robin. The shared cursor points at bob-softphone, so the next inbound call rings Bob first regardless of how busy anyone was. The following call rings Carol; the one after rings the overflow cell; the one after rings Alice again, completing one rotation. Round-robin is deterministic and shares the work evenly by count, but it does not know that Alice just took three calls in a row — it only knows where the cursor stopped. Under longest_idle. The next call rings whichever member’s last-selection timestamp is smallest. If Alice was picked at 14:02 and Bob at 13:47, Bob wins before Carol only if Carol also has a recorded selection; a member with no record at all is treated as idle-forever and wins ties deterministically. Add a new member mid-rotation and they immediately outrank every incumbent. Longest-idle spreads work by recency, which tracks the operator intuition “who has been free the longest” much better. Presence pruning composes with both. If Bob’s softphone has not refreshed REGISTER within five minutes, Bob is dropped from the candidate list and the strategy picks among Alice, Carol, and the overflow cell only — so a run of “Bob never rings” is resolved by re-registering Bob’s device, not by re-ordering the group.

See also

  • Inbound voice routing — where ring groups, find-me/follow-me chains, and paging fan-outs sit in the full resolution chain.
  • Agent presence and aux-code lifecycle — the agent-level availability machine ACD reads on top of the device heartbeat.
  • The ACD queue model — where distribution moves from “which device rings” to “which agent claims the next queue item.”
  • SIP credential lifecycle — what REGISTER/expire/re-register does at the device layer, the same signal the presence filter above reads.
  • Voice call lifecycle — the state vocabulary the routed leg advances through once a topologies decision rings someone.