Skip to content

Page API reference

The embed has no SDK package. Your page talks to it through the loader’s script tag, one configuration object you define, and one control object the loader defines.

<script src="https://embed.bunkhouse.ai/embed.js" data-public-key="pk_YOUR_SITE_PUBLIC_KEY"></script>

Load it with a classic <script src> tag (not a module, not injected inline) before your application’s entry script.

Attribute Purpose
data-public-key Required. The site’s publishable key.
data-session-endpoint Server mint mode: your same-origin endpoint that creates the session.
data-hints-url Fallback hints path, used only when the site has no hints path configured. Must be same-origin.
nonce Applied to the scripts and styles the embed adds, for nonce-based Content Security Policies.

The loader is a singleton: a second copy of the tag is ignored, and a second tag with a different data-public-key is reported as an installation error.

The embed keeps working across navigation that rewrites the page without loading a new document, such as Turbo Drive, htmx boost, Livewire wire:navigate and Blazor enhanced navigation. Its launcher and pane live in one element directly under <html>, so replacing <body> leaves them in place. If your framework removes that element or rewrites the <html> attributes, the embed puts back its element and --agent-embed-width on its own. The open pane, transcript and session are kept. If the element was removed, the agent’s code sandbox restarts: code that was running at that moment fails and the agent is told, and the next code it runs uses a new sandbox. If your page keeps removing the element, the embed stops restoring it and reports an error in status.error.

Navigation does not change the signed-in user. Call resetSession() on sign-in, sign-out and account switch, as you would with full page loads.

Define this object before the loader. Every field is optional.

Field Type Purpose
getIdentityToken () => string | Promise<string> Identity-token mode: return a token your backend signed for the current user. Its presence selects this mode.
getAuthHeaders ({ operationId, url, method }) => Record<string, string> | Promise<...> Extra headers, such as a CSRF token, for the assistant’s calls to your API. Called only after the destination is authorized; values never reach the model or sandbox. Cookie, host and browser-controlled headers are refused.
sensitiveFields string[] Additional field names whose values are treated as sensitive.
layoutTarget CSS selector Your app’s normal-flow wrapper; while the pane is open on desktop, it reserves the pane’s width as right margin.
onWrite (write) => void | Promise<void> Called after each direct API write that succeeded or has an unknown outcome, so you can refresh your UI. Receives { skillId, transport: "api", status, method, origin, path }, never request or response bodies.

Session mode is chosen when a session starts: getIdentityToken if defined, otherwise data-session-endpoint if set, otherwise anonymous.

The loader defines a frozen, read-only window.AgentEmbed as soon as it runs; the pane itself loads on first open. Before then, stop() does nothing and resetSession() drops what was observed so far.

Member Purpose
open() Open the pane.
close() Close the pane.
stop() Stop the current run.
resetSession() Drop the session and anything observed for the current user. Call on sign-in, sign-out and account switch.
destroy() Remove the launcher and pane, restore the page’s fetch/XHR and delete window.AgentEmbed.
status Read-only snapshot, below.

status has these fields:

Field Values
state idle, thinking, executing, awaiting_approval, completed, failed or cancelled
open true while the pane is open
sessionKind signed, anonymous or null before a session exists
skillCount Number of skills currently available
error Latest error message, or null

When the pane opens, closes or is resized, the embed sets the --agent-embed-width CSS custom property on <html> to the width it occupies (0px when closed) and dispatches an agentembed:resize event on window with detail.width in pixels:

window.addEventListener("agentembed:resize", (event) => {
console.log("Assistant pane width", event.detail.width);
});
.app-toolbar { margin-right: var(--agent-embed-width, 0px); }