Skip to main content
Deepgram's Docs

Search documentation

Type to search this documentation.

On this pageOverview

Widget Embedding Guide

Add a voice agent to any website. No framework required, no build step needed. The widget ships as a self-contained bundle with its own Preact runtime (~160KB gzipped), six layout modes, and full design-token theming. It works from a CDN or as an ES module, and tears down cleanly for single-page apps.

Bash
JavaScript
import { init } from "@deepgram/agents-widget";
const teardown = init({
  tokenFactory: () => fetch("/api/deepgram-token").then((r) => r.text()),
  agent: "YOUR_AGENT_ID",
  layout: "sidebar",
});
// Call teardown() to unmount the widget and clean up

Replace YOUR_AGENT_ID with a Reusable Agent Configuration UUID, or pass an inline agent config object instead. See Agent Configuration for both patterns.

Load the widget from cdn.deepgram.com for a no-build path:

HTML
<script src="https://cdn.deepgram.com/widgets/latest/widget.umd.js"></script>
<script>
  const teardown = DeepgramAgent.init({
    tokenFactory: () => fetch("/api/deepgram-token").then((r) => r.text()),
    agent: "YOUR_AGENT_ID",
  });
</script>

The latest segment in the URL above is replaced with the current pinned version when this page loads, so the snippet you copy targets a specific build, not a moving release pointer.

The package ships a UMD bundle at dist/widget.umd.js for <script>-tag usage. Copy or symlink it from node_modules/@deepgram/agents-widget/dist/widget.umd.js into your static assets, then load it like any other script:

HTML
<script src="/assets/widget.umd.js"></script>
<script>
  const teardown = DeepgramAgent.init({
    tokenFactory: () => fetch("/api/deepgram-token").then((r) => r.text()),
    agent: "YOUR_AGENT_ID",
  });
</script>

The widget ships with six layout modes. Set the layout option to choose one.

A panel that slides in from the edge of the screen. Toggled by a floating action button (FAB).

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "sidebar",
  placement: "bottom-right",
  defaultOpen: false,
  dismissible: true,
});

A FAB button that reveals a floating overlay panel.

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "floating",
  placement: "bottom-right",
});

Mounts directly into an existing DOM element. No FAB, no overlay.

HTML
<div id="agent-container"></div>
JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "inline",
  containerId: "agent-container",
});

Full-width card with configurable aspect ratio. Includes the conversation transcript. Ideal for landing pages and product demos.

HTML
<div id="agent-embed"></div>
JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "embedded",
  containerId: "agent-embed",
  theme: {
    aspect: "16 / 9",
    minHeight: "400px",
  },
});

A single talk button — press to start, press again to stop. Minimal footprint.

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "button",
  placement: "bottom-right",
});

The Deepgram animated hoop visualization with start/stop controls. Audio-reactive — the orb responds to input and output volume in real time.

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "orb",
  placement: "bottom-right",
});

For layouts with a FAB (sidebar, floating, button, orb), set where the button appears:

JavaScript
placement: "bottom-right" // default
// Options: "bottom-right", "bottom-left", "bottom",
//          "top-right", "top-left", "top"

To use your own button instead of the built-in FAB, pass its element ID:

HTML
<button id="my-agent-btn">Talk to AI</button>
JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "sidebar",
  buttonId: "my-agent-btn",
});

To toggle the widget programmatically from anywhere:

JavaScript
document.dispatchEvent(new Event("dg-agent-toggle"));

Toggle UI features on or off:

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  showTranscript: true,    // conversation history (default: true)
  showMicToggle: true,     // microphone mute button (default: true)
  showSpeakerToggle: true, // speaker mute button (default: true)
  showTextInput: true,     // text input field (default: true)
});

Override labels and placeholder text:

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  text: {
    name: "Aria",
    startLabel: "Talk to Aria",
    stopLabel: "End conversation",
    connectingLabel: "Connecting...",
    inputPlaceholder: "Type a message...",
    emptyStateHint: "Press start to begin talking.",
  },
});

Override the agent’s system prompt or greeting for this session without changing the agent configuration in the Deepgram console:

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  overrides: {
    systemPrompt: "You are a customer support agent for Acme Corp.",
    greeting: "Hi! How can I help you with your Acme account?",
  },
});

Listen to agent lifecycle events for analytics, logging, or UI integration:

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  on: {
    onConnect: () => console.log("Connected"),
    onDisconnect: (reason) => console.log("Disconnected:", reason),
    onError: (err) => console.error("Error:", err),
    onMessage: (msg) => console.log(`${msg.role}: ${msg.content}`),
    onAgentStartedSpeaking: (msg) => console.log("Agent speaking"),
    onFunctionCallRequest: (msg) => console.log("Function call:", msg),
    onAgentError: (msg) => console.error("Agent error:", msg),
    onReconnecting: (attempt, delayMs) =>
      console.log(`Reconnecting (attempt ${attempt}, ${delayMs}ms)`),
  },
});
Callback Fires when
onConnect WebSocket connection opens
onDisconnect Session ends (user or server side)
onError SDK-level error occurs
onMessage Any conversation turn (user or assistant text)
onAgentStartedSpeaking Agent begins speaking; includes latency metrics
onFunctionCallRequest Agent requests a client-side function call
onAgentError Agent-reported error (distinct from SDK errors)
onReconnecting Reconnect attempt starts; receives attempt number and delay

