close
Skip to content

onAvailabilityStateChanged (v1.0.12) does not fire for internal CCP states previously available via deprecated onStateChanged — no way to detect outbound call dialing #11

Description

@tomctv

With SDK version 1.0.11, AgentClient.onStateChanged() fired for all agent state transitions, including undocumented internal CCP states such as CallingCustomer, Busy, FailedConnectCustomer, FailedConnectAgent, etc. These states were the only reliable mechanism to detect when an outbound voice call entered the dialing phase.

In version 1.0.12, onStateChanged is marked as deprecated in favour of onAvailabilityStateChanged. However, onAvailabilityStateChanged fires exclusively for configured availability state changes (e.g. AvailableOffline, custom states). It does not fire for internal CCP states. As a result, after migrating to the new API, it is impossible to detect outbound call dialing, customer no-answer, or agent-side hang-up during the dialing phase.

Neither ContactClient nor VoiceClient exposes lifecycle events for outbound voice contacts comparable to what ContactClient already provides for inbound contacts (onIncoming, onConnected, onStartingAcw, onMissed, onCleared). This gap makes outbound call tracking only achievable through the now-deprecated onStateChanged, which is being removed with no equivalent replacement.

Environment

  • SDK packages: @amazon-connect/contact, @amazon-connect/voice
  • Affected version: 1.0.12 (regression from 1.0.11)
  • Integration type: Amazon Connect Agent Workspace third-party app (iframe)

Behaviour in v1.0.11 (working)

Subscribing to onStateChanged yielded the following event sequence for an outbound call that was initiated by the agent and then hung up before the customer answered:

onStateChanged → { state: "CallingCustomer", previous: { state: "Available" } }
onStateChanged → { state: "FailedConnectAgent", previous: { state: "CallingCustomer" } }
onStateChanged → { state: "Offline",  previous: { state: "FailedConnectAgent" } }

And for a successful outbound call:

onStateChanged → { state: "CallingCustomer", previous: { state: "Available" } }
onStateChanged → { state: "Busy",            previous: { state: "CallingCustomer" } }
// ContactClient.onConnected fires here
onStateChanged → { state: "Available",       previous: { state: "Busy" } }

This allowed me to implement a reliable outbound call lifecycle tracker:

// v1.0.11 — worked correctly
agentClient.onStateChanged((event) => {
  const { state, previous } = event;

  if (isDialingState(state) && previous?.state !== state) {
    showOutboundDialingBanner();
  } else if (isFailureState(state)) {
    showMissedCallBanner(state);  // kept until dismissed by the user
  } else if (state === "Busy" && isDialing()) {
    // customer answered — hand off to ContactClient.onConnected
    hideOutboundDialingBanner();
  }
});

Behaviour in v1.0.12 (broken)

After migrating to onAvailabilityStateChanged as recommended:

// v1.0.12 — fires only for availability state changes
agentClient.onAvailabilityStateChanged((event) => {
  // Never receives "CallingCustomer", "Busy", "FailedConnectAgent", etc.
  // Outbound dialing is completely invisible.
  console.log(event.state.name); // only: "Available", "Offline", custom states
});

The internal CCP states are no longer surfaced through any public API. The outbound dialing banner never appears, and the missed-call banner flashes momentarily then disappears (because the contact lifecycle resolves before the app can react).

Root causes

onStateChanged exposed two distinct categories of state in a single stream:

  1. Availability states — agent-configurable states (Available, Offline, custom). Now correctly surfaced by onAvailabilityStateChanged.
  2. Internal CCP states — transient states driven by telephony events (CallingCustomer, Busy, FailedConnectCustomer, etc.). No longer surfaced by any API in v1.0.12.
    Deprecating onStateChanged without providing a replacement for category (2) creates a capability regression.

What we expected

Either:
Option A — dedicated outbound voice contact events on ContactClient or VoiceClient (preferred)

// analogous to existing inbound contact events
voiceClient.onOutboundDialing((event) => {
  // { contactId, type: "voice", subtype: "connect:Telephony" }
});

voiceClient.onOutboundDialingFailed((event) => {
  // { contactId, reason: "no-answer" | "agent-hang-up" | ... }
});

This would align with the existing event model (onIncoming, onConnected, onMissed, etc.) and make outbound tracking a first-class citizen.

Option B — preserve internal CCP states in onAvailabilityStateChanged (acceptable)
Document and guarantee that onAvailabilityStateChanged fires for internal CCP states (CallingCustomer, Busy, etc.) in addition to availability states, so migrating from onStateChanged is a true drop-in replacement.

Option C — new dedicated onCcpStateChanged event on AgentClient (acceptable)
Expose a non-deprecated API that preserves the full state stream from onStateChanged, clearly documenting the internal CCP states and their lifecycle.

Why this matters

Outbound call UX is a core use case for contact centre agents. Without visibility into the dialing phase, third-party apps embedded in the Agent Workspace cannot:

  • Show a dialing spinner/banner while the customer's phone is ringing
  • Detect that a call was not answered vs. answered
  • Distinguish agent-initiated hang-up from customer no-answer
  • Implement missed-call notifications that persist until the agent acknowledges them
  • Other custom logic to be performed during outbound call dialing

All of these were achievable in v1.0.11 via onStateChanged. The v1.0.12 deprecation removes this capability with no migration path.

Steps to reproduce

  1. Install @amazon-connect/contact@1.0.12
  2. Subscribe to onAvailabilityStateChanged on AgentClient
  3. Initiate an outbound voice call from the Agent Workspace CCP
  4. Observe that no event fires while the customer's phone is ringing (CallingCustomer state)
  5. Hang up before the customer answers and observe that no failure event fires

Expected: events corresponding to the dialing and failure states
Actual: no events fired; onAvailabilityStateChanged remains silent throughout.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions