Learn how to implement ambient sessions with the Web SDK
Quick Summary
An ambient session captures patient-provider conversations and generates clinical notes in real-time. The SDK handles recording, note generation, and error handling automatically.
You can manage sessions in two ways: uncontrolled mode where users interact only with SDK UI controls, or controlled mode where your EHR system controls when sessions start and stop through external triggers.
An ambient session captures patient-provider conversations and generates clinical notes in real-time. The SDK handles recording, note generation, and error handling automatically.To generate notes, you must configure sections that organize the content. You can use either predefined note types or LOINC codes. The SDK creates notes from the conversation using these configured sections.
LOINC code support is available in version 2.0 and above. See the note sections documentation for supported codes. For older versions, contact support to configure note types.
Users interact only with SDK UI controls. The SDK manages the session lifecycle automatically.
Controlled Mode
Your EHR system controls the session lifecycle (start, stop, resume) through external triggers. The SDK handles recording and note generation while your app controls when sessions start and stop.
The following example shows how to implement controlled session management in JavaScript and React.
JavaScript
React
controlled.js
Copy
Ask AI
import { initialize } from "@suki-sdk/js";let isSukiReady = false;// Replace with your actual encounter dataconst encounterDetails = { identifier: "6ec3920f-b0b1-499d-a4e9-889bf788e5ab", patient: { identifier: "905c2521-25eb-4324-9978-724636df3436", name: { use: "official", family: "Doe", given: ["John"], suffix: ["MD"], }, birthDate: "1990-01-01", gender: "Male", },};const sukiInstance = initialize({ partnerId: "f80c8db8-a4d0-4b75-8d63-56c82b5413f0", // Replace with your actual partner ID partnerToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Replace with your actual partner token providerName: "John Doe", // Replace with the full name of the provider providerOrgId: "1234", // Replace with the provider's organization ID providerSpecialty: "FAMILY_MEDICINE", // Replace with the provider's specialty});const unsubscribeInit = sdkClient.on("init:change", (isInitialized) => { if (isInitialized) { sdkClient.mount({ rootElement: document.getElementById("suki-root"), // The root element to mount the SDK into encounter: encounterDetails, ambientOptions: { sections: [ { loinc: "51848-0" }, { loinc: "11450-4" }, { loinc: "29545-1" }, ], }, }); } else { isSukiReady = false; // Reset the ready state if initialization fails }});const unsubscribeReady = sdkClient.on("ready", () => { isSukiReady = true;});// Ambient session control functionsfunction startAmbient() { if (isSukiReady) { sdkClient.startAmbient(); } else { console.error("Suki SDK is not ready yet."); }}function pauseAmbient() { if (isSukiReady) { sdkClient.pauseAmbient(); } else { console.error("Suki SDK is not ready yet."); }}function resumeAmbient() { if (isSukiReady) { sdkClient.resumeAmbient(); } else { console.error("Suki SDK is not ready yet."); }}function cancelAmbient() { if (isSukiReady) { sdkClient.cancelAmbient(); } else { console.error("Suki SDK is not ready yet."); }}function submitAmbient() { if (isSukiReady) { sdkClient.submitAmbient(); } else { console.error("Suki SDK is not ready yet."); }}// Attach event listeners to buttonsdocument.getElementById("start-ambient").addEventListener("click", startAmbient);document.getElementById("pause-ambient").addEventListener("click", pauseAmbient);document.getElementById("resume-ambient").addEventListener("click", resumeAmbient);document.getElementById("cancel-ambient").addEventListener("click", cancelAmbient);document.getElementById("submit-ambient").addEventListener("click", submitAmbient);// Cleanup function to destroy the SDK and event listeners// Call this function when you no longer need the SDKfunction destroy() { isSukiReady = false; unsubscribeInit(); unsubscribeReady(); sdkClient.destroy(); // Remove event listeners document.getElementById("start-ambient").removeEventListener("click", startAmbient); document.getElementById("pause-ambient").removeEventListener("click", pauseAmbient); document.getElementById("resume-ambient").removeEventListener("click", resumeAmbient); document.getElementById("cancel-ambient").removeEventListener("click", cancelAmbient); document.getElementById("submit-ambient").removeEventListener("click", submitAmbient); // Clear the root element document.getElementById("suki-root").innerHTML = "";}
controlled.jsx
Copy
Ask AI
import { useSuki, SukiAssistant } from "@suki-sdk/react";import { useState, useEffect, useMemo } from "react";const SUKI_OPTIONS = { partnerId: "f80c8db8-a4d0-4b75-8d63-56c82b5413f0", // Replace with your actual partner ID partnerToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Replace with your actual partner token providerName: "John Doe", // Replace with the full name of the provider providerOrgId: "1234", // Replace with the provider's organization ID};function Controlled() { const { cancelAmbient, pauseAmbient, resumeAmbient, startAmbient, submitAmbient, init, on } = useSuki(); const [isSukiReady, setIsSukiReady] = useState(false); // Replace with your actual encounter data const currentEncounter = useMemo( () => ({ identifier: "6ec3920f-b0b1-499d-a4e9-889bf788e5ab", patient: { identifier: "905c2521-25eb-4324-9978-724636df3436", name: { use: "official", family: "Doe", given: ["John"], suffix: ["MD"], }, birthDate: "1990-01-01", gender: "Male", }, }), [] ); // Initialize SDK when component mounts useEffect(() => { init(SUKI_OPTIONS); }, [init]); // Set up event listeners for SDK initialization and readiness useEffect(() => { const unsubscribeInit = on("init:change", (isInitialized) => { if (!isInitialized) { setIsSukiReady(false); // Reset the ready state if initialization fails } }); const unsubscribeReady = on("ready", () => { setIsSukiReady(true); }); return () => { unsubscribeInit(); unsubscribeReady(); }; }, [on]); return ( <> <SukiAssistant encounter={currentEncounter} ambientOptions={{ sections: [ { loinc: "51848-0" }, { loinc: "11450-4" }, { loinc: "29545-1" }, ], }} /> {isSukiReady && ( <div> <button onClick={startAmbient}>Start Ambient</button> <button onClick={pauseAmbient}>Pause Ambient</button> <button onClick={resumeAmbient}>Resume Ambient</button> <button onClick={cancelAmbient}>Cancel Ambient</button> <button onClick={submitAmbient}>Submit Ambient</button> </div> )} {/* Rest of your code */} </> );}
Passing new encounter data or ambient options to the SukiAssistant component automatically updates the encounter details or sections for note generation.
The SDK emits events to track ambient session status in real-time. The ambient:update event includes an ambientId field, which is the unique identifier for the session. Use this ID to track the session lifecycle. For details, see emitter events types.
The SDK emits these events when the session state changes:
ambient:start - Emitted when a new ambient session is started.
ambient:pause - Emitted when the ambient session is paused.
ambient:resume - Emitted when the ambient session is resumed.
ambient:cancel - Emitted when the ambient session is cancelled.
ambient:submit - Emitted when the ambient session is submitted.
JavaScript
React
JavaScript
Copy
Ask AI
sdkClient.on("ambient:update", (flags) => { console.log("Ambient in progress:", flags.isAmbientInProgress); console.log("Ambient paused:", flags.isAmbientPaused);});// lifecycle events supported by the Web SDKsdkClient.on("ambient:start", (ambientSessionId) => { // New in v2.0.4console.log("Ambient started:", ambientSessionId);});
Problem-based charting organizes clinical documentation around patient problems and their management. The SDK supports this by letting you mark a section as the Problem-Based Note (PBN) using the isPBNSection flag with LOINC codes in ambientOptions.
Only one section can have isPBNSection: true. If multiple sections are marked as PBN, the ambient session will fail to start.
2
Explicit Flag Values
You can explicitly pass true or false for the isPBNSection flag. The value provided will be respected as-is.
3
Default Behavior
If no section includes the isPBNSection flag (i.e., left undefined) and the Assessment & Plan section (51847-2) is present, that section will automatically be treated as the PBN.
4
Override Default
If you explicitly set isPBNSection: false on the Assessment & Plan section, the automatic default behavior will not apply.
For a given ambient session, only one section can have isPBNSection: true. If more than one section is marked as PBN, the ambient session will fail to start.
The SDK supports offline mode to keep sessions running during connectivity issues. When offline, the SDK continues recording and processing seamlessly.
New: The SDK uses a 15-second buffer before entering offline mode. This gives you time to show a “Connection unstable” notification before the session goes fully offline.
When the session enters offline mode, the SDK automatically:
Continues Recording
Audio recording continues without interruption during network issues.
Local Storage
Audio and metadata are stored locally on the device.
Automatic Upload
Stored data is automatically uploaded once connection is restored.
User Notification
Users are notified about offline status and reconnection attempts.
During offline mode, session submission is temporarily paused. The SDK will continuously attempt to reconnect and submit the note once connectivity is reestablished.
If the app crashes or a session is abandoned (not cancelled or submitted), the SDK automatically recovers the last ambient session when the app loads again.
The last recorded audio is restored and made available for processing.
Reattach Session Metadata
Session metadata (encounter details, timestamps, configuration) is reattached to maintain continuity.
User Prompt
The user is prompted to either generate the note or discard the session. If the user chooses to generate the note, the SDK proceeds with note generation in the background.
Always submit or cancel the active ambient session when users navigate away from the encounter. This prevents unintended session recoveries.Recommendation: Show a confirmation dialog before navigation so users can decide whether to continue or discard the session.