Let an agent read your components and call their actions.

createAgent connects an agent to the ui-sdk components in your app. It can read their state, find the actions they support, and call those actions through the component's API.

In this example, an agent reads a text field labeled "Project name" and changes it from "Apollo" to "Atlas".

For a complete app you can run, follow the Guide. It takes you from a Vite project to using a Select through the console and ChatGPT.

Create the Bridge

Create the bridge once. These examples use React:

agent.ts
import { createAgent } from "@ui-sdk/react/agent"

const agent = createAgent()

export { agent }

The bridge finds the components already on the page when you create it, and registers new ones as they're created, so you can create it at startup or later, when an assistant opens.

Use the agent entry from the same package as your components:

FrameworkImport From
React@ui-sdk/react/agent
Vue@ui-sdk/vue/agent
Svelte@ui-sdk/svelte/agent
Solid@ui-sdk/solid/agent
Web Components@ui-sdk/web/agent

Add a Component

Render a ui-sdk input with an accessible name:

import { Input } from "@ui-sdk/react/input"
import "./agent"

function ProjectName() {
  return <Input aria-label="Project name" defaultValue="Apollo" />
}

export { ProjectName }

The name helps both people using a screen reader and agents identify the input. A Field label works too.

Read the Page

After the component renders, call snapshot:

import { agent } from "./agent"

const components = agent.snapshot()

For this page, it returns:

[
  {
    "ref": "c1",
    "component": "input",
    "label": "Project name",
    "value": "Apollo",
    "actions": ["setValue", "clear"]
  }
]

ref identifies this component. actions lists what the agent can ask it to do now.

The snapshot includes ui-sdk components. It can also include components that left the page, such as a field in a closed tab, marked with offPage: true. A page with more than 100 components lists the first 100 and ends with an entry that says how many more there are; use query to find the rest.

Change a Value

Use act to call one of the input's actions:

const result = await agent.act({
  steps: [{ ref: "Project name", action: "setValue", args: ["Atlas"] }],
})

The input now reads Atlas. Its onValueChange callback runs with details.source === "agent", so your app can respond to the change or cancel it. Permissions covers those checks.

You can use the label or the ref from the snapshot. A label matches whole words regardless of case and accents, so "project name" works too. If a label is ambiguous, the bridge returns an error with the matches. Use a specific ref to choose one.

result.steps reports what each step changed, and result.values contains the current field values. A callback can cancel a change, so check those values when you need to know what took effect.

Put several steps in one call to run them in order. If a step fails, result.ok is false and result.error tells you which step failed and why. Earlier steps stay applied.

Find List Items

For components with choices, such as a Select or Combobox, query with within lists the available values. For a Select labeled Region:

const [region] = await agent.query({ within: "Region", text: "Europe" })

region.items holds up to 50 matching choices, each with a value and label, and region.more says how many matched beyond that. Leave out text to list the first 50. Depending on how the component supplies its items, the bridge may briefly open it to read them.

query also finds components without listing the page. agent.query({ text: "Europe" }) returns the components whose label or row text has that word, and lists whose choices match, with those choices under them. kind keeps one kind, such as "select".

Connect the Tools

agentTools describes snapshot, act, and query with names, descriptions, and JSON Schemas:

import { agentTools } from "@ui-sdk/react/agent"

Use these definitions when setting up your agent's tools. Route each tool call to the matching method on agent and return its result to the model. Your model SDK determines how you register and handle those calls.

What the tools return comes from the page, so it can include text your users wrote, like a name in a table row. Their descriptions tell the model to treat it as data. Before an agent changes something that matters, have a person confirm it with Permissions.

For a browser that supports WebMCP, register the tools with the browser.

Your Own Components

A component built with definePrimitive joins the bridge too. Its agent key lists the API methods an agent can call, like agent: { actions: ["setValue"] }. Without one, methods named like changes, such as setValue or toggle, become its actions, and event handlers such as keydown stay internal.

The snapshot reads the primitive's controlled state keys. If none are declared, it reads open, value, and checked when present. Your Own Components shows how to add the key and what each part of it does.

Next Steps

  • Permissions: approve, refuse, or cancel an agent's changes.
  • Observe Changes: keep the agent up to date with what the person changed.
  • History and Undo: record changes, undo them, and preview suggestions.
  • WebMCP: make the tools available to a browser agent.
  • Reference: look up options, methods, and return values.