m4Mindset docs

Docs / SDK / Reference / The mindset-agent element

View as Markdown

The mindset-agent element

Reference for the drop-in chat element. Attributes, configure() fields, methods, events, error codes and theming.

This is the full reference for <mindset-agent>, the drop-in half of the SDK. Use it to configure the element, resume conversations, listen for its events and theme it. For a first working setup, start with Put an agent on your page.

Load it

html
<script src="https://YOUR-MINDSET-HOST/sdk/mindset-agent.js"></script>

<mindset-agent agent="billing-help"></mindset-agent>

<script>
  document.querySelector("mindset-agent").configure({
    getSession: async () => {
      const r = await fetch("/api/session");
      if (!r.ok) throw new Error("Could not start a session");
      return r.json();
    },
  });
</script>

The script registers the mindset-agent tag itself. It also sets window.MindsetAgentSDK, which reports version and commit for the build on the page. Quote those when you contact support.

configure()

configure() starts the element. Until you call it, the element draws nothing and send() reports an error.

FieldTypeWhat it does
getSessionfunctionRequired. Returns the JSON body your backend got from the session create call, or a promise of it. The SDK calls it straight away and again whenever it needs a new session
conversationIdstringResume this conversation. Leave it out for a fresh one. See resume a conversation
conversationListbooleanShow the user a list of their earlier conversations with this agent. Off by default
pageToolsarrayFunctions in your page the agent may call. Same as setPageTools()
situationalAwarenessobjectFacts about what the user is looking at. Same as setSituationalAwareness()
passthroughParamsobjectValues a tool needs that the model must never see. Same as setPassthroughParams()
agentstringOverrides the agent attribute. The attribute is the usual way

The session carries your org, environment and Mindset host, so there is nothing else to configure.

Calling configure() again stops the current conversation and starts a new one from the new config. The new config replaces the old one completely. Anything you set with setPageTools(), setSituationalAwareness() or setPassthroughParams() is dropped unless the new config includes it.

Moving the element in the DOM is not a reconfigure. The conversation survives it.

Attributes and properties

Each attribute mirrors a property, in both directions.

PropertyAttributeWhat it is
agentagentWhich agent to run: its handle or its ID, both on the agent's Embed tab
conversationIdconversation-idWhich conversation to resume
conversationListconversation-listWhether to show the conversation list. A presence attribute: any value turns it on, and removing the attribute turns it off

HTML lowercases attribute names, which is why the attribute is conversation-id and the property is conversationId.

Changing agent after configure() stops the conversation and raises stale-configuration. Call configure() again to start one for the new agent. Toggling conversation-list only redraws. The conversation carries on.

Methods

MethodWhat it does
configure(config)Set the element up, as above
send(text)Send a turn as if the user typed it. Before configure(), it raises not-configured
stop()Stop the turn in progress. Safe when nothing is running
setPageTools(tools)Replace the set of page tools
setSituationalAwareness(entries)Replace the situational-awareness entries
setPassthroughParams(params)Replace the pass-through values

The three set methods raise not-configured if called before configure(). Each method behaves like the UI-less command of the same name, which describes page tools, situational awareness and pass-through values in full.

The element also registers one page tool of its own. You can't remove or replace it. If one of your tools uses its name, yours is skipped and the console warns you.

Page tool handlers run with arguments the model chose. Validate them, and put nothing behind a page tool that you wouldn't let a hostile caller do. See page tool safety.

Resume a conversation

By default every mount starts a fresh conversation. To let a user pick up where they left off, store the conversation ID for that user and hand it back next time.

First visit. Leave conversation-id off. After the user's first completed turn, the element writes the ID onto its own conversation-id attribute and fires mindset:conversation. Store the ID against that user, in your own database.

Next visit. Pass the stored ID as conversationId in configure(), or set the conversation-id attribute before you call configure(). The agent continues with its earlier history, and the element shows it.

html
<script>
  const agent = document.querySelector("mindset-agent");

  agent.addEventListener("mindset:conversation", (e) => {
    fetch("/api/conversation-id", {
      method: "PUT",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ conversationId: e.detail.conversationId }),
    });
  });

  fetch("/api/conversation-id")
    .then((r) => r.json())
    .then(({ conversationId }) => {
      agent.configure({
        getSession: async () => {
          const r = await fetch("/api/session");
          if (!r.ok) throw new Error("Could not start a session");
          return r.json();
        },
        ...(conversationId ? { conversationId } : {}),
      });
    });
</script>

Here /api/conversation-id is an endpoint in your own backend that saves and returns the ID for the signed-in user.

Rules to know

  • Store what the event gives you, every time. If an ID you supplied can't be used, the element starts a fresh conversation and fires mindset:conversation again with the new ID, before any turn. Saving whatever arrived last keeps you correct with no cleanup code.
  • Prefer the event to the attribute. If your framework resets the DOM to a template, it may strip the attribute, and the element doesn't write it back.
  • Clearing the attribute does nothing. An unrelated DOM update can't cost the user their conversation.
  • Writing the same ID back does nothing. A re-render that echoes it is safe.
  • Writing a different ID stops the conversation and raises stale-configuration. To open that conversation, call configure() again. To start fresh instead, remove the attribute first, then call configure().
  • An ID is per user. Resolve it per request from who is signed in. Never put one in shared or cached HTML, or every visitor gets the same conversation.

