Live CortexUI Surface
This block renders live CortexUI contract metadata in the docs DOM so AI View can inspect real machine-readable elements instead of only code examples.
| Item | State |
|---|---|
| Search docs | Ready |
| Inspect metadata | Visible in AI View |
Roles Reference
Roles define the semantic type of a UI element within the AI contract. Where data-ai-id identifies which element something is, data-ai-role identifies what kind of thing it is. AI agents use roles to understand what they can do with an element — can they click it? Fill it? Read from it? Navigate through it?
Quick Reference
| Role | Element Purpose | Typical HTML Elements |
|---|---|---|
| action | Triggerable intent — button, link, menu item | <button>, <a>, <[role="button"]> |
| field | Input that accepts user data | <input>, <select>, <textarea> |
| form | Container that groups fields and an action | <form> |
| table | Tabular data display | <table>, data grid containers |
| modal | Overlay that requires attention | <dialog>, modal wrapper <div> |
| nav-item | Navigation destination | <a>, <button> inside nav |
| status | Read-only state indicator | <span>, <p>, badge elements |
| screen | Root identity of the current view | Outermost page container |
| section | Major logical region of a screen | <section>, <div> groupings |
data-ai-role is the single most important attribute in the contract. Without it, no other attribute is interpretable. Every annotated element must have a role.
role="action"
What It Means
An action is an element whose primary purpose is to trigger an operation. Clicking or activating it causes something to happen — a form submits, data saves, a record deletes, a modal opens.
Actions are the verbs of the UI. They carry data-ai-action (the intent name) and data-ai-state (the current condition of that intent).
Which HTML Elements
Use on <button> elements as the default. Can also be used on <a> tags that trigger operations rather than navigating, or on custom elements that have proper keyboard event handling.
<!-- Standard button action -->
<button
data-ai-role="action"
data-ai-id="save-profile"
data-ai-action="save-profile"
data-ai-state="idle"
>
Save Profile
</button>
<!-- Anchor used as action (triggers operation, not navigation) -->
<a
data-ai-role="action"
data-ai-id="export-csv"
data-ai-action="export-csv"
data-ai-state="idle"
href="#"
onClick={handleExport}
>
Export as CSV
</a>
<!-- Destructive action -->
<button
data-ai-role="action"
data-ai-id="delete-account"
data-ai-action="delete-account"
data-ai-state="idle"
>
Delete Account
</button>
Common Mistake
Placing role="action" on a <div> without keyboard support. AI agents may attempt to activate actions programmatically. A <div> without tabIndex and a keydown handler will not respond to keyboard-driven activation and will fail accessibility standards simultaneously.
<!-- Wrong: div with no keyboard support -->
<div data-ai-role="action" data-ai-action="save-profile" onClick={save}>
Save
</div>
<!-- Right: button handles keyboard natively -->
<button data-ai-role="action" data-ai-action="save-profile" onClick={save}>
Save
</button>
role="field"
What It Means
A field is an element that accepts input from the user. It represents a single named value within a form. Fields carry data-ai-field-type (what kind of data it holds) and data-ai-required (whether it must be filled).
Which HTML Elements
<input>, <select>, <textarea>. Do not use on <label> elements — labels describe fields, they are not fields.
<input
data-ai-role="field"
data-ai-id="email-field"
data-ai-field-type="email"
data-ai-required="true"
type="email"
name="email"
placeholder="you@example.com"
/>
<select
data-ai-role="field"
data-ai-id="role-select"
data-ai-field-type="select"
data-ai-required="false"
name="role"
>
<option value="admin">Admin</option>
<option value="viewer">Viewer</option>
</select>
<textarea
data-ai-role="field"
data-ai-id="notes-field"
data-ai-field-type="textarea"
data-ai-required="false"
name="notes"
></textarea>
Common Mistake
Using role="field" on a <label>. Labels are not fields — they are descriptions of fields. The AI contract reads fields as elements the agent can write values into. Writing into a label element has no effect.
<!-- Wrong -->
<label data-ai-role="field" data-ai-id="name-label">Name</label>
<!-- Right -->
<label htmlFor="name-input">Name</label>
<input data-ai-role="field" data-ai-id="name-field" data-ai-field-type="text" />
role="form"
What It Means
A form is a container that groups related fields and at least one action (submit). It represents a cohesive unit of data entry. The AI contract can retrieve a form's full field schema via getFormSchema(formId).
Which HTML Elements
The native <form> element is strongly preferred. Custom form-like containers can use a <div> with role="form" in ARIA terms and data-ai-role="form" in the AI contract.
<form
data-ai-role="form"
data-ai-id="create-user-form"
onSubmit={handleSubmit}
>
<input
data-ai-role="field"
data-ai-id="username-field"
data-ai-field-type="text"
data-ai-required="true"
name="username"
/>
<input
data-ai-role="field"
data-ai-id="email-field"
data-ai-field-type="email"
data-ai-required="true"
name="email"
/>
<button
data-ai-role="action"
data-ai-id="create-user-submit"
data-ai-action="create-user"
data-ai-state="idle"
type="submit"
>
Create User
</button>
</form>
Common Mistake
Giving forms generic IDs like form-1 or main-form. Form IDs must be stable and descriptive because agents reference them by ID when calling getFormSchema.
role="table"
What It Means
A table is a container that displays structured, tabular data — rows and columns of records. Tables are read-heavy and often include actions per row (edit, delete, view).
Which HTML Elements
The native <table> element, or a custom data grid wrapper <div> when using a virtualized grid library.
<table
data-ai-role="table"
data-ai-id="users-table"
data-ai-entity="user"
>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr data-ai-entity="user" data-ai-entity-id="user-001">
<td>Alice Smith</td>
<td>alice@example.com</td>
<td><span data-ai-role="status">Active</span></td>
<td>
<button
data-ai-role="action"
data-ai-id="edit-user-user-001"
data-ai-action="edit-user"
data-ai-state="idle"
>Edit</button>
</td>
</tr>
</tbody>
</table>
role="modal"
What It Means
A modal is an overlay element that takes focus and requires user interaction before returning to the underlying page. Modals typically contain forms or confirmation dialogs.
Which HTML Elements
The native <dialog> element, or a <div> positioned as an overlay with appropriate ARIA attributes.
<dialog
data-ai-role="modal"
data-ai-id="confirm-delete-modal"
data-ai-state="expanded"
open
>
<p>Are you sure you want to delete this account?</p>
<button
data-ai-role="action"
data-ai-id="confirm-delete"
data-ai-action="delete-account"
data-ai-state="idle"
>
Confirm Delete
</button>
<button
data-ai-role="action"
data-ai-id="cancel-delete"
data-ai-action="cancel-delete"
data-ai-state="idle"
>
Cancel
</button>
</dialog>
role="nav-item"
What It Means
A nav-item is a navigation link that moves the user to a different screen or section. Unlike role="action" which triggers operations, role="nav-item" declares navigational intent.
Which HTML Elements
<a> elements inside navigation containers, or <button> elements that trigger client-side routing.
<nav>
<a
data-ai-role="nav-item"
data-ai-id="nav-dashboard"
href="/dashboard"
>
Dashboard
</a>
<a
data-ai-role="nav-item"
data-ai-id="nav-users"
href="/users"
>
Users
</a>
<a
data-ai-role="nav-item"
data-ai-id="nav-settings"
href="/settings"
>
Settings
</a>
</nav>
role="status"
What It Means
A status element displays a read-only state value — a badge showing "Active", a label showing "Pending", a chip showing "Overdue". It is informational, not interactive.
Which HTML Elements
<span>, <p>, badge <div> elements, or any inline element used to display a state.
<span
data-ai-role="status"
data-ai-id="order-status"
data-ai-state="success"
>
Delivered
</span>
<span
data-ai-role="status"
data-ai-id="payment-status"
data-ai-state="error"
>
Payment Failed
</span>
Combine data-ai-state with role="status" to give the AI agent a machine-readable state value alongside the human-readable label text. An agent reading a status badge with data-ai-state="error" doesn't need to parse the text "Payment Failed" — it reads the state directly.
role="screen" and role="section"
What They Mean
These roles mark structural containers. screen marks the root of the current view. section marks a major logical region.
In practice, data-ai-screen and data-ai-section on their container elements implicitly carry these roles — you typically don't need to set data-ai-role="screen" separately if data-ai-screen is already present.
<div data-ai-screen="user-profile">
<section data-ai-section="profile-header">
<h1>Alice Smith</h1>
<span data-ai-role="status" data-ai-state="success">Active</span>
</section>
<section data-ai-section="profile-form">
<form data-ai-role="form" data-ai-id="edit-profile-form">
<!-- fields and actions -->
</form>
</section>
</div>