> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hibonsai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Events & API

> Events you can dispatch and listen for, and the window.BonsaiAgent global

## How the Concierge is controlled

The Concierge renders in a closed shadow DOM, so you never reach into it directly. Instead it listens for events on `window` and dispatches events back the same way.

<Callout color="#0A5B3B" icon="info">
  **Events are dispatched on `window`, not on the `<bonsai-chat-bubble>` element.** Attach listeners with `window.addEventListener(...)`. A listener bound to the element itself will never fire.
</Callout>

## Events you dispatch

### `bonsai:open-chat`

Opens the chat panel, reusing the configuration on your `<bonsai-chat-bubble>` tag. This is the recommended way to open the Concierge from your own UI.

```js theme={null}
window.dispatchEvent(new CustomEvent("bonsai:open-chat"));
```

Optionally seed the conversation with an opening question:

```js theme={null}
window.dispatchEvent(
  new CustomEvent("bonsai:open-chat", {
    detail: { query: "Do you carry this in stock?" },
  })
);
```

| Detail field | Type   | Notes                                                                       |
| ------------ | ------ | --------------------------------------------------------------------------- |
| `query`      | string | Opening question to send on the shopper's behalf                            |
| `source`     | string | Label recorded against the conversation for analytics. Defaults to `bubble` |

This event is ignored if no `<bonsai-chat-bubble>` is present on the page, since that tag is what supplies the API key and panel configuration.

### `bonsai:search`

Tells the Concierge that a shopper ran an on-site search, so it can offer to refine the results conversationally. The Bonsai search components dispatch this for you; dispatch it yourself only if you are wiring up a search experience the Concierge does not already know about.

Set `disable-search-refine` on the tag to make the Concierge ignore this event entirely.

### `bonsai:agent-reset-search`

Clears the remembered search state, so the next `bonsai:search` is treated as a fresh query rather than a repeat.

## Events you listen for

### `bonsai:support-handoff`

Fires when the conversation reaches a point where a human should take over. Use it to open your own support widget, route to a contact form, or record the escalation.

```js theme={null}
window.addEventListener("bonsai:support-handoff", (event) => {
  const { reason, sessionId, messageId } = event.detail;
  console.log("Escalating to support", reason, sessionId);
  // Open your own support channel here
});
```

| Detail field | Type   | Notes                                                            |
| ------------ | ------ | ---------------------------------------------------------------- |
| `reason`     | string | What triggered it — see below                                    |
| `sessionId`  | string | The conversation this relates to. Absent when `reason` is `user` |
| `messageId`  | string | The message that triggered it. Absent when `reason` is `user`    |
| `url`        | string | Destination URL. Present only when `reason` is `support-card`    |
| `label`      | string | Link text. Present only when `reason` is `support-card`          |

| `reason`       | Meaning                                                                       |
| -------------- | ----------------------------------------------------------------------------- |
| `auto`         | The assistant determined on its own that the conversation should be escalated |
| `user`         | The shopper pressed the Customer Care Team button in the panel header         |
| `support-card` | The shopper clicked a support link the assistant offered in a reply           |

<Callout color="#0A5B3B" icon="circle-alert">
  **Requires the `handoff` attribute.** Without it the header button and the support cards are not rendered, and the automatic escalation does not run, so this event never fires.
</Callout>

An `auto` handoff fires **once per message** — the component records which messages have already escalated, so reloading the page or reopening the panel does not re-fire it for the same reply.

## The `window.BonsaiAgent` global

Loading the script exposes two functions:

```js theme={null}
window.BonsaiAgent.openChat(options); // Open with an explicit configuration
window.BonsaiAgent.closeChat();       // Close the panel
```

<Callout color="#0A5B3B" icon="circle-alert">
  **`openChat` requires a configuration object** — it does not read your `<bonsai-chat-bubble>` tag. At minimum it needs `apiKey` and `externalId`:

  ```js theme={null}
  window.BonsaiAgent.openChat({ apiKey: "API-KEY", externalId: "" });
  ```

  Prefer dispatching `bonsai:open-chat` instead. It reuses the configuration already on your tag, so your API key stays in one place and every entry point behaves identically.
</Callout>

`closeChat()` takes no arguments and is safe to call when the panel is already closed.

The global is assigned asynchronously just after the script loads. If you call it from an inline script in the same tick, guard for it:

```js theme={null}
if (window.BonsaiAgent) window.BonsaiAgent.closeChat();
```