The ID is a correlation key, not a credential. It grants nothing without a session for the same user, and an ID that belongs to another user is refused.

The conversation list

Set conversationList: true in configure() (or add the conversation-list attribute) and the element shows a Conversations button in its top corner. It opens a list of this user's earlier conversations with this agent, newest first. Picking one switches the element to it.

The list shows only this user's conversations, and only with this agent. It controls what is drawn, not what the user may read: the session decides that.

When the user switches, mindset:conversation fires with the new ID. Store it as usual.

Events

DOM CustomEvents. They bubble and cross the shadow boundary, so a listener on any ancestor sees them.

Eventdetail
mindset:runtime-eventOne runtime event, exactly as the events reference lists. Fires for every turn, whether typed in the element or sent with send()
mindset:error{ code, message, cause? }. A configuration or transport problem. See error codes below
mindset:conversation{ type: "conversation_id", conversationId, replacedConversationId?, replacedBecause? }. Which conversation the element is having

mindset:conversation fires when the conversation ID first becomes known (at configure when you supplied one, otherwise after the first completed turn). It fires again only when the element moves to another conversation:

replacedBecauseMeaningWhat to do
"discarded"The ID you supplied couldn't be used, so a fresh conversation startedStore the new ID. The old one is dead
"switched"The user picked another conversation from the listStore the new ID. The old one still works

replacedConversationId names the ID left behind. The event carries nothing else, on purpose, because every script on your page can read it.

The element doesn't re-emit the SDK's history_settled event. It contains the user's conversation, and the element draws it for you.

Error codes

mindset:error always carries a code. Branch on the code and treat an unknown one as a general failure. Every error is also logged to the console.

codeRaised when
missing-agentconfigure() ran with no agent, from either the attribute or the config
invalid-authconfigure() got no getSession, or getSession returned something the SDK can't use, such as a Response that wasn't parsed with .json(), or a session that has already expired. Raised as soon as getSession answers. The message says what to return
not-configuredsend() or a set method was called with no live conversation: before configure(), or after the element was removed from the page
stale-configurationAn attribute changed after configure(), so the conversation no longer matches the element. Call configure() again
turn-failedA turn failed: transport, credential or the run itself. An expired session shows up here and nowhere else

stop() is not an error. A stopped turn arrives as a run_error runtime event with aborted: true.

Theming

Theme the element with CSS custom properties set on the element itself. There is no ::part() API.

The element ships its own default colors, so it looks right on a page with no theme. Add class="dark" to the tag for the dark set.

Override any channel from your own stylesheet. A rule on the element beats its built-in defaults.

css
mindset-agent {
  --ch-accent: 124 58 237;
  --ch-page: 255 255 255;
}

Values are three space-separated numbers for red, green and blue, from 0 to 255. Hex and rgb() don't work.

The current set has 77 channels. It can grow as the interface changes, so treat this as the current list, not a fixed contract.

text
--ch-page                       --ch-panel                      --ch-card
--ch-surface                    --ch-input                      --ch-card-hover
--ch-selected                   --ch-placeholder                --ch-surface-sunken
--ch-surface-raised             --ch-overlay                    --ch-text-heading
--ch-text-primary               --ch-text-secondary             --ch-text-muted
--ch-logo                       --ch-edge                       --ch-edge-subtle
--ch-edge-strong                --ch-btn-primary                --ch-btn-primary-hover
--ch-btn-secondary              --ch-btn-secondary-hover        --ch-accent
--ch-accent-hover               --ch-on-accent                  --ch-agent
--ch-agent-hover                --ch-node-agent                 --ch-node-connection
--ch-node-tool                  --ch-node-knowledge             --ch-node-widget
--ch-node-function              --ch-chip                       --ch-chip-text
--ch-chip-border                --ch-status-warning-bg          --ch-status-warning-text
--ch-status-warning-border      --ch-status-success-bg          --ch-status-success-text
--ch-status-success-border      --ch-code                       --ch-status-info-bg
--ch-status-info-text           --ch-status-info-border         --ch-status-danger-bg
--ch-status-danger-text         --ch-status-danger-border       --ch-step-neutral
--ch-step-model                 --ch-step-call                  --ch-step-gate
--ch-on-step-gate               --ch-script-end                 --ch-script-hold
--ch-canvas                     --ch-raised                     --ch-canvas-dot
--ch-on-step                    --ch-status-neutral-bg          --ch-status-neutral-text
--ch-status-neutral-border      --ch-phase-specify-bg           --ch-phase-specify-text
--ch-phase-specify-border       --ch-phase-specify-container    --ch-phase-build-bg
--ch-phase-build-text           --ch-phase-build-border         --ch-phase-build-container
--ch-phase-verify-bg            --ch-phase-verify-text          --ch-phase-verify-border
--ch-phase-verify-container     --ch-phase-draft-container

Style isolation works both ways. The interface lives in a shadow root and its stylesheet is attached to that root, never to your document.

One SDK per page

The tag can be registered once per page. Loading this script twice is harmless. If another script, such as an older Mindset embed, already registered mindset-agent, the element can't register, and the console names the tag and this build's version. Remove the other embed.