Skip to main content
Use this guidance to keep the host application responsive when an embedded lifecycle event does not arrive. The most important event to guard is interaction.loaded, which confirms that the requested interaction is ready to display after navigation.
Load the Assistant with visibility="hidden", navigate to the interaction, and show the component after you receive embedded.navigated or interaction.loaded. This prevents users from seeing an incomplete embedded state.
Start a timeout whenever your integration initiates navigation that depends on interaction.loaded. Use a default timeout between 10 and 30 seconds. Corti recommends starting with 20 seconds, then tuning based on your own network and WebView conditions. When the timeout expires:
  1. Stop waiting for the stale event listener.
  2. Show a user-visible recovery state.
  3. Provide a retry action that reinitializes the embed, remounts the Web Component, or reloads the iframe.
  4. Log the timeout in your own monitoring so your team can separate integration, network, and service issues.
Do not leave users on an indefinite spinner. A clear recovery state is safer than a silent loading screen.

User-facing recovery copy

Use short copy that explains the state without exposing implementation details:
Assistant is taking longer than expected to load.
Check your connection, then try again.
Use an action label such as Retry or Reload Assistant. When the user retries, create a fresh embedded instance or reload the iframe before repeating authentication, configuration, interaction creation, and navigation.

Minimal implementation

The following example starts a timer before navigation, clears it when interaction.loaded arrives, and exposes a retry path that remounts the Web Component.
TypeScript
const INTERACTION_LOADED_TIMEOUT_MS = 20000;

type EmbedState = "loading" | "ready" | "recoverable-error";

let interactionLoadedTimer: ReturnType<typeof setTimeout> | undefined;

function setEmbedState(state: EmbedState) {
  // Render your own loading, ready, or retry UI here.
  console.log("Embedded Assistant state:", state);
}

function clearInteractionLoadedTimer() {
  if (interactionLoadedTimer) clearTimeout(interactionLoadedTimer);
  interactionLoadedTimer = undefined;
}

function waitForInteractionLoaded(
  corti: HTMLElement,
  startEmbed: (corti: HTMLElement) => Promise<void>,
) {
  clearInteractionLoadedTimer();
  setEmbedState("loading");

  const handleLoaded = () => {
    clearInteractionLoadedTimer();
    setEmbedState("ready");
  };

  corti.addEventListener("interaction.loaded", handleLoaded, { once: true });

  interactionLoadedTimer = setTimeout(() => {
    corti.removeEventListener("interaction.loaded", handleLoaded);
    setEmbedState("recoverable-error");
  }, INTERACTION_LOADED_TIMEOUT_MS);

  return startEmbed(corti);
}

async function retryEmbed(
  corti: HTMLElement,
  startEmbed: (corti: HTMLElement) => Promise<void>,
) {
  clearInteractionLoadedTimer();
  const freshCorti = corti.cloneNode(false) as HTMLElement;
  corti.replaceWith(freshCorti);

  await waitForInteractionLoaded(freshCorti, startEmbed);
}

What to monitor

Track these signals in your host application:
  • Timeout count and timeout rate for interaction.loaded
  • Browser or WebView family and version
  • Assistant region and baseURL
  • Whether the retry succeeds
  • The last Embedded API method called before the timeout
Do not log OAuth tokens, request bodies, transcripts, generated documents, or other sensitive clinical data.

Web Component API

Use the recommended integration method for new embedded deployments.

Events Reference

Review lifecycle events emitted by the Embedded Assistant.