Embedding Widgets

AgentPress ships two embeddable widgets that can be added to any public site with a single <script> tag:

  • Chat widget — real-time conversational agent with support for inline, overlay, and sidebar modes.
  • Assessment widget — multi-step assessments (BVA calculator and AI Maturity Assessment).

Both widgets expose a small, imperative JavaScript API on window so you can control them from your own buttons, forms, and analytics code.

Quick Start

Chat widget

<div id="agentpress-chat"></div>
<script>
  window.__AGENTPRESS_CHAT_CONFIG__ = {
    apiKey: "pk_live_...",
    containerId: "agentpress-chat",
  };
</script>
<script src="https://your-api-host/bundles/chat/widget.js" async></script>

The widget's layout — inline, overlay, or sidebar — is controlled by the server-side embed credential configuration. You do not need to specify it on the host page.

Assessment widget

<div id="assessment-widget"></div>
<script src="https://your-api-host/bundles/assessment/widget.js"></script>
<script>
  window.AgentPressAssessmentEmbed.mount({
    containerId: "assessment-widget",
    apiBaseUrl: "https://your-api-host",
    apiKey: "pk_live_...",
    // Pick one:
    bvaConfigId: "<bva-config-id>",
    // maturityConfigId: "<maturity-config-id>",
  });
</script>

Imperative Control

Both widgets expose an API on window.AgentPressChat and window.AgentPressAssessmentEmbed respectively. Methods are safe to call before the bundle finishes loading — calls are buffered internally and flushed once the widget is ready.

Chat: open / close / toggle

window.AgentPressChat.open();
window.AgentPressChat.close();
window.AgentPressChat.toggle();
window.AgentPressChat.isOpen(); // boolean

These work for both overlay and sidebar modes. In inline mode, open/close/toggle are no-ops (the widget is always visible).

Chat: send a message from your own button

// Send into the currently-open thread
await window.AgentPressChat.sendMessage("Ask about pricing");

// Start a new thread with an initial message
await window.AgentPressChat.sendMessage("Ask about pricing", {
  newThread: true,
});
// → opens the widget, creates a new thread, sends the message

Options:

OptionDefaultDescription
newThreadfalseCreate a new thread before sending
agentIdcurrent agentOverride which agent receives the message
openWidgettrue for overlay/sidebarOpen the widget before sending. Set false to send silently

The call returns { threadId } once the message has been dispatched.

Chat: create a new thread

// Empty new thread (useful for "Start a new chat" buttons)
await window.AgentPressChat.newThread();

// New thread with a prefilled first message
await window.AgentPressChat.newThread({
  initialMessage: "I'm interested in the enterprise plan.",
});

Hide the built-in launcher

If you want to drive the sidebar entirely from your own UI — say, a navbar button — set triggerStyle: "none" in your embed credential's sidebar config (via the admin console's Embed settings). The panel mounts offscreen and stays hidden until your code calls .open().

// Your own host-page button
document.getElementById("my-chat-button").addEventListener("click", () => {
  window.AgentPressChat.open();
});

Three launcher options are available:

StyleRenderedTypical use
"tab" (default)Edge-attached tab, always visibleStandard chat widget experience
"fab"Floating action buttonCorner launcher, minimal footprint
"none"NothingHost page provides its own trigger

The legacy showTrigger: false field still works and is treated as triggerStyle: "none".

Open the sidebar automatically on first load

