@avaya/infinity-agent-sdk - v1.0.0
    Preparing search index...

    Transfer and Conference

    This guide covers blind and attended transfers to users, queue or external phone number, and conferencing - adding a third party to an attended call and bridging all parties together.

    Personas: Agent - blind-transfers, attended-transfers, or conferences their interaction.

    The SDK exposes two transfer modes on a live Interaction:

    Mode Behavior
    Blind Immediately hands the interaction off to the destination - the agent drops off as soon as the transfer is confirmed.
    Attended Opens a consultation leg to the destination first. The agent can brief the party, then either complete the transfer (hand off), cancel (return to the customer), or conference (bridge all three parties together).

    Both modes support three destination types: queue, agent, and external phone number. Blind transfers use a type discriminant from the TransferDestination enum; attended transfers use distinct option shapes per destination type.

    • An active Interaction in a state that allows transfer - check canBlindTransfer() or canAttendedTransfer() before calling.
    • For transfer to queue or agent, run a lookup first to obtain valid IDs (see below).

    Use paginated lookup methods to populate a transfer picker. Both accept an optional name filter:

    // Search queues
    const queuePage = await interaction.getTransferableQueues({ name: "billing" });
    const queue = queuePage.queues[0]; // { queueId, name, eligible, ... }

    // Search agents
    const userPage = await interaction.getTransferableUsers({ name: "Alice" });
    const agent = userPage.users[0]; // { userId, fullName, eligible, ... }

    Gate on the appropriate capability check - canBlindTransfer() for queue/user, canExternalBlindTransfer() for external - then call Interaction.blindTransfer. The interaction ends for the agent once the transfer is confirmed.

    // To a queue
    if (interaction.canBlindTransfer()) {
    await interaction.blindTransfer({
    type: TransferDestination.QUEUE,
    queueId: queue.queueId,
    queueName: queue.name,
    });
    }

    // To an agent
    if (interaction.canBlindTransfer()) {
    await interaction.blindTransfer({
    type: TransferDestination.USER,
    userId: agent.userId,
    });
    }

    // To an external number
    if (interaction.canExternalBlindTransfer()) {
    await interaction.blindTransfer({
    type: TransferDestination.EXTERNAL,
    externalNumber: "+14155551234",
    });
    }

    // Confirmation fires when the platform commits the transfer
    interaction.subscribe(InteractionEventType.INTERACTION_BLIND_TRANSFERRED, () => {
    clearInteractionUI();
    });

    Elite agents: For Elite interactions (interaction.isElite === true), canBlindTransfer() returns false for queue and user destinations - only canExternalBlindTransfer() may return true. Hide queue and agent transfer options when interaction.isElite is set. See Elite Transfer Restrictions.

    Initiate the consultation leg with Interaction.attendedTransfer, brief the party while the customer is held, then commit or abort:

    // Start consultation - pass { userId } for agent, { queueId, queueName } for queue,
    // or { type: 'external', externalNumber } for an external number
    if (interaction.canAttendedTransfer()) {
    await interaction.attendedTransfer({
    userId: agent.userId,
    });
    }

    // Track consultation lifecycle
    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER, () => {
    showConsultingBanner(); // consultation leg dialling
    });
    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER_ANSWER, () => {
    showCompleteOrCancelControls(); // destination answered - brief them, then decide
    });

    // Commit - hands the customer off to the destination
    if (interaction.canCompleteTransfer()) {
    await interaction.completeTransfer();
    }

    // Abort - drops the consultation leg, returns to the customer
    if (interaction.canCancelTransfer()) {
    await interaction.cancelTransfer();
    }

    // Track completion / cancellation
    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER_COMPLETE, () => clearInteractionUI());
    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER_CANCEL, () => hideCompleteOrCancelControls());

    Elite agents: For Elite interactions, canAttendedTransfer() returns false for queue and user destinations - only external attended transfer is supported. Additionally, once the consultation party answers (INTERACTION_TRANSFER_ANSWER), the transfer is locked - canCancelTransfer() returns false and the agent cannot abort. See Elite Transfer Restrictions.

    Transfer failures surface asynchronously via InteractionEventType.INTERACTION_TRANSFER_FAILED. Inspect event.payload.reason ( TransferFailReason) to surface a recoverable error:

    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER_FAILED, (event) => {
    showTransferFailedBanner(event.payload.reason);
    });

    Once the consulted party answers (INTERACTION_TRANSFER_ANSWER), the agent can bridge all three parties into a conference instead of completing the transfer. Gate on Interaction.canConference and call Interaction.conference:

    interaction.subscribe(InteractionEventType.INTERACTION_TRANSFER_ANSWER, async () => {
    if (interaction.canConference()) {
    await interaction.conference();
    }
    });

    interaction.subscribe(InteractionEventType.INTERACTION_CONFERENCE, () => {
    showConferenceControls(); // all three parties are now on the call
    });

    With all three parties bridged, finalize or abort:

    // Finalize - consulted party transitions to viewer role, call continues
    if (interaction.canCompleteConference()) {
    await interaction.completeConference();
    }

    // Drop the third party, return to one-on-one with the customer
    if (interaction.canCancelConference()) {
    await interaction.cancelConference();
    }

    interaction.subscribe(InteractionEventType.INTERACTION_CONFERENCE_COMPLETE, () => {
    hideConferenceControls();
    });

    Elite agents: canCompleteConference() returns false for Elite interactions - the three-way conference completion is not supported via the Elite PBX. The attended transfer path (complete or cancel) remains available instead.

    Elite interactions only support transfers to external phone numbers. canBlindTransfer() and canAttendedTransfer() return false for user and queue destinations when interaction.isElite is true - only canExternalBlindTransfer() may return true.

    Additionally, once an attended transfer consultation is answered ( InteractionEventType.INTERACTION_TRANSFER_ANSWER), the transfer is locked for Elite - canCancelTransfer() returns false and the agent cannot abort the consultation leg. Three-way conference completion is likewise unavailable (canCompleteConference() returns false).

    Gate your transfer UI accordingly:

    if (interaction.isElite) {
    // Only offer external transfer option
    showExternalTransferOnly();
    } else {
    showAllTransferOptions();
    }

    See Detecting Elite Context for how the deployment model is exposed at runtime.

    Failures surface as typed AvayaInfinityAgentSdkErrors with stable codes from AvayaInfinityAgentSdkErrorCodes. Errors that occur on the transfer path belong to the ASE_4xxx family - match error.code against AvayaInfinityAgentSdkErrorCodes to identify the specific failure. If no specific code applies, the SDK falls back to ASE_4000.

    Transfer rejections from the destination (busy, no answer, declined) surface as InteractionEventType.INTERACTION_TRANSFER_FAILED on the interaction - subscribe to that event rather than relying on a promise rejection.