> ## 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.

# How to integrate the Mindset AI agent into your application

> End-to-end walkthrough, from a blank page to an agent running against your data, with the client-side APIs ready to drive.

This guide walks through a Mindset AI agent integration from the start. By the end, you'll have an agent loading on your page, authenticating your user, and ready to use the client-side APIs (page tools, situational awareness, pass-through parameters, DOM events) that let your page talk to it. These APIs work whether you keep the built-in chat UI or render your own.

The integration has four pieces:

1. Configure the agent in the Agent Management Studio (tools, knowledge, behavior).
2. Set up your token endpoint, so your backend mints SDK tokens for your users.
3. Add the SDK script and element to your page: one `<script>` tag, one `<mindset-agent>` element.
4. Initialize and (optionally) build your UI. Call `mindset.init()`, then either let the agent render itself or hook into its events.

Each piece is independent. You can do (1) and (2) ahead of time, then iterate on (3) and (4) until the integration feels right.

***

## Prerequisites

Before you start, you'll need:

* A Mindset AI account and an app set up in the Agent Management Studio. This gives you an `appUid` and lets you build agents.
* An agent configured with your tools and knowledge. Each agent has an `agent-uid`. You'll reference this from your page.
* A backend that can call `sdkusersapi` to mint a token for the current user. Mindset AI doesn't talk to your auth system; you do, and you hand a token to the SDK.
* A page where you can add a `<script>` tag. Vanilla HTML, React, Vue, Svelte, or any other setup that produces HTML works.

***

<Steps>
  <Step title="Configure your agent">
    Sign in to the Agent Management Studio, build the agent you want, and copy its `agent-uid`. You'll paste this into your HTML in step 3.

    See the [Agent Management Studio walkthrough](/build-optimize/AMS/AgentManagementStudio-walkthrough) for a full tour of AMS, or [Creating Agents](/build-optimize/guides/agents/howto-create-agents) for a focused agent-build guide.
  </Step>

  <Step title="Set up your token endpoint">
    The Mindset AI SDK never talks directly to your authentication system. Instead, it asks your app for a token using a callback you provide. Your callback hits an endpoint on your backend; that endpoint calls `sdkusersapi` with your API key to mint an SDK token for the current user.

    The flow:

    ```
    Browser (your app)         Your backend             Mindset (sdkusersapi)
           │                         │                          │
           │ GET /api/mindset-token  │                          │
           ├────────────────────────▶│                          │
           │                         │ Auth + mint SDK token    │
           │                         ├─────────────────────────▶│
           │                         │                          │
           │                         │◀─────────────────────────┤
           │                         │  authToken               │
           │◀────────────────────────┤                          │
           │  { authToken }          │                          │
           │                         │                          │
    ```

    Your endpoint:

    * Authenticates the request using your existing session, JWT, or whatever you already have
    * Maps the user to a Mindset AI identity (you choose the strategy, typically your user ID becomes their Mindset AI user ID)
    * Calls `sdkusersapi` with your Mindset AI API key to mint a token
    * Returns the token to the browser

    See the [SDK 3 Authentication guide](/deploy/sdk3/sdk3-authentication) for the full setup, including request body, headers, and example implementations. The [SDK Users API reference](/deploy/api/sdkusers-api) has the parameter-level detail.
  </Step>

  <Step title="Add the SDK script and element">
    Add the SDK bundle and your `<mindset-agent>` element to the page.

    ```html theme={null}
    <!DOCTYPE html>
    <html>
    <head>
      <script src="MINDSET-SERVER-URL/mindset-sdk3.umd.js"></script>
    </head>
    <body>
      <mindset-agent agent-uid="agt-your-agent-uid"></mindset-agent>
    </body>
    </html>
    ```

    <Warning>
      Replace `MINDSET-SERVER-URL` with the URL provided by Mindset AI.
    </Warning>

    Two things happen automatically:

    * The `<script>` registers `<mindset-agent>` as a custom element. After this, `customElements.get('mindset-agent')` returns the constructor.
    * The element is added to the DOM. The `connectedCallback` fires, the element dispatches `mindset:agent-registered`, and queues itself for runtime binding.

    The element doesn't load anything yet. It's waiting for `mindset.init()` to bind it to a runtime instance.

    ### Choose your mode

    The element has two modes, set with the `headless` attribute.

    In the default mode (no `headless` attribute), Mindset AI renders a chat UI inside the element. Your users get a working chat experience with no UI code on your side.

    In headless mode (`headless` attribute present), the element runs the agent and dispatches DOM events, but renders nothing. You build the UI.

    If you're not sure which to pick, start with the default mode. Switch to headless later if you need full UI control.

    ```html theme={null}
    <!-- Built-in chat UI -->
    <mindset-agent agent-uid="agt-..."></mindset-agent>

    <!-- Headless: you build the UI -->
    <mindset-agent agent-uid="agt-..." headless></mindset-agent>
    ```

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

  <Step title="Initialize the SDK">
    Call `mindset.init()` once. This wires up the runtime, calls your `fetchAuthentication` callback, and starts loading the agent.

    ```html theme={null}
    <script>
      window.mindset.init({
        appUid: 'your-app-uid',
        fetchAuthentication: async () => {
          const r = await fetch('/api/mindset-token', { credentials: 'include' });
          const { authToken } = await r.json();
          return authToken;
        },
      });
    </script>
    ```

    You can call `init` before or after the `<mindset-agent>` element is added to the DOM. Both orders work. The SDK uses a `MutationObserver` to find elements added later, so React, Vue, and other frameworks that mount the element in a component lifecycle work without extra wiring.

    After init succeeds, each `<mindset-agent>` on the page fires:

    ```
    mindset:agent-initializing
    mindset:agent-idle              ← ready to take input
    ```

    Listen for `mindset:agent-idle` if you want to know when an agent is ready.
  </Step>