Sidebar widgets support an openByDefault: true flag (configured in the admin console's Embed settings) that opens the panel as soon as the widget mounts. Users can still close it, and subsequent page loads respect the flag again. Pair this with triggerStyle: "none" if you want the widget to open exactly once per page with no persistent trigger.

Events

Subscribe to lifecycle events with .on():

const unsubscribe = window.AgentPressChat.on("opened", ({ mode }) => {
  console.log(`Widget opened in ${mode} mode`);
});

// Later
unsubscribe();

Available chat events:

EventDetail
ready{ mode } — fired once the widget finishes auth + layout resolution
opened{ mode, width?, side? }
closed{ mode }
thread_created{ threadId, agentId }
message_sent{ threadId, text, role: "user" }
message_received{ threadId, text, role: "assistant" } — reserved
voice_started{ threadId } — reserved
voice_ended{ threadId, durationMs? } — reserved

Events also fire as native CustomEvents on document, namespaced agentpress:widget-ready, agentpress:thread-created, etc. Use whichever style fits your codebase:

document.addEventListener("agentpress:widget-opened", (e) => {
  console.log(e.detail); // { mode, width?, side? }
});

Assessment Widget API

The assessment widget exposes a parallel control surface:

// Reset the user's progress and restart from step 1
await window.AgentPressAssessmentEmbed.reset();

// Subscribe to events
window.AgentPressAssessmentEmbed.on("completed", (detail) => {
  if (detail.type === "maturity") {
    console.log("Snapshot:", detail.snapshotId, detail.pdfUrl);
  } else {
    console.log("BVA results:", detail.results);
  }
});

Available assessment events:

EventDetail
ready{ type: "bva" | "maturity" }
step_changed{ step }
completedBVA: { type: "bva", results }; Maturity: { type: "maturity", snapshotId, pdfUrl? }
error{ error: { message } }

open(), close(), and toggle() are reserved on the assessment widget — they are no-ops today (the widget is always inline) but are stable API so host integrations don't have to be rewritten when overlay/sidebar assessment modes ship.

TypeScript Types

For host-page TypeScript projects, the widget exposes its type surface on window. You can paste this ambient declaration into your project:

declare global {
  interface Window {
    AgentPressChat?: {
      init(containerId?: string): void;
      destroy(): void;
      open(): void;
      close(): void;
      toggle(): void;
      isOpen(): boolean;
      sendMessage(
        text: string,
        options?: {
          newThread?: boolean;
          agentId?: string;
          openWidget?: boolean;
        },
      ): Promise<{ threadId: string }>;
      newThread(options?: {
        initialMessage?: string;
        agentId?: string;
        openWidget?: boolean;
      }): Promise<{ threadId: string }>;
      on(event: string, handler: (detail: unknown) => void): () => void;
      off(event: string, handler: (detail: unknown) => void): void;
    };
    AgentPressAssessmentEmbed?: {
      init(containerId?: string): void;
      mount(config: unknown): void;
      destroy(): void;
      open(): void;
      close(): void;
      toggle(): void;
      reset(): Promise<void>;
      on(event: string, handler: (detail: unknown) => void): () => void;
      off(event: string, handler: (detail: unknown) => void): void;
    };
  }
}
export {};

Pre-init Buffering

All public methods are safe to call before the widget bundle finishes loading. The widget installs an internal readiness gate — calls made before init() completes wait for the first layout to mount and then replay in order.

For latency-sensitive integrations where you need to register an .on() listener literally before the <script> tag runs, you can publish a minimal preloader stub:

<script>
  window.AgentPressChat = window.AgentPressChat || {
    _q: [],
    on: function (event, handler) {
      this._q.push(["on", [event, handler]]);
    },
  };
</script>
<script src="https://your-api-host/bundles/chat/widget.js" async></script>

The widget detects _q on boot and drains it against the real API.

Common Patterns

"Ask about X" CTA button

<button
  onclick="window.AgentPressChat.sendMessage('Tell me about your pricing', { newThread: true })"
>
  Ask about pricing
</button>

Start-over button for an assessment

<button onclick="window.AgentPressAssessmentEmbed.reset()">Start over</button>

Sync a custom button's state with the widget

const button = document.getElementById("my-chat-button");

window.AgentPressChat.on("opened", () => {
  button.textContent = "Close chat";
});
window.AgentPressChat.on("closed", () => {
  button.textContent = "Open chat";
});

button.addEventListener("click", () => {
  window.AgentPressChat.toggle();
});

Analytics forwarding

window.AgentPressChat.on("message_sent", ({ threadId, text }) => {
  window.gtag?.("event", "chat_message_sent", {
    thread_id: threadId,
    message_length: text.length,
  });
});

On this page