BuildersPut it in your productLet the agent act on your page

Updated 27 Oct 2026View as Markdown

Let the agent act on your page

Lets an agent call functions in your page, tells it what the user is looking at, and fills in values the model must never choose.

Let the billing-help agent open an invoice in our app, and tell it which invoice the user is looking at. Check the user may see the invoice before opening it.

The agent's turn loop runs in the page, so it can call JavaScript you define there, with no round trip to Mindset. Three commands connect your app to the agent, on both the mindset-agent element and the UI-less client:

CommandWhat it does
setPageTools(tools)Functions in your page the agent may call
setSituationalAwareness(entries)Facts about what the user is looking at, as a { key: value } map of JSON values, added to the agent's context on every turn
setPassthroughParams(params)Values a tool needs that the model must never see

Each replaces its whole set, so pass the full picture each time. Passing a shorter set is how you remove an entry. Each is read fresh on every turn. On the element, configure() also takes them as pageTools, situationalAwareness and passthroughParams.

Page tools#

html
<script src="https://eu.mindset.ai/sdk/mindset-agent.js"></script>

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

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

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

  agent.setPageTools([
    {
      name: "open_invoice",
      description: "Open one of the signed-in user's invoices in the app.",
      jsonSchema: {
        type: "object",
        properties: { invoiceId: { type: "string" } },
        required: ["invoiceId"],
      },
      runningDescription: "Opening the invoice",
      completedDescription: "Opened the invoice",
      execute: async (args) => {
        const id = typeof args.invoiceId === "string" ? args.invoiceId : "";
        if (!/^inv_[a-z0-9]+$/.test(id)) return "That is not a valid invoice ID.";
        const r = await fetch(`/api/invoices/${id}`); // your backend checks this user may see it
        if (!r.ok) throw new Error("That invoice can't be opened.");
        window.location.hash = `#/invoices/${id}`;
        return { opened: id };
      },
    },
  ]);
</script>

On the UI-less client, call chat.setPageTools([...]) with the same array.

FieldWhat it does
name, description, jsonSchemaWhat the model reads to decide when to call the tool and with what arguments
execute(args)Runs in your page with the arguments the model chose. May be async
runningDescription, completedDescriptionOptional. What the element's activity row reads while the tool runs and when it's done. A string, or one per language, such as { en: "Saving", fr: "Enregistrement" }. Never sent to the model

What execute returns goes back to the agent as the tool's result. A string goes as it is, undefined or null reads as {"success":true}, and anything else as its JSON. If execute throws, the agent is told the tool failed, with your error's message (up to 500 characters) and never its stack.

Tools written for Mindset 3, as { name, description, parameters, handler }, work unchanged.

Page tool safety#

The model decides whether to call your tool and with what arguments, and anything in its context can influence it, including knowledge sources and other tools' output.

  • jsonSchema is mostly guidance. The SDK checks one thing before execute runs: a call missing an argument your schema lists as required is refused, and the model is told why. A value supplied through pass-through counts. Types, formats and allowed values aren't checked, so validate them yourself.
  • Mindset can't re-authorize a page tool. It runs in your page, so nothing checks that this user may take that action when the handler runs.

The org API key never reaches the browser, and tools that run on Mindset's side still authorize there.

Situational awareness#

javascript
chat.setSituationalAwareness({
  page: "Invoice detail",
  invoiceId: "inv_4471",
  invoiceStatus: "overdue",
});

Call it whenever the view changes. The agent treats it as context only, and it isn't a security boundary. What the agent may reach is still decided by Mindset.

Pass-through values#

javascript
chat.setPassthroughParams({
  "lookup_account.tenantId": "acme-eu",
  region: "eu-west-1",
});

A "tool_name.param" key scopes a value to one tool. A plain param key goes to every page tool, and to each tool that runs on Mindset's side and declares that parameter. When both name the same parameter, the tool_name.param key wins. Mindset removes the parameter from the schema the model sees, and your value is added to the tool's arguments when the tool is called. The model can't see or choose it.

The turn loop runs in the page, so pass-through values sit in the browser, where the user and every script on the page can read them. They also reach the model if a tool puts them in its result. Use pass-through to stop the model choosing a value.

See it working#

Live demoStore assistant · Northwind OutdoorThe agent filters an outdoor store’s product grid, points at its pick and fills your basket. Live demoAdd a new employee · PlinthA copilot fills a long HR form field by field, flags a salary outside its band and leaves Save to you. Live demoWhat’s wrong with this one? · RelayAsk about a delayed shipment: an agent with no tools answers from what the page tells it.