# Building with agents Choose a component. Supply typed arguments. Update a working interface. Describe your app in the [Playground](/docs/agents/playground) to generate a dropdown with Azure Luna. This guide covers integrating model output and composing layouts. ## One component Give your model the JSON Schema and allowed action names. Validate its completed output before applying it to the current component. ```tsx import { applyDropdownEdit, dropdownEditJsonSchema } from '@uthereal/ui/agent' // Provide dropdownEditJsonSchema for partial updates to your model. const result = applyDropdownEdit(currentConfig, modelOutput, ['save', 'rename']) if (result.success) setConfig(result.config) else sendErrorsToAgent(result.errors) ``` `dropdownJsonSchema` describes creation input: `items` is required and omitted settings receive defaults. Use `dropdownEditJsonSchema` for partial edits; omitted arguments keep their current values. An edit merges nested option objects, including theme tokens and motion settings. An `items` array replaces the previous array. Callback functions and application credentials are never part of model output. ## Compose components The optional composition catalog supports `Stack` and `DropdownMenu`. Stacks arrange children into rows and columns and can be nested to create larger layouts. Component and item IDs retain user selections. ```tsx 'use client' import { useReducer, useState } from 'react' import { createComposition, applyCompositionUpdate, } from '@uthereal/ui/composition' import { CompositionView, createStateStore, } from '@uthereal/ui/composition/react' const allowedActions = ['save'] const initialDocument = createComposition( { root: 'toolbar', elements: { toolbar: { type: 'Stack', props: { direction: 'row', gap: 'md' }, children: ['files'], }, files: { type: 'DropdownMenu', props: { label: 'File actions', items: [ { kind: 'action', id: 'save', label: 'Save', action: 'save' }, ], }, children: [], }, }, }, allowedActions, ) export function AgentToolbar() { const [store] = useState(() => createStateStore({})) const [feedback, setFeedback] = useState('Ready') const [document, dispatch] = useReducer( (current: typeof initialDocument, output: unknown) => { const result = applyCompositionUpdate(current, output, allowedActions) return result.success ? result.document : current }, initialDocument, ) return ( <> setFeedback(`Save requested by ${componentId}`), }} />

