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

# <mindset-agent> element

> The custom HTML element that hosts an agent on your page. Attributes, properties, registration, and the headless mode toggle.

`<mindset-agent>` is the customer-facing surface of the Mindset AI SDK. Drop it in your HTML, give it an agent UID, and an agent appears. The element handles auth, streaming, state, and (unless you opt out) rendering its own chat UI.

```html theme={null}
<mindset-agent agent-uid="agt-abc123"></mindset-agent>
```

You configure the element with HTML attributes for one-time setup, listen for events to react to what the agent does, and call methods on it to drive turns. This page covers the attributes and the registration lifecycle. See the [methods reference](./methods.mdx) and [events reference](./events.mdx) for the full method and event surface.

***

## Two modes: chat UI vs headless

The element has one optional toggle that changes everything: the `headless` attribute.

### Default (chat UI rendered)

Without `headless`, the element renders Mindset AI's built-in chat UI inside a shadow DOM. Your users see a chat panel; you don't write any UI code.

```html theme={null}
<mindset-agent agent-uid="agt-abc123"></mindset-agent>
```

This is the right choice when:

* You want a working chat experience in minutes
* Mindset AI's UI matches your needs (configurable theme, customizable widgets, branded buttons)
* You don't have strong design constraints

### Headless (you render the UI)

With `headless`, the element runs the agent and dispatches DOM events but does *not* render any UI. You build the chat (or whatever interface you want) using events and methods.

```html theme={null}
<mindset-agent agent-uid="agt-abc123" headless></mindset-agent>
```

This is the right choice when:

* You have an existing UI design and want the agent to drive it
* You need a non-chat surface, like voice, slash commands, or an embedded recommendation panel
* You're integrating into a framework (React, Vue, Svelte) and want full control

The runtime, state machine, auth flow, and DOM events are *identical* in both modes. The only difference is whether the element renders its own chat UI.

<Note>
  **Icebreakers fire in headless mode too.** If your agent is configured with an icebreaker (a turn that fires automatically when the agent starts), it runs in headless mode just like it does with the built-in chat UI. You'll see `mindset:agent-busy → mindset:text-delta → mindset:complete → mindset:agent-idle` before your first `sendMessage` runs. Use the [`sendWhenIdle` pattern](./methods.mdx#waiting-for-the-agent-to-be-ready) to handle this safely.
</Note>

***

## Attributes

You set attributes once when the element is added to the DOM. The element reads them on first render. After that, use the corresponding [JS methods](./methods.mdx) to update values dynamically.

### Required

| Attribute   | Type         | Description                                                                    |
| ----------- | ------------ | ------------------------------------------------------------------------------ |
| `agent-uid` | string (UID) | The agent to load. Each agent in the Agent Management Studio has a unique UID. |

Your app's UID is **not** a per-element attribute. Pass it once via `mindset.init({ appUid })`. It's a page-level concern and applies to every `<mindset-agent>` element on the page.

### Mode