Control how the widget adapts to light and dark mode:

JavaScript
// Automatic -- follows prefers-color-scheme (default)
colorScheme: "auto"
// Force light or dark
colorScheme: "light"
colorScheme: "dark"
// Class-based -- for CSS framework integration (e.g., Tailwind dark mode)
colorScheme: {
  mode: "class",
  darkSelector: ".dark",   // default
  lightSelector: ".light", // default
}

The class-based option watches for a CSS selector on any ancestor element. Use it when the host app controls theme via a class on <html> rather than OS preference.

Customize the widget’s appearance by overriding design tokens. Each property maps to a CSS custom property on the widget root element ([data-dg-agent]). Set a token here to override the built-in adaptive default in both light and dark modes.

JavaScript
init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  theme: {
    // Accent
    primary: "#6366f1",
    primaryHover: "#4f46e5",
    primaryActive: "#4338ca",
    onPrimary: "#ffffff",
    // Surface
    background: "#ffffff",
    backgroundRaised: "#f9fafb",
    backgroundInput: "#ffffff",
    backgroundHover: "#f3f4f6",
    backgroundActive: "#e5e7eb",
    // Text
    text: "#111827",
    textMuted: "#6b7280",
    // Chrome
    border: "#e5e7eb",
    error: "#ef4444",
    overlay: "rgba(0, 0, 0, 0.25)",
    // Messages
    userMessageBackground: "#f3f4f6",
    userMessageBorder: "#e5e7eb",
    // Radius
    panelRadius: "16px",
    buttonRadius: "9999px",
    inputRadius: "8px",
    messageRadius: "12px",
    // Structural
    fabSize: 56,
    padding: "16px",
    font: "Inter, system-ui, sans-serif",
  },
});

To override only one color scheme, skip the theme option and write CSS directly:

CSS
@media (prefers-color-scheme: dark) {
  [data-dg-agent] {
    --dg-va-bg: #0d1117;
  }
}

The embedded layout supports additional sizing tokens:

JavaScript
theme: {
  aspect: "4 / 3",       // CSS aspect-ratio (default: "4 / 3")
  minHeight: "320px",     // default: "320px"
  maxHeight: "80vh",      // default: "80vh"
}
JavaScript
init({
  // -- Auth (one required) --
  apiKey: "...",                              // Development only
  tokenFactory: () => Promise<string>,        // Production
  // -- Agent --
  agent: "AGENT_ID" | AgentSettingsObject,    // Required
  overrides: { systemPrompt, greeting },
  // -- Layout --
  layout: "sidebar",                          // sidebar | inline | floating
                                              // button | embedded | orb
  placement: "bottom-right",                  // FAB position
  containerId: "my-element",                  // Required for inline / embedded
  buttonId: "my-button",                      // External trigger element
  defaultOpen: false,                         // Start panel open (sidebar/floating)
  dismissible: true,                          // Allow close/dismiss
  // -- Features --
  showTranscript: true,
  showMicToggle: true,
  showSpeakerToggle: true,
  showTextInput: true,
  // -- Text --
  text: {
    name, startLabel, stopLabel,
    connectingLabel, inputPlaceholder, emptyStateHint,
  },
  // -- Theming --
  colorScheme: "auto" | "light" | "dark"
             | { mode: "class", darkSelector, lightSelector },
  theme: { /* design tokens listed above */ },
  // -- Callbacks --
  on: {
    onConnect, onDisconnect, onError, onMessage,
    onAgentStartedSpeaking, onFunctionCallRequest,
    onAgentError, onReconnecting,
  },
  // -- Audio --
  playerSampleRate: 24_000,                   // Agent audio sample rate
  // -- Network --
  url: "wss://...",                           // Custom WebSocket URL (proxy)
});

The init() function returns a teardown function. Call it to unmount the widget, remove all injected styles, and release audio resources. This is essential for single-page apps where the widget mounts and unmounts as the user navigates.

JavaScript
const teardown = init({
  tokenFactory,
  agent: "YOUR_AGENT_ID",
  layout: "sidebar",
});
// When the user navigates away or you no longer need the widget:
teardown();

For frameworks with lifecycle hooks, call teardown in the cleanup phase:

JavaScript
// React useEffect
useEffect(() => {
  const teardown = init({ tokenFactory, agent: "YOUR_AGENT_ID" });
  return teardown;
}, []);
// Vue onUnmounted
onMounted(() => {
  const teardown = init({ tokenFactory, agent: "YOUR_AGENT_ID" });
  onUnmounted(teardown);
});
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu