Implementing Campaign Pacing Algorithms to Maximize Agent Utilization without SLA Breach
What This Guide Covers
You are implementing custom pacing logic for Genesys Cloud Outbound campaigns to solve the “Utilization vs. Compliance” dilemma. The standard “Predictive” dialer works well for large pools, but for smaller agent groups (10-30 agents), it can be erratic-causing either high agent idle time or excessive abandoned calls. This guide demonstrates how to build a Custom Pacing Controller using AWS Lambda and the Genesys Cloud APIs. This controller dynamically adjusts the maxCallsPerAgent (the pacing multiplier) based on a real-time calculation of “Available Agent Capacity” and “Historical Live Answer Rate.”
Prerequisites, Roles & Licensing
- Genesys Cloud: CX 1, 2, or 3 with Outbound.
- Permissions:
Outbound > Campaign > EditAnalytics > Queue > View
- Mathematics: Understanding of the “Erlang-C” model for capacity, though we will use a simplified linear regression for pacing.
The Implementation Deep-Dive
1. The Pacing Formula
The goal is to determine how many calls to place ($Calls_{total}$) to result in exactly the number of idle agents ($Agents_{idle}$) being connected.
$$PacingMultiplier = \frac{1}{\text{Live Answer Rate} \times (1 - \text{Abandon Rate Target})}$$
Example:
- If only 20% of calls are answered by a human (Live Answer Rate = 0.20).
- And you want a 0% abandon rate.
- Your multiplier is $1 / 0.20 = 5$. You must dial 5 numbers to get 1 human.
2. Fetching Real-Time Capacity
You need to know exactly how many agents are truly “Available” (Status = Available, on the correct queue, not currently on a call).
import requests
def get_available_agent_count(access_token, queue_id):
headers = {"Authorization": f"Bearer {access_token}"}
resp = requests.get(f"https://api.mypurecloud.com/api/v2/routing/queues/{queue_id}/observations", headers=headers)
# Extract 'onQueue' and 'idle' counts
data = resp.json()
idle_agents = data.get('metrics', [{}])[0].get('stats', {}).get('count', 0)
return idle_agents
3. Dynamic Multiplier Adjustment
Instead of a static multiplier, the Lambda script adjusts it every 60 seconds based on the current Abandon Rate trend.
def adjust_pacing(token, campaign_id, current_abandon_rate, target_abandon_rate=2.5):
# Fetch campaign
campaign = requests.get(f"https://api.mypurecloud.com/api/v2/outbound/campaigns/{campaign_id}", headers=token).json()
current_multiplier = campaign['campaignConfig']['maxCallsPerAgent']
if current_abandon_rate > target_abandon_rate:
# Too many abandons! Slow down.
new_multiplier = max(1.0, current_multiplier - 0.2)
elif current_abandon_rate < 1.0:
# Agents are sitting idle. Speed up.
new_multiplier = min(10.0, current_multiplier + 0.5)
else:
new_multiplier = current_multiplier
# Apply update
campaign['campaignConfig']['maxCallsPerAgent'] = round(new_multiplier, 1)
requests.put(f"https://api.mypurecloud.com/api/v2/outbound/campaigns/{campaign_id}", headers=token, json=campaign)
4. Handling “Spike” Protection
If 5 agents suddenly go on break, and the dialer has 20 calls in flight based on the old 10-agent capacity, you will hit an abandon spike.
The Solution: Capacity Buffer
Always subtract a “Buffer” from the available agent count before calculating the pacing.
$Agents_{target} = Agents_{idle} - Buffer$ (where Buffer is typically 1 or 2 agents).
Validation, Edge Cases & Troubleshooting
Edge Case 1: High Answering Machine Detection (AMD) False Positives
If your AMD is too aggressive, it will hang up on humans (Live Answer Rate drops), causing the pacing algorithm to dial even more calls to compensate, potentially causing a feedback loop of abandons.
Solution: Monitor the “AMD Resolution Rate.” If it exceeds 40%, trigger an alert to audit the AMD sensitivity settings rather than letting the pacing algorithm increase the multiplier.
Edge Case 2: Short Handle Time (SHT)
If calls only last 30 seconds (e.g., “Press 1 to confirm”), agents become available much faster than predicted.
Solution: Incorporate “Average Handle Time” (AHT) into the pacing multiplier. If AHT < 60s, reduce the multiplier by a factor of 0.5 to prevent “Machine Gun” dialing that outpaces agent wrap-up speed.
Edge Case 3: List Exhaustion
If the algorithm dials at a 10.0 multiplier because answer rates are low, it will burn through your lead list very quickly.
Solution: Add a “List Velocity” check. If the remaining records in the contact list are < 1000, force the multiplier to 1.0 (Progressive) to ensure the last few leads are handled with high quality and no risk of abandon.