{feedback}

) } ``` This complete host example validates each update against the latest reducer state. The Playground also displays validation errors so output can be corrected. Keep a `createStateStore({})` instance in host state and pass it to `CompositionView` with the validated `spec` and registered action handlers. Checkbox selections are stored by component and item ID, so moving a menu does not reset them. ## Apply live changes An update includes the revision it was based on, plus a complete `spec` or JSON Patch operations: ```json { "baseRevision": 0, "patch": [ { "op": "replace", "path": "/elements/files/props/label", "value": "Project actions" }, { "op": "replace", "path": "/elements/files/props/closeOnSelect", "value": false } ] } ``` Use `applyCompositionUpdate(currentDocument, output, allowedActions)` against the latest document, for example inside a reducer. It validates the entire candidate before committing. Invalid arguments, missing children, cycles, unregistered actions, and stale revisions leave the working interface unchanged. ## Connect your model Export `compositionPrompt(allowedActions)` and `compositionUpdateJsonSchema` from `@uthereal/ui/composition`. Send these with the current document to your model. Pass its completed, parsed response to your reducer, and return validation errors for a retry when needed. Adapt the JSON Schema to your provider's supported structured-output subset if required. The library does not impose a model provider, transport, or agent framework. ## State and actions - The agent controls supported component arguments and layout structure. - Your application owns persistent selections and registered action handlers. - Open state and keyboard focus follow the mounted component's lifecycle. Moving a component to another parent can remount it. - Editing configuration does not execute an application action. ## Documentation for agents Use [llms.txt](/llms.txt) to discover pages, [llms-full.txt](/llms-full.txt) for the complete text, or **Copy page** on any documentation page. These are generated from the same MDX content as this website. ## Theme and motion are ordinary arguments The same `theme` and `motionOptions` objects work in React props, the composition catalog, and model-generated JSON. Agents can adjust presentation without providing CSS, callbacks, or executable code. ```tsx import { applyDropdownEdit } from '@uthereal/ui/agent' const result = applyDropdownEdit(current, { theme: { mode: 'dark', accent: 'blue', tokens: { popupRadius: 16 } }, motionOptions: { transition: { type: 'spring', stiffness: 340, damping: 38 }, enter: { offset: 8 }, }, allowedActions) if (result.success) setConfig(result.config) ``` For a single component, `applyDropdownEdit` merges supplied object fields; item arrays replace. Changing the transition `type` replaces that transition variant. Omitted fields stay unchanged, and explicit zero values are preserved. Send `{ theme: null }` or `{ motionOptions: null }` to remove that entire override group and return to recipe or motion preset values. `null` is an **edit operation**, not a component creation argument. Composition updates follow JSON Patch semantics: `add` or `replace` an object replaces that object. To preserve its siblings, update a specific existing token path. Create an absent `theme` object with `add` before addressing children; use `remove` to reset an individual token. Both update paths validate the full candidate atomically. See [Theming](/docs/foundations/theming) and [Motion](/docs/foundations/motion) for the complete vocabulary, ranges, and defaults. Reduced motion and immediate keyboard feedback remain enforced regardless of agent output. --- # Playground Describe what you’re building. Let AI configure the dropdown. Live AI playground: describe your application and Azure Luna generates validated DropdownMenu arguments. Try the resulting menu, request a change, or copy its configuration. Runs with server-side Azure credentials; actions display events only. The model chooses the menu items, labels, appearance, and behavior from the dropdown’s typed arguments. Try the result, then describe a change to refine it. Open **Generated configuration** to inspect or copy the exact arguments. This playground calls Azure Luna when you submit a prompt. Menu actions display the selected event; your application provides the actual export, save, or other operation. For schemas, validation, and composing components into layouts, see [Building with agents](/docs/agents). --- # Dropdown menu A focused list of actions, right where you need it. Interactive component preview: /docs/components/dropdown-menu ## Overview An independent dropdown with nested actions, checkboxes, keyboard navigation, and interruptible motion. Change its appearance and behavior through typed arguments, or let an agent supply those arguments at runtime. Use it for a short list of commands behind a button: file actions, row actions, or view settings. For choosing a form value, use a select instead. ## Installation Uthereal UI is currently a private source package. From a checkout of this repository, create a package archive: ```sh npm pack ``` Install that archive in your React application: ```sh npm install /path/to/uthereal-ui-0.1.0.tgz ``` Use React 19.2.3 or later and a bundler that handles TypeScript and CSS Modules, such as Next.js or Vite. The package installs Zag, Motion, and Zod as dependencies. Component styles are imported with the component. ## Usage ```tsx import { DropdownMenu } from '@uthereal/ui/dropdown-menu' export function FileActions() { return ( console.log(action, itemId)} /> ) } ``` The component emits named actions. Your application implements what those actions do. ## Examples Live examples: nested actions and persistent checkboxes. ### Nested actions A submenu is an item with its own `items` array. Item IDs must be unique across the whole menu. ```tsx const items = [ { kind: 'submenu', id: 'export', label: 'Export', items: [ { kind: 'action', id: 'pdf', label: 'PDF document', action: 'exportPdf' }, { kind: 'action', id: 'csv', label: 'CSV spreadsheet', action: 'exportCsv', }, ], }, ] satisfies import('@uthereal/ui').MenuItem[] ``` ### Controlled state Keep checkbox selections in your application when they must survive a remount. Omit these props to let the component manage its own state. ```tsx const [checked, setChecked] = useState({ preview: true }) ``` ## API reference These serializable arguments and defaults come directly from the component schema. | Argument | Type | Default | Description | | --- | --- | --- | --- | | label | string | "Actions" | Visible trigger text and accessible menu name. | | items (required) | MenuItem[] | — | Actions, checkboxes, separators, and nested submenus. Each item needs a stable, unique ID. | | placement | bottom-start \| bottom \| bottom-end \| top-start \| top \| top-end \| left-start \| left \| left-end \| right-start \| right \| right-end | "bottom-end" | Preferred popup position. Collision detection can adjust it. | | size | sm \| md \| lg | "md" | Trigger and menu item density. | | variant | solid \| outline \| ghost | "outline" | Trigger appearance. | | recipe | studio \| soft | "studio" | Visual treatment. Both recipes use the same interaction behavior. | | motion | none \| subtle \| expressive | "subtle" | Animation preset. System reduced-motion preferences take precedence. | | motionOptions | MotionOptions | — | Popup, highlight, label, and chevron overrides. Durations are milliseconds. See Motion. | | theme | DropdownTheme | — | Color mode, accent, and semantic tokens. See Theming for all keys and defaults. | | dir | ltr \| rtl | "ltr" | Reading direction and submenu navigation. | | closeOnSelect | boolean | true | Close after selecting an action. Checkbox items stay open unless overridden. | | loopFocus | boolean | false | Wrap keyboard navigation at the first and last items. | | disabled | boolean | false | Disable the trigger. | | defaultOpen | boolean | false | Initial open state. Later argument edits do not reset an existing instance. | ### React integration | Prop | Purpose | | ------------------------------------------------- | ---------------------------------------------------------------- | | `onAction(action, itemId)` | Handle named actions in your application. | | `open` / `onOpenChange(open)` | Control whether the menu is open. | | `checked` / `onCheckedChange(checked, changedId)` | Control checkbox selections by item ID. | | `tokens` | CSS variables applied to both trigger and portalled menus. | | `preset` | Application defaults, overridden by explicit instance arguments. | | `renderTrigger(props, state)` | Render a custom button; forward all supplied props. | | `triggerRef` | Access the native trigger button. | | `className` | Class applied to the component root. | | `portalContainer` | Place the popup inside a native dialog's top layer. | ## Keyboard & accessibility | Key | Interaction | | --------------------- | ---------------------------------------------------- | | `Enter`, `Space`, `↓` | Open the menu from its trigger. | | `↑` / `↓` | Move between enabled items. | | `Home` / `End` | Move to the first or last enabled item. | | `→` / `←` | Enter or leave a submenu; directions reverse in RTL. | | Type a label | Jump to a matching item. | | `Escape` | Close the current menu and restore focus. | | `Tab` | Dismiss the menu and continue through the page. | Zag supplies focus management, menu semantics, typeahead, and collision handling. Disabled items are skipped. Use clear labels for destructive actions; color alone does not communicate their effect. ## Motion `subtle` is the default. `expressive` adds a more pronounced spring; `none` removes animation. Pointer highlights animate between items, while keyboard highlights respond immediately. System reduced-motion preferences always take precedence. Override individual settings while retaining the preset's remaining defaults: ```tsx ``` All durations are milliseconds. See the [complete motion reference](/docs/foundations/motion), or tune it alongside your theme in the [Design Playground](/docs/foundations/playground). ## Theming Choose light or dark mode, an accent, and optional design tokens. The same typed settings apply to the trigger and every portalled submenu, and are available to agents. ```tsx ``` Recipe and size supply defaults for omitted tokens. Geometry uses pixels. Explore all 30 tokens in the [theming reference](/docs/foundations/theming), or open Customize in the preview above. Appearance edits preserve existing checkbox selections and open-menu state. --- # Motion Spring recipes, timing curves, travel, and accessible overrides. Choose a preset for a coherent starting point. Use `motionOptions` to tune individual transitions without replacing the component's interaction behavior. Motion remains a package dependency; the library owns the typed configuration and how it applies to the menu. Explore theme and motion together in the [Design Playground](/docs/foundations/playground). ## Presets | Preset | Popup | Pointer highlight | Label / chevron | | ------------ | ------------------------------------------------------------------ | ----------------- | --------------- | | `none` | Immediate | Immediate | Immediate | | `subtle` | 120 ms tween, scale 0.98, travel 4 px | 90 ms | 120 / 140 ms | | `expressive` | Spring: stiffness 420, damping 26, mass 1; scale 0.94, travel 4 px | 180 ms | 120 / 140 ms | `motion="none"` disables animation even when overrides are present. Preset changes keep explicit overrides; remove `motionOptions` to return to the new preset's defaults. ## Springs Shared spring recipes are exported as `motionTokens.spring`. Each is a valid `motionOptions.transition` value. | Recipe | Stiffness | Damping | Mass | Use | | -------- | --------- | ------- | ---- | --------------------------------------------- | | `snappy` | 520 | 38 | 1 | Small, responsive changes | | `smooth` | 340 | 38 | 1 | Restrained panel motion | | `morph` | 420 | 26 | 1 | A more elastic change; the expressive default | | `gentle` | 220 | 30 | 1 | Slower, calmer movement | ```tsx import { DropdownMenu, motionTokens } from '@uthereal/ui/dropdown-menu' ; ``` For your own spring, provide `type: 'spring'` and any of `stiffness`, `damping`, or `mass`. Unspecified spring fields use `morph` defaults. A spring is physics-based; it does not accept a tween duration or easing curve. ## Easing and duration All public duration options use **milliseconds**. Motion itself expects seconds for tweens; the component converts at the rendering boundary. `motionTokens.duration` provides `fast: 120`, `standard: 240`, and `considered: 480`. `motionTokens.easing` provides `standard: 'easeInOut'`, `enter: 'easeOut'`, and `exit: 'easeIn'`. You can also choose `linear`. ```tsx ``` The popup settles at opacity 1, scale 1, and zero travel. Enter/exit offsets are positive distances **toward the trigger**, on the axis of the actual placement. Submenus and collision-flipped menus therefore travel in the appropriate direction. `transition` controls both entrance and exit; there is no looping or delay option. ## Option reference Generated from the schema. Defaults below use `subtle`; spring-only fields show the fallback spring values. Numeric geometry uses pixels, rotation uses degrees, opacity and scale are unitless. A zero duration or offset is preserved. | Option | Default | Accepted values | Purpose | | --- | --- | --- | --- | | transition.type | tween | tween, spring | Popup transition kind | | transition.duration | 120 | 0–2000 | Milliseconds; zero is immediate | | transition.ease | easeOut | linear, easeIn, easeOut, easeInOut | Timing curve | | transition.stiffness | 420 | 1–1000 | Spring stiffness | | transition.damping | 26 | 1–100 | Resistance to oscillation | | transition.mass | 1 | 0.1–10 | Simulated mass | | enter.opacity | 0 | 0–1 | Starting or ending opacity | | enter.scale | 0.98 | 0.5–1.2 | Starting or ending scale | | enter.offset | 4 | 0–40 | Travel toward the trigger, px; follows actual placement | | exit.opacity | 0 | 0–1 | Starting or ending opacity | | exit.scale | 0.98 | 0.5–1.2 | Starting or ending scale | | exit.offset | 2 | 0–40 | Travel toward the trigger, px; follows actual placement | | highlightDuration | 90 | 0–2000 | Pointer highlight travel, ms; keyboard is always immediate | | labelDuration | 120 | 0–2000 | Trigger text transition, ms | | labelOffset | 3 | 0–24 | Trigger text travel, px | | chevronDuration | 140 | 0–2000 | Chevron rotation, ms | | chevronRotation | 180 | -360–360 | Open chevron angle, degrees | | chevronEase | easeInOut | linear, easeIn, easeOut, easeInOut | Chevron timing curve | ## Reduced motion and input The component watches the device's `prefers-reduced-motion` setting, including changes while mounted. Reduced motion removes popup travel, label transitions, pointer-highlight movement, and chevron animation, regardless of the preset or supplied overrides. Focus, state changes, and action feedback remain available. Keyboard navigation always updates its highlight immediately. Timing overrides apply to pointer movement; repeated arrow presses never wait for an animation. Avoid using motion alone to communicate a result. ## Interruptions and live edits Motion handles interrupted transitions. Closing makes the exiting popup inert immediately; an animation never delays an action or leaves a closing menu interactive. Changing design or motion arguments preserves a mounted menu's selections and IDs. Changing entrance settings is easiest to compare by reopening the menu. Use a `DropdownPreset` to share `motion` and `motionOptions` across an application. Nested fields merge; changing `transition.type` replaces its old variant, so tween settings cannot leak into a spring. Agents use the same options and validation rules; see [Building with agents](/docs/agents). --- # Playground A workspace for color, shape, spacing, type, and motion. Make it yours. Interactive design playground: /docs/foundations/playground. Explore Colors, Shape, Spacing, Typography, and Motion with a live dropdown and copyable React configuration. --- # Theming Semantic colors, light and dark palettes, shape, spacing, and type. Start with a recipe. Choose a color mode and accent. Override only the tokens your design needs. Every option is typed, serializable, and available to agents through the same component contract. Explore theme and motion together in the [Design Playground](/docs/foundations/playground). ## Color roles Colors describe a purpose: `surface` for the trigger, `surfaceRaised` for the popup, `foreground` for text, and `highlight` for the active item. `accent` and `accentForeground` are a pair; `focusRing` and `danger` remain independent so interaction and destructive actions stay legible. ```tsx ``` Use `neutral`, `blue`, `violet`, `green`, `amber`, or `coral`. Omitting the accent keeps the recipe's palette. A supplied accent updates the solid trigger and keyboard focus ring; surfaces remain neutral. ## Dark mode Pass `theme.mode="dark"` as an object property. The dropdown uses a separately defined dark palette, including its portalled and nested menus. It does not change the page theme or read local storage. ```tsx ``` Your application owns its theme preference. Pass the same mode to each instance through a shared preset; changing it does not reset menu state. ## Shape, spacing, and typography `recipe` chooses `studio` or `soft`; `size` chooses `sm`, `md`, or `lg`. These supply defaults for the same token vocabulary. Explicit tokens win, even when their value is zero. ```tsx ``` Numeric geometry and font sizes use **pixels**. Opacity is unitless; font weight is numeric. Fonts are provided by the host application. Popup widths remain clamped to the viewport; if the preferred minimum exceeds the maximum, the maximum wins. ## Token reference These values are generated from the schema and `resolveTheme()`. Defaults below are **studio / md / light**, without an accent override. The Design Playground starts with blue. `soft` changes its palette, shape, spacing, and elevation; size changes density. Call `resolveTheme(theme, recipe, size)` to inspect any combination. | Token | CSS variable | Studio / md / light default | Accepted values | Purpose | | --- | --- | --- | --- | --- | | surface | --ui-surface | #ffffff | CSS color | Trigger background | | surfaceRaised | --ui-surface-raised | #ffffff | CSS color | Popup background | | foreground | --ui-text | #26272b | CSS color | Primary text and icons | | mutedForeground | --ui-muted | #6b6e76 | CSS color | Shortcut text | | border | --ui-border | #e3e4e8 | CSS color | Control edges and separators | | highlight | --ui-highlight | #f2f3f5 | CSS color | Hovered trigger and active menu item | | accent | --ui-accent | #36383e | CSS color | Solid trigger background | | accentForeground | --ui-accent-foreground | #ffffff | CSS color | Text on a solid trigger | | danger | --ui-danger | #b23e38 | CSS color | Destructive action text | | focusRing | --ui-focus-ring | #36383e | CSS color | Keyboard focus outline | | radius | --ui-radius | 8 | 0–48 | Trigger corner radius, px | | popupRadius | --ui-popup-radius | 10 | 0–48 | Popup corner radius, px | | itemRadius | --ui-item-radius | 5 | 0–48 | Item corner radius, px | | borderWidth | --ui-border-width | 1 | 0–4 | Control and popup border, px | | fontFamily | --ui-font | inherit | Font family list | CSS font family list; fonts are supplied by the host | | fontSize | --ui-font-size | 14 | 10–24 | Trigger and item text, px | | fontWeight | --ui-font-weight | 500 | 100–900 | Trigger text weight | | shortcutSize | --ui-shortcut-size | 11 | 10–20 | Shortcut text, px | | triggerHeight | --ui-trigger-height | 36 | 24–80 | Minimum trigger height, px | | triggerPadding | --ui-trigger-padding | 12 | 0–40 | Trigger inline padding, px | | triggerGap | --ui-trigger-gap | 12 | 0–32 | Trigger label-to-chevron gap, px | | popupPadding | --ui-popup-padding | 6 | 0–24 | Popup inner padding, px | | itemHeight | --ui-item-height | 36 | 24–80 | Minimum item height, px | | itemPaddingX | --ui-item-padding-x | 10 | 0–32 | Item inline padding, px | | itemPaddingY | --ui-item-padding-y | 8 | 0–24 | Item block padding, px | | itemGap | --ui-item-gap | 8 | 0–24 | Item label-to-icon gap, px | | popupMinWidth | --ui-popup-min-width | 220 | 120–640 | Preferred minimum popup width, px; viewport clamped | | popupMaxWidth | --ui-popup-max-width | 320 | 120–800 | Preferred maximum popup width, px; viewport clamped | | shadow | --ui-shadow | soft | none, soft, floating | Popup elevation | | disabledOpacity | --ui-disabled-opacity | 0.45 | 0.2–1 | Disabled trigger and item opacity | Color values accept hex, numeric `rgb()` / `rgba()`, `hsl()` / `hsla()`, `oklch()` / `oklab()`, `transparent`, `currentColor`, or a simple `var(--token)` reference. Use valid CSS color syntax. Define referenced variables on a shared ancestor such as `:root`, since a portal can leave a locally scoped container. Keep foreground/background contrast when overriding colors. ## Shared application defaults ```tsx import { DropdownMenu, type DropdownPreset } from '@uthereal/ui/dropdown-menu' const appMenu = { recipe: 'studio', size: 'sm', theme: { mode: 'light', accent: 'blue', tokens: { fontFamily: 'Inter, sans-serif', popupRadius: 12 }, }, } satisfies DropdownPreset ``` Resolution order is **library defaults → application preset → instance arguments**. Nested option objects merge by field, arrays replace, and `undefined` leaves the inherited value alone. The example keeps the font and accent but uses square popup corners. Resolved design values then follow **recipe and size → color mode and accent → explicit tokens**. ## React CSS escape hatch The existing `tokens` prop still accepts CSS custom properties and inline styles, applied to the trigger container and every popup positioner. It wins over typed theme values. Use it for host-only CSS integration; agents use the validated `theme` object instead. ```tsx ``` The legacy `--ui-surface` shorthand also colors the popup, and `--ui-radius` derives popup and item radii unless those CSS variables are supplied separately. Prefer typed tokens for new components: their names, limits, and meaning are exported in the agent schema. --- # Installation Add the source foundation to your React application. ## Requirements - React and React DOM **19.2.3 or later**. - TypeScript and a bundler with CSS Modules support. - Node **22.13+ (22.x) or 24+** for this repository's development tooling. ## Run this documentation ```sh npm ci npm run dev ``` Open [localhost:5173](http://127.0.0.1:5173). The documentation app uses Next.js, Fumadocs, and MDX. ## Install the source package The package is currently private and is not published to the npm registry. Create a local archive from the repository: ```sh npm pack ``` Then install it in your application: ```sh npm install /path/to/uthereal-ui-0.1.0.tgz ``` The archive contains `src/` and the package documentation. It does not include this documentation website or test fixtures. Next.js and Fumadocs are development dependencies of this repository, not runtime dependencies of your app. ## Next.js Enable transpilation for the source package in your application's Next.js configuration: ```ts // next.config.ts import type { NextConfig } from 'next' const config: NextConfig = { transpilePackages: ['@uthereal/ui'], } export default config ``` Use the dropdown from a Client Component when passing event handlers: ```tsx 'use client' import { DropdownMenu } from '@uthereal/ui/dropdown-menu' export function Actions() { return ( console.log(action)} /> ) } ``` ## Vite Vite handles the package's TypeScript and CSS Modules directly. Import the component using the same public path. React Compiler is optional. ## Optional agent integration Use `@uthereal/ui/agent` for validated single-component edits. Use `@uthereal/ui/composition` and `@uthereal/ui/composition/react` to compose registered components with json-render. See [Building with agents](/docs/agents). --- # Introduction Independent React components, with design and behavior you can shape. Uthereal UI is a source foundation for building applications with consistent interactions. Every component is usable on its own, has typed arguments and defaults, and can be updated by an application or an agent. ## Start with a component [**Dropdown menu →**](/docs/components/dropdown-menu) Try the real dropdown, adjust its parameters, inspect the code, and explore nested actions and checkboxes. This is the first component in the library. ## Three parts, one component - **Behavior:** keyboard navigation, focus, positioning, and accessible semantics, powered by Zag. - **Presentation:** appearance recipes, size, variant, and CSS tokens. - **Motion:** named presets powered by Motion, with system reduced-motion support. You own the component source. Supporting packages handle established interaction and animation mechanics. ## Read a component page Every page begins with a working preview and controls. Installation and usage come next, followed by examples, typed parameters, keyboard behavior, and motion. The preview runs the actual component. Changes to the implementation appear in the documentation immediately. ## Build with agents Agents select registered components and provide validated, serializable arguments. Your application owns actions and persistent state. [Learn how the agent bridge works →](/docs/agents) ## Find your way Use the grouped sidebar or press **⌘ K** / **Ctrl K** to search. Copy a page as Markdown for an assistant, or use the [agent documentation index](/llms.txt).