| Attribute  | Type                    | Description                                                                                                     |
| ---------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `headless` | boolean (presence wins) | When present, the element runs the agent without rendering UI. See [Two modes](#two-modes-chat-ui-vs-headless). |

### Configuration (alternative to JS methods)

Each of these attributes mirrors a JS method on the element. The attribute path is convenient when your initial setup is static and known at render time. Use the JS method when you need to update the value later.

| Attribute               | Type                         | Equivalent method                                                                                                                                              |
| ----------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `passthrough-params`    | JSON object as string        | `agent.setPassthroughParams(params)`                                                                                                                           |
| `situational-awareness` | JSON object as string        | `agent.setSituationalAwareness(sa)`                                                                                                                            |
| `initial-question`      | string                       | Auto-sends a first message when the agent loads                                                                                                                |
| `thread-uid`            | string (thread UID)          | Resumes an existing thread on mount. Works in both modes. No icebreaker fires when this is set, because the agent loads the existing thread's history instead. |
| `theme`                 | JSON `ThemeConfig` as string | Per-agent theme override                                                                                                                                       |
| `show-thread-list`      | `"true"` or `"false"`        | Show or hide the thread list panel in the chat UI. Default: true. Ignored in headless mode.                                                                    |

Most of these accept both kebab-case and camelCase forms (`passthrough-params` and `passthroughParams` work the same). Kebab-case is the recommended form because it's the HTML standard.

```html theme={null}
<mindset-agent
  agent-uid="agt-abc123"
  situational-awareness='{"currentPage":"/products","userPlan":"enterprise"}'
  initial-question="What's new this week?"
></mindset-agent>
```

***

## Properties

Properties are read-only fields you access on the element instance after it's registered.

| Property          | Type             | Description                                                                                                                                                                                                                                                                     |
| ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agent.threadUid` | `string \| null` | The active thread UID. `null` if the element isn't bound to a runtime yet, or if the current thread is local-only (just created via `newThread()`, no persisted user-message turn yet). See [thread-uid persistence semantics](./methods.mdx#thread-uid-persistence-semantics). |

```js theme={null}
const agent = document.querySelector('mindset-agent');
console.log('Active thread:', agent.threadUid);
```

The thread UID is also available via the `mindset:thread-changed` event when it changes.

***

## Methods

The element has methods for driving turns, configuring per-agent state, and managing threads. All documented in the [methods reference](./methods.mdx). Quick summary:

* `agent.sendMessage(text, options?)` sends a user message
* `agent.setPageTools(tools)`, `setSituationalAwareness(sa)`, `setPassthroughParams(params)` configure per-agent state
* `agent.newThread()`, `switchThread(uid)`, `deleteThread(uid)`, `renameThread(uid, title)`, `listThreads(options?)` manage threads
* `agent.isAgentBusy()` checks turn state
* `agent.stop()` cancels the in-flight turn (the only way to stop a turn in headless mode)

***

## Registration lifecycle

The element follows the standard custom-element lifecycle. Knowing the order helps when you're debugging "why isn't my listener firing" or coordinating timing across init and DOM mount.

### When the SDK script loads

The class is registered globally:

```js theme={null}
customElements.get('mindset-agent'); // returns the constructor (MindsetAgentElement)
```

You can verify the SDK has loaded by checking this. Until it returns a value, the element is unknown to the browser.

### When the element is added to the DOM

The browser fires `connectedCallback`, which the element uses to:

1. Set `data-mindset-element-registered="true"` and `data-mindset-headless="true"` (or `"false"`) on the DOM node
2. Dispatch `mindset:agent-registered` with `event.detail = { headless: boolean }`

At this point the element exists and you can attach event listeners, but the runtime isn't bound yet. Wait for `mindset:agent-idle` before calling methods like `setPageTools` or `sendMessage`. See [§ When the element is ready to call](./methods.mdx#when-the-element-is-ready-to-call).

### When `mindset.init()` completes and binds the element

The init pipeline finds the element, attaches a runtime instance, and sets `data-instance-id="<id>"` on the DOM node. The agent begins initializing and will fire `mindset:agent-initializing` followed by `mindset:agent-idle` once ready. Methods are safe to call from `mindset:agent-idle` onward.

### When the element is removed from the DOM

The browser fires `disconnectedCallback`. The element detaches its event bridges and cleans up. State setters called after this point are no-ops.

### Registration signals you can rely on

| Signal                                                        | Where                    | When set                                 |
| ------------------------------------------------------------- | ------------------------ | ---------------------------------------- |
| `customElements.get('mindset-agent')` returns the constructor | global                   | After the SDK bundle script loads        |
| `data-mindset-element-registered="true"`                      | DOM attribute            | After `connectedCallback`                |
| `data-mindset-headless="true"` or `"false"`                   | DOM attribute            | After `connectedCallback`                |
| `mindset:agent-registered` event                              | Bubbles from the element | On `connectedCallback`                   |
| `data-instance-id="<id>"`                                     | DOM attribute            | After `mindset.init()` binds the element |
| `mindset:agent-idle` event                                    | Bubbles from the element | After init completes successfully        |

If you need to know that a specific element is ready to take messages, listen for `mindset:agent-idle` on it. If the agent has an icebreaker configured, the first `mindset:agent-idle` (init done) is followed immediately by an icebreaker turn, and the agent is fully ready for customer-driven `sendMessage` calls after the second `mindset:agent-idle`. Use the [`sendWhenIdle` pattern](./methods.mdx#waiting-for-the-agent-to-be-ready) to handle both cases without needing to know which configuration applies.

***

## Dynamic mounting (frameworks)

The SDK uses a `MutationObserver` to detect `<mindset-agent>` elements added to the DOM after `mindset.init()` has run. This means React, Vue, Svelte, and other frameworks that mount the element in a component lifecycle work without extra wiring:

```jsx theme={null}
function ChatPanel({ agentUid }) {
  return <mindset-agent agent-uid={agentUid} headless />;
}
```

The observer picks up the element when React mounts it, runs the same registration sequence as a static element, and dispatches `mindset:agent-registered`. Unmounting fires `disconnectedCallback` and cleans up the runtime binding.

See the [Examples page](./examples.mdx) (Headless: React tab) for the full pattern, including refs, useEffect cleanup, and event subscription.

***

## What's *not* on the element

These are SDK-level concerns, not per-agent. Set them via `mindset.init()`, not on individual elements:

* `appUid`: your app's identity, shared by every `<mindset-agent>` element on the page
* `extendedSituationalAwareness`: lifts the SA character limit from 10,000 to 20,000 for every agent on the page
* `fetchAuthentication` callback
* Auth state helpers (`onAuthStateChanged`, `signInWithGoogle`, etc.)

See the [SDK init reference](./sdk-init.mdx) for the full SDK-level API.
