Agentic Workforce ME Developer PortalDocs 1.0 · Widget 0.1.0

Reference

JavaScript API & events

HiveChat.init handle methods, element events and programmatic control recipes.

Three objects matter: the global HiveChat API (the loader puts it on window; the ESM build exports it), the handle returned by HiveChat.init, and the <hive-chat> element itself, which dispatches DOM events.

HiveChat

MemberSignatureDescription
versionreadonly version: stringBuild version of the loaded bundle (the @hive/embed package version, currently 0.1.0); the URL path /embed/v1/ is the compatibility line.
initinit(opts: HiveChatOptions, container?: Element | null): HiveChatHandleCreates a <hive-chat> (launcher mode: appended to document.body; or into container). Calling it again with the same key reuses the existing widget and applies the new options.

HiveChatHandle

MemberSignatureDescription
elementreadonly element: HiveChatElementThe underlying custom element — add event listeners here.
openopen(): voidOpen the panel and focus the composer.
closeclose(): voidClose the panel; focus returns to the launcher.
toggletoggle(): voidOpen or close.
sendsend(text: string): Promise<void>Send a message as the end user and follow the run until it settles. Ignored while another turn is in flight.
resetreset(): voidForget the current thread and start fresh (also cancels a live stream).
updateupdate(opts: Partial<HiveChatOptions>): voidChange options in place — theme/locale/texts re-render without a new session; changing key, apiUrl, user.token, storage or visitorId re-mints.
destroydestroy(): voidRemove the element and forget the handle.
TypeScript
const chat = HiveChat.init({ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY' });

chat.open();                       // show the panel
await chat.send('Where is my order?');   // send as the visitor, resolves when the run settles
chat.update({ locale: 'ar' });     // re-render in Arabic, same session
chat.reset();                      // new thread
chat.destroy();                    // remove the element

HiveChatElement

The element registered as hive-chat. Everything on the handle is a thin call into it. Useful when you create elements in markup (Vue, Angular, plain HTML):

MemberSignatureDescription
configureconfigure(opts: Partial<HiveChatOptions>): voidMerge options programmatically (what the loader and React wrapper use). Attributes still win over programmatic values.
openopen(): voidSame as the handle.
closeclose(): voidSame as the handle.
toggletoggle(): voidSame as the handle.
sendsend(text: string): Promise<void>Same as the handle.
resetreset(): voidSame as the handle.
threadIdreadonly threadId: string | nullThe current thread id (null before the first message).
HTML
<!-- Drive the element directly (no loader) -->
<hive-chat id="support" key="hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY" api-url="https://HIVE" mode="inline"
           style="display:block;height:600px"></hive-chat>
<script type="module">
  import 'https://HIVE/embed/v1/hive-embed.mjs';
  const el = document.getElementById('support');
  el.addEventListener('hive:ready', () => el.send('Hello!'));
  console.log(el.threadId);   // null until the first message is accepted
</script>

Events

All events are CustomEvents dispatched on the <hive-chat> host, bubbles: true and composed: true, so you can also listen on document. The React wrapper maps each to a prop.

EventdetailWhenReact prop
hive:ready{ key_id }Display config loaded (GET /v1/embed/config); the launcher/panel is rendered and usable. No session exists yet.onReady
hive:session{ visitor_id, identified }A session token was minted — on the first open (launcher mode), on mount (inline mode) or on the first send(), whichever comes first. identified is true when a valid identity JWT was presented.onSession
hive:openundefinedThe panel opened (launcher click, open(), or the open attribute).onOpen
hive:closeundefinedThe panel closed (close button, Escape, or close()).onClose
hive:message{ role: 'user' | 'agent', text }A user turn was sent, or an agent reply completed.onMessage
hive:error{ code }Config fetch, session or run failure — an API problem code (e.g. EMBED_ORIGIN_DENIED, RATE_LIMITED), or a widget code (NETWORK, STREAM_LOST, HTTP_<status>).onError
JavaScript
const chat = HiveChat.init({ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY' });
const el = chat.element;

el.addEventListener('hive:ready', (e) => {
  console.log('config loaded for key', e.detail.key_id);   // no session yet
});
el.addEventListener('hive:session', (e) => {
  const { visitor_id, identified } = e.detail;   // minted on first open / first send
  analytics.identify(visitor_id);
});
el.addEventListener('hive:message', (e) => {
  const { role, text } = e.detail;      // 'user' | 'agent'
  analytics.track('chat_message', { role, length: text.length });
});
el.addEventListener('hive:error', (e) => {
  console.warn('hive-chat error', e.detail.code);   // e.g. 'RATE_LIMITED'
});
el.addEventListener('hive:open', () => document.body.classList.add('chat-open'));
el.addEventListener('hive:close', () => document.body.classList.remove('chat-open'));
TypeScript
// TypeScript: the events are plain CustomEvents — type the detail yourself
import type { HiveChatElement } from '@hive/embed';

type HiveEvents = {
  'hive:ready': { key_id: string };
  'hive:session': { visitor_id: string; identified: boolean };
  'hive:message': { role: 'user' | 'agent'; text: string };
  'hive:error': { code: string };
};

function on<K extends keyof HiveEvents>(
  el: HiveChatElement, name: K, fn: (detail: HiveEvents[K]) => void,
) {
  el.addEventListener(name, (e) => fn((e as CustomEvent<HiveEvents[K]>).detail));
}

Error codes in hive:error

detail.code is either a platform problem code (see the REST reference EMBED_ORIGIN_DENIED, EMBED_KEY_DISABLED, RATE_LIMITED, AGENT_NOT_PUBLISHED…) or one of the widget’s own:

CodeMeaning
CONFIGInvalid init options (bad key format, or apiUrl could not be inferred). Logged as a [hive-embed] console warning and the panel shows the offline notice; this one is internal — no hive:error event is dispatched.
NETWORKThe fetch itself failed (offline, DNS, CSP connect-src block, mixed content).
STREAM_LOSTThe SSE stream dropped and three reconnect attempts (with ?since) failed.
HTTP_<status>The API answered with a non-JSON error body (e.g. a proxy 502).

A run that ends with the SSE event run.failed renders an error bubble with the run’s failure code and a Retry action; it is a run outcome, not a transport failure, so it does not dispatch hive:error.

Recipes

Open on a button click

HTML
<button id="help">Need help?</button>
<script async src="https://HIVE/embed/v1/hive-embed.js" data-key="hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY"></script>
<script>
  // The script is async: a click can land before it has loaded, when
  // window.HiveChat is still the stub below and has no init(). The loader
  // drains the queue (q: [[options, container?]]) as soon as it runs.
  window.HiveChat = window.HiveChat || { q: [] };
  document.getElementById('help').addEventListener('click', () => {
    if (typeof window.HiveChat.init === 'function') {
      // Loaded: init() is idempotent per key and returns the auto-initialized handle.
      window.HiveChat.init({ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY' }).open();
    } else {
      // Not yet: queue an init that opens the panel once the bundle arrives.
      window.HiveChat.q.push([{ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY', open: true }]);
    }
  });
</script>

Prefill from page context

JavaScript
// Open with a context-aware first message (sent as the visitor).
const chat = HiveChat.init({ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY' });

document.querySelector('#ask-about-product').addEventListener('click', async () => {
  chat.open();
  await chat.send(`I have a question about ${document.title} (${location.pathname})`);
});

Pass page URL / user metadata

JavaScript
// Pass page URL and user metadata — the safe way.
//
// The widget sends no free-form metadata from the browser (it is untrusted).
// Page context therefore travels either as part of the message text (visible
// to the visitor, above) or — for attributes you vouch for — inside the
// identity JWT your backend signs:
//
//   { sub: user.id, name: user.name, meta: { plan: 'pro', region: 'ae', page: '/pricing' } }
//
// meta lands on the contact record (end_users.attributes.embed) and is visible
// to operators in the console; it is not injected into the prompt.
const { token } = await fetch('/api/hive-identity?page=' + encodeURIComponent(location.pathname))
  .then((r) => r.json());
HiveChat.init({ key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY', user: { token } });

Single-page apps, login and logout

JavaScript
// Single-page apps: create once, update on route change, destroy on logout.
let chat;

export function mountChat(user) {
  chat = HiveChat.init({
    key: 'hive_pk_REPLACE_WITH_YOUR_PUBLISHABLE_KEY',
    locale: document.documentElement.lang.startsWith('ar') ? 'ar' : 'en',
    user: user ? { token: user.hiveToken } : undefined,
  });
}

router.afterEach((to) => {
  // e.g. hide the launcher on checkout
  chat?.element.toggleAttribute('hidden', to.path.startsWith('/checkout'));
});

export function onLogout() {
  chat?.reset();                       // drop the identified thread
  chat?.update({ user: undefined });   // continue as anonymous …
  // … or chat?.destroy() to remove it entirely
}

ESM exports

Beyond HiveChat, the ESM build (@hive/embed / /embed/v1/hive-embed.mjs) exports the building blocks, so you can reuse the API client, the Markdown renderer or the SSE parser in a custom UI:

HiveChat, HiveChatElement, TAG, defineHiveChat, setDefaultApiUrl, VERSION, EmbedClient, EmbedApiError, HiveChatConfigError, resolveOptions, sanitizeTheme, mergeTheme, themeToCssVars, resolveLocale, dirFor, STRINGS, renderMarkdown, escapeHtml, createSseParser, reduce, initialState

Types: HiveChatOptions, HiveChatHandle, HiveChatApi, EmbedTheme, EmbedDisplayConfig, EmbedPublicConfig, EmbedSession, EmbedEvent, HistoryMessage, ProblemDocument, ChatState, ChatMessage, Strings, SseFrame.