</Steps>

***

## Step 5: Render the UI

<Tabs>
  <Tab title="Default mode (built-in chat UI)">
    If you went with default mode, you're done. Mindset AI renders a chat panel inside the element. Users can chat, switch threads, and view the history.

    You can still hook into events if you want to react to what the agent does:

    ```js theme={null}
    const agent = document.querySelector('mindset-agent');

    agent.addEventListener('mindset:thread-changed', (e) => {
      // Sync the active thread to your URL. threadUid can be null between threads
      // (e.g. immediately after newThread() before the user's first message persists).
      if (e.detail.threadUid) {
        history.pushState({}, '', `?thread=${e.detail.threadUid}`);
      }
    });

    agent.addEventListener('mindset:complete', (e) => {
      // Track turn completions in your analytics
      analytics.track('agent_turn_complete', {
        agentUid: agent.getAttribute('agent-uid'),
        responseLength: e.detail.response.length,
      });
    });
    ```

    You can drive the agent programmatically too, for example to open a thread when the user clicks something on your page:

    ```js theme={null}
    async function openSupportThread(threadUid) {
      const agent = document.querySelector('mindset-agent');
      await agent.switchThread(threadUid);
    }
    ```

    See the [Examples page](./examples.mdx) (Built-in chat UI tab) for a complete working setup.
  </Tab>

  <Tab title="Headless mode (you build the UI)">
    In headless mode, the element runs the agent and dispatches DOM events. You write the UI.

    The minimum you need:

    * An input control (textarea, contenteditable div, your own component)
    * An output area for the agent's reply
    * Event listeners for `mindset:text-delta` (streaming output) and `mindset:complete` (turn end)
    * A call to `agent.sendMessage(text)` when the user submits

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

    <div id="output"></div>
    <textarea id="input"></textarea>
    <button id="send">Send</button>

    <script>
      const agent = document.getElementById('agent');
      const output = document.getElementById('output');
      const input = document.getElementById('input');

      let currentReply = '';

      agent.addEventListener('mindset:agent-busy', () => {
        currentReply = '';
        output.textContent = '';
      });

      agent.addEventListener('mindset:text-delta', (e) => {
        currentReply += e.detail.content;
        output.textContent = currentReply;
      });

      // sendWhenIdle queues the send if the agent is busy (e.g. running its
      // icebreaker turn after init). See "Choosing when to send" below.
      function sendWhenIdle(text) {
        if (!agent.isAgentBusy()) {
          agent.sendMessage(text);
        } else {
          agent.addEventListener('mindset:agent-idle', () => sendWhenIdle(text), { once: true });
        }
      }

      document.getElementById('send').addEventListener('click', () => {
        sendWhenIdle(input.value);
        input.value = '';
      });
    </script>
    ```

    ### Choosing when to send

    `sendMessage` throws if the agent is busy. The most common place this trips people up is the first send. If your agent is configured with an icebreaker (a turn that fires automatically as the agent settles after init), the lifecycle is `agent-idle` (init done) → `agent-busy` (icebreaker streaming) → `agent-idle` (icebreaker done). A user who clicks Send during that first window will hit a busy throw.

    The `sendWhenIdle` helper above handles this. It sends straight away if the agent is idle, otherwise it waits for the next `mindset:agent-idle` and recurses. Safe to call at any point, with or without an icebreaker configured. See the [methods reference](./methods.mdx#waiting-for-the-agent-to-be-ready) for the full pattern.

    This is the minimum. From here you'll typically add:

    * Thread management (list, switch, create, delete) via [thread CRUD methods](./methods.mdx#thread-crud)
    * Tool widgets that render `mindset:tool-end` payloads for tools that produce visual artifacts
    * Quick replies and follow-ups, rendering `mindset:quick-replies` and `mindset:follow-up-questions` as buttons
    * Citations and references, displaying sources from `mindset:references`

    See the [Examples page](./examples.mdx) for three complete headless integrations: vanilla HTML (thread management and widget rendering), React (component pattern with refs, useEffect, and cleanup), and Angular (standalone components, signals, and zone-safe event handling).
  </Tab>
</Tabs>

***

## Configuring per-agent state

Two common pieces of per-agent setup happen on the element itself, not in `mindset.init()`. Both have dedicated guides, [page tools](./page-tools.mdx) and [situational awareness](./situational-awareness.mdx), covering scenarios, best practices, and security in depth. The summaries below get you started.

### Page tools

Page tools are functions on your page that the agent can call during a turn. You declare the name, description, and arguments; the agent decides when to call.

```js theme={null}
const agent = document.querySelector('mindset-agent');

