PSTN inbound

Caller on hold music until a skilled agent answers.

Inbound runs in the same process as outbound, in both Progressive and Predictive. AMI parks the trunk on MusicOnHold, looks up sales_dialer_master_data by phone, and offers an idle agent whose skills include form_type and whose priority_ids allow the lead’s priority_id (empty = all). That desk’s outbound engine yields until the inbound ends.

Always on Skill match Unlimited hold Decline cooldown

Flow

  1. AMI sees a PSTN caller. The process parks them in the inbound wait context with MusicOnHold (AMI_INBOUND_WAIT_*).
  2. Lookup by last 10 digits. If a live master row exists, it is claimed for inbound. If not, the caller can still sit on hold / pass through depending on AMI.
  3. Pick a skilled idle agent (SIP idle, wrap clear, not paused, not already on a call). Soft-avoid the FreePBX flash desk and the last offered extension.
  4. Originate / redirect to that PJSIP/{extension} with the shared AMI_CALLERID placeholder on the agent's SIP (not the PSTN number). Agent panel gets inbound ringing.
  5. Answer → talking, call_connected, settle later as Received. Decline → caller stays on hold; that extension is blocked for decline_cooldown_seconds.

Concurrent callers on the same DID are isolated with a park key like {desk}~{timestamp} (including while the first is still on hold under the shared inbound key). Same phone/OLI on two trunks is allowed; only a true same-trunk double-fire is dropped. Reshuffle after decline still skips desks that are already on a live call.

Outside work_start–work_end, only called numbers in AMI_AFTER_HOURS_DID (default 3365233005,913365233005) stop MOH, play AMI_AFTER_HOURS_SOUND (default /var/lib/asterisk/sounds/custom/off-hours — keep this file out of the MOH folder so hold music is only dialer-hold.wav) then hang up — no agents, no mobile forward. The miss is stored in sales_dialer_after_hours_calls (master snapshot when the number matches, otherwise phone only). After-hours inbound on any other DID is left to FreePBX.

Skill offer and yield

Offer uses the same pickSkilledAgent as predictive, including decline cooldown. Dashboard On hold counts inbound waiters plus predictive holds.

While this desk is offered or talking inbound, Progressive / Predictive will not originate another outbound on that extension. A predictive connecting offer to that desk is dropped back to hold. An agent who is outbound-blocked by missed activities still gets inbound offers, and inbound calls never create missed-activity rows. When isMaintainance = 1, inbound is left to FreePBX (no park / skill offer from this process).

There is no hold timeout. The caller stays on music until they hang up or an agent answers. hold_timeout_seconds is not read.

Settle

Outcomedial_status
Agent and caller talkedReceived
Caller left before talkAbandoned. Keeps a future next_retry_at; otherwise schedules retry_seconds (work-hours clamped)

Attempts are call_type = incoming on sales_dialer_call_attempts. Declines on that offer are also incoming on sales_dialer_agent_declines.

Socket

inbound with kind waiting is dashboard-only (caller parked, desk not ringing yet). ringing, answered, offer_failed, and ended go to the desk room and the dashboard. The built-in agent page listens and shows the caller number. Full payload is in the Socket guide.