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

# Build Event-Driven Agent Conversations

> A complete integration guide for creating proactive agent threads from your backend and delivering them to users via the embedded SDK.

## Overview

This guide walks through a complete integration flow where your backend system creates an agent conversation in response to an event, then delivers that conversation to your end user via the embedded SDK widget.

**What you'll build:** A backend function that detects an event, starts an agent conversation about it, and directs the user to pick it up — with the agent's response already waiting.

**Time to complete:** 20–30 minutes

**Prerequisites:**

* A Mindset AI app with a configured agent (agentVersion 3)
* An API key from the Developer section of AMS
* Your API host URL — of the form `{subdomain}.api.mindset.ai`, shown as `{api-host}` in this guide. Available in the Developer section of AMS.
* Your SDK script URL — shown as `{MINDSET_SDK_LOCATION}` in this guide. Also available in the Developer section of AMS.
* The Mindset AI SDK v3 script loaded on the page where the agent will be embedded

## How the Flow Works

Your backend makes two API calls before notifying the user, then one more when the user arrives.

```
Customer Backend                                    Mindset Platform
───────────────                                     ────────────────

1. Event occurs for user
         │
         ▼
2. POST /agentsessions ──────────────────────────►  Create agent session
   (externalUserId, agentUid)                       Returns: uid, agentSessionUid
         │
         ▼
3. POST /threads ─────────────────────────────────► Create thread, invoke agent
   (agentSessionUid, externalUserId, message)       Agent processes message
                                                    Returns: threadUid, humanUid
         │
         ▼
4. Store threadUid + agentSessionUid
         │
         ▼
5. Notify user (email, push, in-app)
         .
         .
         .
User arrives
         │
         ▼
6. POST /sdkusers/auth ──────────────────────────►  Authenticate user
   (externalId, name)                               Returns: authToken
         │
         ▼
7. Render page with embedded SDK
   <mindset-agent
     agent-uid="{agentSessionUid}"
     thread-uid="{threadUid}">
         │
         ▼
8. User sees the agent's response to the
   original event-specific message
```

***

## Step-by-Step

