This guide covers the agent-availability lifecycle within a session - logging into the CX platform to become ready to receive interactions, switching between status reasons (Available, Busy, Away, etc.) throughout the shift, and logging out at end of shift.
Personas: Agent, Supervisor - each logs into the CX platform and manages their own availability status.
The User (returned after AvayaInfinityAgentSdk.init resolves) represents an authenticated agent. But, the agent is not yet ready to receive the interactions. Interactions only flow to the agents who are logged into the CX platform, so the next step is to login to CX via User.loginToCx. Once logged in, the status reason (Available, Busy, Away, Offline) which is set determines whether this agent will receive new interactions. As the agent moves through their shift, switch the status via User.changeStatus.
Make sure to subscribe to the relevant events mentioned in the following sections to keep your UI updated.
Log in to the CX using User.loginToCx, the returned promise will resolve once the agent is logged into CX. The User.isLoggedInToCx flips to true and UserEventType.USER_CX_LOGGED_IN event will be emitted. Make sure to gate the login button using User.canLoginToCx before calling User.loginToCx.
Optionally, pass a ReasonCode (acquired from User.getAssignableReasonCodes) while logging in to also set the agent's initial status in a single call, instead of calling User.changeStatus separately afterward.
user.subscribe(UserEventType.USER_CX_LOGGED_IN, () => {
showOnShiftIndicator();
});
if (user.canLoginToCx()) {
await user.loginToCx();
}
// Log in and set an initial status in one call
const reasons = await user.getAssignableReasonCodes();
const available = reasons.find(r => r.type === ReasonType.AVAILABLE);
if (user.canLoginToCx() && available) {
await user.loginToCx(available);
}
For Elite agents: loginToCx does not accept a reasonCode - passing one throws AvayaInfinityAgentSdkError (code ASE-2030). Elite agents must call loginToCx() without a reason, wait for login to complete, and then call User.changeStatus explicitly.
Reason codes are configured per tenant via the admin console. Fetch all the available reason codes via User.getAssignableReasonCodes. Then populate your status picker using the resolved values. Each ReasonCode carries a ReasonType and the reason itself.
Check the user's current status using User.currentStatus. The agent can change their status using User.changeStatus. The UserEventType.USER_STATUS_CHANGED event will be emitted once the user status changes. Make sure to gate the change status button using User.canChangeStatus before calling User.changeStatus.
const reasons = await user.getAssignableReasonCodes();
const available = reasons.find(r => r.type === ReasonType.AVAILABLE);
if (available && user.canChangeStatus()) {
await user.changeStatus(available);
}
For Elite agents: Each ReasonCode also carries an optional eliteAuxCode field required by the Elite PBX for availability tracking. Elite agents must only use reason codes where eliteAuxCode is defined. See Elite Status Reason Codes for more info.
Call the User.refreshStatus to sync the status with the server (e.g. after a reconnect).
Status can change without your code initiating the call, for example the server times them out. An authorized supervisor can log the agent in or out remotely. Subscribe to the relevant events to keep your UI in sync:
user.subscribe(UserEventType.USER_STATUS_CHANGED, (event) => {
updateStatusBadge(event.payload.status);
});
user.subscribe(UserEventType.USER_CX_LOGGED_IN, (event) => {
resetToSignedIn(event.payload);
});
user.subscribe(UserEventType.USER_CX_LOGGED_OUT, (event) => {
resetToSignedOut(event.payload);
});
At the end of the shift the agent can logout from the CX platform via User.logoutFromCx. Logging out requires a valid reason of type ReasonType.LOGOUT. Make sure to gate the action using User.canLogoutFromCx:
const reasons = await user.getAssignableReasonCodes();
const logoutReasons = reasons.filter(r => r.type === ReasonType.LOGOUT);
if (user.canLogoutFromCx()) {
await user.logoutFromCx(logoutReasons[0]);
}
This is distinct from AvayaInfinityAgentSdk.destroy - logoutFromCx only logs the agent out from CX. To tear down the full SDK session, call the destroy(). See Integration and Lifecycle.
Avaya Infinity™ supports two agent deployment models:
| Model | Description |
|---|---|
| Standard (cloud) | Agent routes through Avaya Infinity queues for all channels. |
| Elite (hybrid) | Agent's voice calls route through an on-premises Elite PBX. Queue routing is bypassed; only external transfers are supported for voice. |
The SDK exposes two read-only flags to identify the deployment context at runtime:
true when the authenticated agent has an Elite voice license.true when a specific interaction is routed through the Elite PBX.These flags drive conditional UI - hiding unsupported controls, filtering reason codes, and adjusting the outbound call flow. Check user.isEliteVoiceEnabled once after init() to adapt session-level UI; check interaction.isElite per interaction to gate call controls:
// Session level - is this agent on Elite voice?
if (user.isEliteVoiceEnabled) {
showEliteStatusIndicator();
}
// Per interaction - is this call routed through the Elite PBX?
if (interaction.isElite) {
hideQueueTransferOption();
hideUserTransferOption();
}
Elite agents must only use reason codes that have an eliteAuxCode configured - the Elite PBX uses this value for its own availability tracking. Reasons without eliteAuxCode are not valid for Elite. Filter the list before populating your status picker:
const reasons = await user.getAssignableReasonCodes();
const eligibleReasons = user.isEliteVoiceEnabled
? reasons.filter(r => r.eliteAuxCode !== undefined)
: reasons;
populateStatusPicker(eligibleReasons);
Failures surface as typed AvayaInfinityAgentSdkErrors with stable codes from AvayaInfinityAgentSdkErrorCodes. Errors on the Agent login/logout path belong to the ASE_2xxx family - match error.code against AvayaInfinityAgentSdkErrorCodes to identify the specific failure. If no specific code applies, the SDK falls back to ASE_2000.