Why the PresenceUserConfig Metadata Type Controls the Agent Experience
While ServiceChannel defines what is routed and QueueRoutingConfig defines how items are prioritized, PresenceUserConfig (presenceUserConfigs/<Name>.presenceUserConfig-meta.xml) governs the agent’s Omni-Channel console behavior and capacity limits:
- Total & Interruptible Capacity (
capacity,interruptibleCapacity): Maximum workload units an agent can hold at once, plus separate capacity for background/interruptible work (Case/Email) vs. live synchronous channels (Voice/Messaging). - Auto-Accept vs. Manual Decline (
enableAutoAccept,enableDecline,declineReasons): Whether work opens automatically or allows agents to reject offers with an audited reason. - Automatic Away Status on Missed Push (
presenceStatusOnPushTimeout,presenceStatusOnDecline): Prevents “ghost agents” who walk away from their desk without logging out of Omni-Channel from stalling the routing queue.
Key Metadata Fields on PresenceUserConfig
| Field | Type | Required | Description |
|---|---|---|---|
label |
string |
Yes | Display name of the Presence Configuration in Setup. |
capacity |
int |
Yes | Maximum primary capacity units an agent assigned to this configuration can hold simultaneously. |
interruptibleCapacity |
int |
No | (API v57.0+) Maximum capacity units allowed for interruptible work items (where QueueRoutingConfig.isInterruptible = true). |
enableAutoAccept |
boolean |
No | Automatically accepts pushed work items without requiring the agent to click Accept (cannot be combined with enableDecline = true). |
enableDecline |
boolean |
No | Allows agents to decline pushed work offers. |
enableDeclineReason |
boolean |
No | Requires agents to pick a reason (declineReasons) when declining a work item. |
presenceStatusOnDecline |
string |
No | ServicePresenceStatus developer name automatically applied when an agent declines an offer. |
presenceStatusOnPushTimeout |
string |
No | ServicePresenceStatus developer name automatically applied when a push offer times out (QueueRoutingConfig.pushTimeout). |
acwExtensionEnabled |
boolean |
No | (API v60.0+) Allows agents to extend their After Conversation Work (ACW) wrap-up timer. |
maxExtensions / acwExtensionDuration |
int |
No | (API v60.0+) Number of allowed ACW extensions and seconds per extension. |
Real-World XML Example (presenceUserConfigs/Blended_Voice_And_Case_Agents.presenceUserConfig-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<PresenceUserConfig xmlns="http://soap.sforce.com/2006/04/metadata">
<acwExtensionDuration>60</acwExtensionDuration>
<acwExtensionEnabled>true</acwExtensionEnabled>
<capacity>10</capacity>
<declineReasons>On_Customer_Escalation_Call</declineReasons>
<declineReasons>Shift_Ending_Within_10_Mins</declineReasons>
<enableAutoAccept>false</enableAutoAccept>
<enableDisconnectSound>true</enableDisconnectSound>
<enableDecline>true</enableDecline>
<enableDeclineReason>true</enableDeclineReason>
<enableRequestSound>true</enableRequestSound>
<interruptibleCapacity>6</interruptibleCapacity>
<label>Blended Voice and Case Agents</label>
<maxExtensions>2</maxExtensions>
<presenceStatusOnPushTimeout>Busy_Missed_Offer</presenceStatusOnPushTimeout>
</PresenceUserConfig>Querying PresenceUserConfig and Assigned Users via SOQL
Both PresenceUserConfig and PresenceUserConfigUser / PresenceUserConfigProfile are queryable in SOQL.
1. Audit All Presence Configurations and Their Capacity Limits
SELECT Id, DeveloperName, MasterLabel, Capacity, InterruptibleCapacity,
ShouldAutoAcceptEnabled, ShouldDeclineEnabled,
PresenceStatusOnPushTimeoutId, PresenceStatusOnDeclineId
FROM PresenceUserConfig
ORDER BY MasterLabel ASC2. List Users Assigned to a Specific PresenceUserConfig
SELECT Id, PresenceUserConfig.DeveloperName, User.Name, User.Username
FROM PresenceUserConfigUser
WHERE User.IsActive = true
ORDER BY PresenceUserConfig.DeveloperName, User.NameSenior Architect Best Practices & Gotchas
Warning
Never Commit <assignments><users> to Git: If you assign individual users to a PresenceUserConfig in Setup and retrieve the metadata, Salesforce populates <assignments><users>jane@acme.com.sandbox</users></assignments>. Deploying that file to Production or another Sandbox will fail because the sandbox username does not exist. Always strip <assignments><users> from version control!
- Always Configure
presenceStatusOnPushTimeout: WithoutpresenceStatusOnPushTimeoutmapped to a busy/awayServicePresenceStatus, an agent who steps away from their computer with their Omni-Channel status set toAvailablewill continuously receive and time out on every high-priority work item in the queue.
Frequently asked questions
What is the purpose of interruptibleCapacity on PresenceUserConfig?
Available in API v57.0+, interruptibleCapacity splits an agent's workload into primary (non-interruptible) and interruptible buckets so an agent working on asynchronous Cases or Leads can still receive real-time VoiceCall or MessagingSession requests.
Can enableAutoAccept and enableDecline both be set to true on a PresenceUserConfig?
No. Salesforce enforces that enableAutoAccept and enableDecline are mutually exclusive. If work items are automatically accepted when pushed to the agent, the agent cannot manually decline the push offer.
Why should you avoid hardcoding usernames inside PresenceUserConfig in SFDX?
Usernames inside the assignments.users block of a PresenceUserConfig are environment-specific and frequently fail deployment across Sandboxes. Assign PresenceUserConfig via profiles or automate user assignments separately.
How do you query PresenceUserConfig settings in SOQL?
You can query the PresenceUserConfig standard object in SOQL to inspect DeveloperName, MasterLabel, Capacity, InterruptibleCapacity, ShouldAutoAcceptEnabled, ShouldDeclineEnabled, and PresenceStatusOnPushTimeoutId.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.