agent.setPageTools([
  {
    name: 'lookup_order',
    description: 'Look up the current user\'s order by ID',
    parameters: {
      type: 'object',
      properties: { orderId: { type: 'string' } },
      required: ['orderId'],
    },
    handler: async ({ orderId }) => {
      const r = await fetch(`/api/orders/${orderId}`);
      return await r.json();
    },
  },
]);
```

Call `setPageTools` whenever your tool list changes. The element applies the new value on the agent's next turn.

Call element methods only after the element has fired `mindset:agent-idle`. See [§ When the element is ready to call](./methods.mdx#when-the-element-is-ready-to-call).

### Situational awareness

Situational awareness is structured context the agent reads on every turn. Use it for the things the agent should know about the current user or the current page that the user shouldn't have to repeat.

```js theme={null}
agent.setSituationalAwareness({
  currentPage: location.pathname,
  userPlan: currentUser.plan,
  cartItems: cart.length.toString(),
});
```

Update it whenever the page state changes. The agent sees the latest values on the next turn.

***

## What's next

<CardGroup cols={2}>
  <Card title="<mindset-agent> element" icon="tag" href="/deploy/sdk3-client-apis/mindset-agent-element">
    Every attribute, property, and the registration lifecycle.
  </Card>

  <Card title="Element methods" icon="terminal" href="/deploy/sdk3-client-apis/methods">
    Every method on the element with signatures and behaviors.
  </Card>

  <Card title="DOM events" icon="bell" href="/deploy/sdk3-client-apis/events">
    Every event the element fires, with payload shapes.
  </Card>

  <Card title="SDK init" icon="gear" href="/deploy/sdk3-client-apis/sdk-init">
    window\.mindset.init() config and SDK-level helpers.
  </Card>

  <Card title="Page tools" icon="wrench" href="/deploy/sdk3-client-apis/page-tools">
    Let the agent take actions in the browser.
  </Card>

  <Card title="Situational awareness" icon="eye" href="/deploy/sdk3-client-apis/situational-awareness">
    Give the agent context about what the user is looking at.
  </Card>

  <Card title="Pass-through parameters" icon="bolt" href="/deploy/sdk3-client-apis/passthrough-parameters">
    Inject exact data into tool calls without the LLM copying it.
  </Card>
</CardGroup>

***

## Common questions

### Do I need a build step?

No. The SDK is a UMD bundle you load with a `<script>` tag. It works in any HTML page, with or without a JavaScript framework.

### Do I need an npm package?

Not for the integration itself. We may publish a TypeScript type declaration package later for IDE autocomplete; the runtime stays as a hosted bundle.

### Can I have multiple agents on one page?

Yes. Each `<mindset-agent>` element has its own runtime, state, and threads. Use different `agent-uid` values for each. See the [`<mindset-agent>` reference](./mindset-agent-element.mdx#multiple-elements-on-a-page) for the current single-active-agent constraint.

### What about TypeScript?

TypeScript declarations for the element and DOM events are on the roadmap. For now, type the events with `CustomEvent<{ ... }>` based on the [events reference](./events.mdx) payload tables.

### What about React?

Custom elements work in React out of the box. `<mindset-agent>` is a valid JSX tag. Use refs to access the element instance and `useEffect` for event subscription. See the [Examples page](./examples.mdx) (Headless: React tab).

### What about Angular?

Angular needs `CUSTOM_ELEMENTS_SCHEMA` on the component so the template accepts `<mindset-agent>`. Subscribe to events with `addEventListener` rather than template binding, because the colon in `mindset:*` event names clashes with Angular's `target:event` syntax. See the [Examples page](./examples.mdx) (Headless: Angular tab).

### Can I host the bundle myself?

The recommended path is the hosted URL. You always run the latest tested build, and we handle availability. Self-hosting is not currently supported.