<Steps>
  <Step title="Event Occurs">
    Your system detects an event that warrants a proactive agent conversation. You know which user it relates to and what information the agent needs.

    For this example, an order has shipped and you want an agent to proactively brief the user on their delivery details.
  </Step>

  <Step title="Create an Agent Session">
    Create an agent session that links the agent to the specific user. This session scopes the conversation and can optionally attach specific contexts or MCP servers.

    ```http theme={null}
    POST https://{api-host}/api/v1/appuid/{appUid}/agentsessions
    x-api-key: {apiKey}
    Content-Type: application/json

    {
      "agentUid": "your-agent-uid",
      "externalUserId": "user-12345",
      "mcpserverUids": ["order-tracking-tools", "customer-tools"],
      "contextUids": ["product-training"]
    }
    ```

    **Response (201):**

    ```json theme={null}
    {
      "uid": "a1b2c3d4e5",
      "agentSessionUid": "your-agent-uid::a1b2c3d4e5",
      "humanUid": "firebase-uid-xyz",
      "agentUid": "your-agent-uid",
      "externalUserId": "user-12345",
      "contextUids": ["product-training"],
      "mcpserverUids": ["order-tracking-tools", "customer-tools"],
      "createdAt": "2026-02-27T10:30:00.000Z"
    }
    ```

    Store the `agentSessionUid` value — you'll need it in steps 3 and 7.

    **Optional fields:**

    | Field  | Purpose                                                   |
    | ------ | --------------------------------------------------------- |
    | `tags` | Label the session (e.g., `["order-shipped", "priority"]`) |
  </Step>

  <Step title="Create a Thread via the Threads API">
    Use the Threads API to start a new conversation thread. The agent processes your message and generates its first response.

    ```http theme={null}
    POST https://{api-host}/api/v1/appuid/{appUid}/threads
    x-api-key: {apiKey}
    Content-Type: application/json

    {
      "agentUid": "your-agent-uid::a1b2c3d4e5",
      "externalUserId": "user-12345",
      "messageType": "system",
      "message": "Order ORD-98765 for customer user-12345 has shipped via FedEx, tracking number 1Z999AA10123456784, estimated delivery March 2nd. Please brief the user on their delivery status and offer to help with any questions about their order."
    }
    ```

    <Note>
      Pass the full `agentSessionUid` (the composite `agentUid::sessionUid` string) as the `agentUid` field. This links the thread to the session you created in step 2.
    </Note>

    <Note>
      Use the same user identifier type (`externalUserId` in this example) that you used when creating the agent session.
    </Note>

    **Response (201):**

    ```json theme={null}
    {
      "threadUid": "t9x8y7z6w5",
      "humanUid": "firebase-uid-xyz",
      "agentUid": "your-agent-uid"
    }
    ```

    Store the `threadUid` — this is the conversation the user will be directed to.

    The API waits for the agent to process your message before responding. The agent's first response is now stored in the thread and ready for the user to see.

    #### Message Types

    By default, your message appears in the conversation as a visible user message. To have the agent act on context without the user seeing your original prompt, use `messageType: "system"`:

    ```json theme={null}
    {
      "agentUid": "your-agent-uid::a1b2c3d4e5",
      "externalUserId": "user-12345",
      "message": "The user's name is Jane. Order ORD-98765 has shipped. Tracking: 1Z999AA10123456784. Delivery: March 2nd. Brief the user naturally about their delivery.",
      "messageType": "system"
    }
    ```

    With `"system"`, the user only sees the agent's response — not your original message. Because your backend knows who the user is and what triggered the event, you can include personal details (name, order number, account status) in the system message. The agent can then greet the user by name and reference specifics naturally, without needing agent memory or prior conversation history.
  </Step>

  <Step title="Store the Identifiers">
    Your system now has everything it needs to deliver this conversation to the user later.

    | Value             | From            | Used In                          |
    | ----------------- | --------------- | -------------------------------- |
    | `agentSessionUid` | Step 2 response | Embedding the SDK (step 7)       |
    | `threadUid`       | Step 3 response | Embedding the SDK (step 7)       |
    | `externalUserId`  | Your system     | Authenticating the user (step 6) |

    Store these against the user and event in your system.
  </Step>

  <Step title="Notify the User">
    Notify the user through whatever channel suits your application — email, push notification, in-app alert, SMS. Include a link that takes them to the page where the agent is embedded.

    This step is entirely within your system. Mindset doesn't send the notification.

    See [Building Deep Links](#building-deep-links) below for how to construct the link.
  </Step>

  <Step title="Authenticate the User">
    When the user arrives, authenticate them with Mindset to get a Firebase auth token. Use the same identifier you used in steps 2 and 3.

    ```http theme={null}
    POST https://{api-host}/api/v1/appuid/{appUid}/sdkusers/auth
    x-api-key: {apiKey}
    Content-Type: application/json

    {
      "externalId": "user-12345"
    }
    ```

    <Warning>
      The `sdkusers/auth` endpoint uses `externalId` (not `externalUserId`). This refers to the same user — the field name just differs between APIs.
    </Warning>

    **Response (201):**

    ```json theme={null}
    {
      "authToken": "eyJhbGciOiJSUzI1NiIs..."
    }
    ```
  </Step>

  <Step title="Embed the SDK with the Thread">
    Render the page with the Mindset AI SDK, passing the `agentSessionUid` and `threadUid` so the widget loads the existing conversation rather than starting a new one.

    ```html theme={null}
    <script src="https://{{MINDSET_SDK_LOCATION}}/mindset-sdk3.umd.js"></script>

    <mindset-agent
      agent-uid="{agentSessionUid}"
      thread-uid="{threadUid}">
    </mindset-agent>

    <script>
      window.MindsetAgent.initialize({
        appUid: '{appUid}',
        fetchAuthentication: async () => {
          // Return the authToken obtained in step 6
          return '{authToken}';
        }
      });
    </script>
    ```

    Replace the placeholders:

    * `{appUid}` — your Mindset app UID
    * `{agentSessionUid}` — the composite string from step 2 (e.g., `your-agent-uid::a1b2c3d4e5`)
    * `{threadUid}` — the thread UID from step 3
    * `{authToken}` — the token from step 6
  </Step>

  <Step title="User Sees the Conversation">
    The SDK loads the existing thread and displays the agent's response to the event-specific message you sent in step 3. The user can continue the conversation naturally from there.

    * If `messageType` was `"user"` (the default), the user sees both their message and the agent's reply.
    * If `messageType` was `"system"`, the user sees only the agent's reply — the conversation appears to have been initiated by the agent.
  </Step>
</Steps>

## User Identifier Consistency

You must use the **same user identifier type** across all three API calls. The identifier resolves to the same internal user, so mixing types creates separate users.

| API Call                | Field Name       | Example Value |
| ----------------------- | ---------------- | ------------- |
| Agent Sessions (step 2) | `externalUserId` | `user-12345`  |
| Threads (step 3)        | `externalUserId` | `user-12345`  |
| SDK Users Auth (step 6) | `externalId`     | `user-12345`  |

<Note>
  The `sdkusers/auth` endpoint uses `externalId` rather than `externalUserId`. Despite the different field name, these refer to the same identifier.
</Note>

### Using Email-Based Identifiers

If your users are identified by email rather than an external ID:

| API Call                | Field Name     | Example Value      |
| ----------------------- | -------------- | ------------------ |
| Agent Sessions (step 2) | `sdkUserEmail` | `jane@example.com` |
| Threads (step 3)        | `sdkUserEmail` | `jane@example.com` |
| SDK Users Auth (step 6) | `sdkUserEmail` | `jane@example.com` |

## Error Handling

### Thread Creation Errors

| Status | Meaning                                        | Action                                             |
| ------ | ---------------------------------------------- | -------------------------------------------------- |
| 404    | Agent not found or not version 3               | Check agent UID and that the agent is active       |
| 422    | User identifier invalid or agent denied access | Check identifier format; review agent access rules |
| 502    | Agent processing failed                        | Retry; if persistent, check agent configuration    |
| 503    | Agent service unavailable                      | Retry after a short delay                          |
| 504    | Agent timed out (120s)                         | The message may be too complex — simplify or retry |

### SDK Thread Loading

If the `threadUid` is invalid or the thread can't be loaded, the SDK displays an error message and offers the user a "Start New Thread" option to begin a fresh conversation.

## Complete Backend Example (Node.js)

```javascript theme={null}
const API_HOST = 'https://{api-host}';
const APP_UID = 'your-app-uid';
const API_KEY = 'your-base64-api-key';
const AGENT_UID = 'your-agent-uid';

async function createProactiveThread(externalUserId, eventMessage) {
  // Step 2: Create agent session
  const sessionRes = await fetch(
    `${API_HOST}/api/v1/appuid/${APP_UID}/agentsessions`,
    {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        agentUid: AGENT_UID,
        externalUserId,
        mcpserverUids: ['order-tracking-tools', 'customer-tools'],
        contextUids: ['product-training'],
      }),
    }
  );
  const session = await sessionRes.json();

  // Step 3: Create thread
  const threadRes = await fetch(
    `${API_HOST}/api/v1/appuid/${APP_UID}/threads`,
    {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        agentUid: session.agentSessionUid,
        externalUserId,
        message: eventMessage,
        messageType: 'system',
      }),
    }
  );
  const thread = await threadRes.json();

  return {
    agentSessionUid: session.agentSessionUid,
    threadUid: thread.threadUid,
  };
}

async function getAuthToken(externalUserId) {
  // Step 6: Authenticate user
  const authRes = await fetch(
    `${API_HOST}/api/v1/appuid/${APP_UID}/sdkusers/auth`,
    {
      method: 'POST',
      headers: {
        'x-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        externalId: externalUserId,
      }),
    }
  );
  const auth = await authRes.json();

  return auth.authToken;
}
```

## Building Deep Links

The flow above creates several identifiers that together point to a specific conversation for a specific user. To notify the user in step 5, you need to build a link that routes them to the right place in your application.

### Why Deep Links Are Your Responsibility

In the embedded SDK model, the Mindset agent lives inside your application. You control how users log in, what pages exist, and how the `<mindset-agent>` element is rendered. Mindset can't generate a working deep link for you because we don't know your application's URL structure or routing. What we provide is the set of identifiers your application needs to render the right conversation — you build the link.

### What Your Deep Link Needs to Encode

At minimum, your link needs to carry enough information for your application to:

1. Identify the user (so your app can authenticate them and call `/sdkusers/auth`)
2. Retrieve the stored `agentSessionUid` and `threadUid` (so your app can render `<mindset-agent>` with the correct attributes)

How you encode this is up to you. Three common approaches:

**Option A: Encode the Mindset identifiers directly in the URL**

```
https://app.example.com/agent?sid=your-agent-uid::a1b2c3d4e5&tid=t9x8y7z6w5
```

Your page reads `sid` and `tid` from the query string and passes them to the SDK element. Authentication is handled by your existing user session.

**Option B: Use your own event or notification ID**

```
https://app.example.com/notifications/evt-77890
```

Your application looks up event `evt-77890` in your database, retrieves the associated `agentSessionUid` and `threadUid` stored in step 4, authenticates the user, and renders the agent.

**Option C: Route within an existing page**

```
https://app.example.com/dashboard#agent/t9x8y7z6w5
```

Your SPA catches the hash route and opens the agent panel with the correct thread.

### Example: Email Notification with Deep Link

```
Subject: Update on your order ORD-98765

Hi Jane,

Your order has shipped! Our AI assistant has prepared a delivery
briefing for you.

[View delivery details]
→ https://app.example.com/agent?sid=your-agent-uid::a1b2c3d4e5&tid=t9x8y7z6w5
```

When Jane clicks the link, your application:

1. Recognises Jane from her existing session (or prompts login)
2. Reads `sid` and `tid` from the query string
3. Calls `/sdkusers/auth` with Jane's `externalId` to get an auth token
4. Renders `<mindset-agent agent-uid="{sid}" thread-uid="{tid}">` with the token

### Universal Client: A Simpler Path

When Mindset provides the entire end-user application — as with Universal Client — the deep linking story is simpler:

* **User identifier**: `realEmailAddress` — users log into the UC app directly with their real email, so there's no need for `/sdkusers/auth` or external ID mapping
* **Agent session**: Not required — the Threads API can be called with a plain `agentUid` rather than a composite `agentSessionUid`, because the UC app manages agent access directly
* **Deep link**: A URL pointing to the specific app, agent, and thread within the UC app

In this model, the only API call your external system needs to make is the Threads API itself.

<Note>
  Deep link URL patterns for Universal Client are under active development and will be documented separately.
</Note>

***
