Overview

In-house outbound and inbound dialer on Asterisk.

CRM pushes leads into sales_dialer_master_data. Agents join a Socket.IO panel. One process claims rows, originates through AMI, and settles hangups. Mode is Progressive or Predictive from sales_dialer_config. Inbound PSTN is always on.

Skill-only claim No master agent pin AMI originate Unlimited hold

How the pieces fit

HTTP APICRM upserts leads and schedules callbacks. Does not originate.
Socket hubAgent ready/pause (picker reason required), dashboard snapshot, dialer phases, inbound ringing, redial.
EnginesProgressive: one call per idle agent. Predictive: customer first, then skill bridge.
AMI + inboundDevice state, originate, bridge, MOH. PSTN park and skill offer.

Roster is sales_dialer_employee for module_id = sales-dialer. Skills JSON must include the lead form_type. AMI only tracks those extensions. Config reloads every 30 seconds; switching dialer_type waits until the floor is idle.

Life of a lead

  1. CRM POST /api/leads upserts by oli_id and mints a new data_id (returned on the 201). Status is Pending, or Callback if a callback priority has a time.
  2. An idle ready agent with matching skill claims the row: Calling, reserved. call_count does not increment here.
  3. Progressive originates the agent channel. Predictive originates the customer Local channel, then bridges a skilled agent on answer.
  4. Hangup settles master + a row on sales_dialer_call_attempts (agent, call_type, and the master data_id at settle).
  5. Not Connected retries on sales_dialer_config.retry_pattern (currently [4,4,3,2,1,1,1,1,1,1,1]) until max_tries (currently 20). Abandoned is not on that cycle — it keeps a future next_retry_at, otherwise waits retry_seconds (currently 3600). Received / Rejected / Disposed stop unless socket redial, a new CRM push, or a CRM pending callback.
  6. After a bridged outgoing / redial call the agent has MISSED_ACTIVITY_GRACE_MINUTES (default 10) to store a callback or disposition from the CRM. Otherwise their outbound is paused (inbound still rings) until they do. See Missed activities.

Master has no agent_id column. Sending it on the API is a 400. Connected agent is on sales_dialer_call_attempts only.

Dial status

StatusMeaningClaimed again?
PendingIn the poolYes, skill + priority allowlist
CallbackWaiting on callback_scheduled_atWhen due, skill + priority allowlist
CallingReserved, originate in flightNo
ReceivedTalkedNo (unless redial)
Not ConnectedNo answer / busy / congestionAfter retry_pattern / retry_seconds
AbandonedCustomer left while waiting (predictive / inbound)After retry_seconds (or existing next_retry_at)
RejectedCancel / invalid / reject causeNo (unless redial)
DisposedNC cap, or CRM final dispositionNo unless redial, a new CRM push, or a CRM pending callback

Tables this process owns

TableRole
sales_dialer_employeeRoster, skills, priority_ids, panel pause/active
sales_dialer_configMode, wrap, ratio, retry, hours, isMaintainance
sales_dialer_priorityQueue order, callback flags
sales_dialer_master_dataLeads. No agent pin
sales_dialer_call_attemptsEvery settle, with agent, hold seconds, master data_id snapshot, previous_dial_status (master at claim), and call_type (outgoing / incoming / redial)
sales_dialer_agent_declinesSIP deny on a live hold (same call_type values)
sales_dialer_agent_pausesPanel pause intervals
sales_dialer_api_call_logHangup webhook posts
sales_dialer_after_hours_callsAfter-hours DID misses (announce path only)
sales_dialer_pending_callbacksCRM callbacks / final dispositions held until the live call settles
sales_dialer_missed_activitiesBridged outgoing / redial calls awaiting a CRM callback or disposition (outbound block)

What this dialer does not do