# Migrate Rep Presence Status

Manage rep presence through Omni-Channel instead of your previous Open CTI pattern.

Open CTI doesn't natively integrate with Omni-Channel for presence. Adapters that managed presence typically did one of the following:

- Maintained an in-adapter presence widget that didn't talk to Omni-Channel at all
- Mirrored adapter status to Omni-Channel via custom Apex REST endpoints setting `UserServicePresence`
- Relied on the rep manually changing their Omni-Channel status in the UI

This means for many Open CTI orgs, there is no Omni-Channel integration to migrate from. You're moving from "adapter has its own presence" to "Omni-Channel owns presence."

## What Omni-Channel Does and Doesn't Do

Omni-Channel is channel-agnostic. It manages presence across Voice, Chat, Messaging, Cases, and more for the same rep. A single presence status (for example, "Available") can signal readiness for routing across all enabled channels.

Omni-Channel does **not** change presence status when a rep accepts a call. When a rep takes a call, they go "busy" from a routing standpoint. Their capacity is consumed via AgentWork, but their Omni-Channel presence status itself doesn't change. They're still "Available." Capacity is the routing-side concept. Presence is the user-facing concept; they're decoupled.

Omni-Channel does **not** set status to anything during the call. Reps stay on their selected presence status throughout the call. The "I'm on a call" indicator comes from AgentWork, not from presence status.

`enqueueNextState` is the bridge between rep intent ("I want to go offline") and call lifecycle ("but they're still on a call"). Without it, premature status changes drop calls.

:::note
Partners coming from non-Omni-Channel telephony platforms expect an explicit "On Call" status. There isn't one in Omni-Channel. The rep stays Available; their capacity is fully consumed by AgentWork for the duration. We recommend covering this in your training materials.
:::

## Salesforce Voice with Partner Telephony Pattern for Presence Status

Your connector responds to Omni-Channel in the new Salesforce Voice with Partner Telephony pattern. Here's an example of how to handle changes in rep status.

```sfdocs-code {"lang":"javascript"}
async setAgentStatus(agentStatus, statusInfo, enqueueNextState) {
    // agentStatus: 'Online' | 'Offline' | 'AfterCallWork' | <custom>
    if (enqueueNextState) {
        // Rep clicked "Go Offline" mid-call — apply AFTER the call ends
        await myBackend.queueStatusChange(agentStatus);
    } else {
        await myBackend.setStatus(agentStatus);
    }
    // Return a Promise<GenericResult>
}

async getSharedCapabilities() {
    return new VoiceCapabilitiesResult({
        hasPendingStatusChange: true,  // enables enqueueNextState behavior
        hasTransferToOmniFlow: true,
    });
}
```

:::important
Skipping `enqueueNextState` causes dropped calls. If you apply Offline immediately while a call is active, your backend tears down the rep's session, and the call drops. Offline is the worst status to flip to mid-call. This is the root cause of numerous support cases with partner telephony. Always honor the `enqueueNextState` flag.
:::
