Generative UIs

Potential approaches to facilitating high-trust generative UI

Active project

This research project is actively under way and this page may be subject to regular updates.

Background

HashDS is intended as an agent-first design system, built for consumption and use by both humans and AI agents, leveraging SemType.

We anticipate that an overwhelming (>99%) proportion of interfaces created using HashDS will be generated by AI.

Potential Architecture

Intents

Most design systems begin with tokens that give way to components. HashDS begins with intents.

Intents describe the goal underlying the use of a component — for example: Compare(items, criteria), Collect(fields, validation), ReviewAndConfirm(summary, actions), or ExplainAndChoose(options, rationale).

Intents can also be chained into series of two or more that work well together in service of a larger objective.

We envisage that generative user interfaces (GenUI) will primarily be created by agents emitting intents, which are then translated into components.

Intents provide a form of capability-based security, insofar as what can be done is determined by the capabilities held — not by identity or role. A capability is an unforgeable token that grants permission to perform a specific kind of operation or to access a specific resource.

Our notion of intents maps directly onto this model. In GenUI, the agent does not have a blanket capability to render arbitrary UI. It can only emit declared intents from a fixed, curated set (e.g. Collect, ConfirmDestructiveAction, VerifiedAction). The system then:

  • Resolves each intent to one or more components that are authorized to fulfill that intent.
  • Gates access to sensitive surfaces — trust tokens, payment flows, destructive confirmations, verified-action buttons — so that only components bound to the matching intent can use them.
  • Rejects agent output that references intents that don’t exist, or that tries to use a high-trust component for an intent that doesn’t carry the corresponding capability.

Intents effectively function as capability tokens: agents hold the capability to request “collect payment” or “confirm destructive action” only by emitting the right intent, and the renderer will only attach components that declare that intent. The agent cannot invent a new intent, cannot restyle a trust component to look like something else, and cannot get a “verified” or “destructive confirmation” surface without going through the declared intent, providing a genuine form of capability-based security at the UI layer. Privileges cannot be escalated by describing the UI in different words; the only way to get a sensitive capability is to hold the right intent, which the system validates and maps to a bounded set of components and behaviors.

Tokens

Tokens are a common feature of nearly all design systems, acting as primitives that define base values and semantic correspondence.

Trust tokens

In addition to traditional tokens, HashDS defines a protected set of trust tokens.

Trust tokens are special-cased tokens which agents will be unable to use arbitrarily. They are reserved for styling specific components that users can easily recognize as trustworthy.

Relatedly, agents will be prevented from setting raw hex values or arbitrary spacing values to avoid them wittingly (or unwittingly) producing components which mimic or obscure real "trusted" ones.

Additional concerns

Tokens encode accessibility concerns (e.g. minimum contrast ratios), enabling good user experiences to be linted and enforced during UI generation.

Components

The final scope of components is the subject of ongoing active investigation. This section outlines our current thinking and research direction.

Deterministic composition

Components should be composable by agents using a user interface intermediate representation (UI‑IR) that can be validated, linted, and rendered deterministically.

  • The UI‑IR is likely to be a JSON-based schema representing intent, structure, states, actions, and data dependencies.
  • A renderer provides the only place where actual DOM or native views are created.
  • A validator rejects invalid combinations (e.g. a modal containing primary + destructive + no confirmation). Invalid plans may be auto-repaired via a constraint-solver pass, supporting agentic learning ("I fixed X because Y").
  • A linter ensures stable ordering and formatting so that the same plan always produces the same UI, limiting diff noise.

Strong typing

Components will be strongly typed:

  • An input schema explicitly defines what data fields a component can accommodate and what it requires, corresponding to SemType data types. This provides guarantees around correctness and supports reusability across multiple contexts.
  • An output schema specifies all possible events (defined as intents) that a component may emit upon interaction, supporting the triggering of actions beyond the component itself. Arbitrary callbacks will not be allowed.
  • A declared intent allows components to access the appropriate set of capabilities associated with them (e.g. collect-payment, compare-options, confirm-destructive-action).
  • Copy controls guide or restrict the text that appears within components. "Typed slots" for copy (e.g. title, helper, error, disclaimer, cta_label) are used, with constraints defined per slot — for example, max character length, allowed or disallowed verbs, a target reading age, a restriction on "making promises", or any other linguistic rule. Standardized intent-linked phrase banks and templates encourage consistency and precision. Text may be automatically inferred from a component's declared intent, and form labels derived from the name or description of the SemType property and link types associated with any inputs.
  • Other constraints such as allowed props, required pairings, or forbidden combinations may also be encoded.
  • Cost information may be included to help avoid generating cognitively heavy or screen-real-estate-intensive components and series.
  • Trust information unlocks the use of otherwise reserved trust tokens by specific approved components, enabling them to style themselves in a way that end-users can easily recognize. By leveraging the typings of SemType attributes and entities, the system can assess what kind of information and operations a component touches. Capabilities like "Reads PII" and "Writes PII" can be known about intents, and appropriate components selected accordingly. Agents generating things that "look right" but violate trust (phishing-like flows, hidden destructive actions, fake verification badges, etc.) can be prevented through capability-based security gating — components are only accessible where intent matches up. Protecting these components minimizes the risk of agents inventing novel dangerous patterns.
    • Confirmation dialogues: destructive actions can always be gated.
    • Verified action buttons: cannot be restyled and always show scope, target, and undo (where supported).
    • Transaction summaries: standardized breakdown (amount, recipient, source, fees).
    • Data-use disclosures: standardized "what data will be used" block.
    • Source attribution: structured citations and links when the UI makes claims.
    • Confidence chips: a non-marketing, consistent way to show uncertainty only when appropriate.
  • Interaction state encoding: instead of ad-hoc props, explicit state machines help GenUI avoid unintended intermediate states (e.g. "loading but clickable" or "error but success copy"). For each pattern or component these define:
    • States — e.g. idlevalidatingsubmittingsuccess | errorretry | done
    • Allowed transitions
    • Required UI affordances per state — e.g. submitting disables the primary action and shows a progress indicator (or optimistically renders the outcome with the ability to revert if a background operation subsequently fails)
    • Standardized error taxonomies — e.g. network, authorization, or other error messages, typed and fitted into the typed slots defined by copy constraints (see above)

We would like to build tooling directly into our component library to facilitate easy visual inspection of component state machines using Petrinaut.

When events are emitted by components, we also want to ensure that contextual information (i.e. what a user sees on their screen) is transmitted alongside each event, for provenance and traceability purposes. This could entail the UI‑IR being preserved for audit.

Stream safety

  • Components should support progressive hydration with guaranteed stable heights to avoid layout shift.
  • Skeleton states should preserve layout to avoid jank. "Placeholders with commitments" can indicate what will appear ("Results list", "Price breakdown") without showing incorrect content.
  • Agents should be able to add sections but not reorder sections a user has already interacted with.

Accessibility

In support of the validator, components should also:

  • Contain accessibility invariants (e.g. require a label, enforce focus-order rules)
  • Enforce keyboard navigation order and focus traps (where needed)
  • Enforce automatic color-contrast minimums (via the tokens they use)
  • Support screen-reader-friendly dynamic updates (e.g. standardize ARIA live regions)

Composability

Component composition by agents will not be freeform. Stacks, grids, sidebars, and layouts in general should be defined, each with constraints (e.g. maximum number of columns, minimum touch-target sizing, or required spacing tokens).

This approach enables:

  • Layout linting: checking for cognitive overload — e.g. multiple "primary" actions per view, density overload (too many interactive controls per viewport), or "scanline" checks (ensuring the UI reads sensibly top to bottom).
  • Layout budgeting: calculating attention, interaction, and reading budgets that agents must stay within unless they can explicitly justify exceeding them.
  • Design fuzzing: automatically composing components in many different ways to detect issues when combined (accessibility violations, visual collisions, etc.).

Observability and optimization

In addition to a standardized error taxonomy, and ensuring events are only ever emitted by components as intents, observability can provide:

  • A high-integrity provenance trail showing how information was generated or produced.
  • A standardized way to track real user experience in GenUI. A consistent mechanism for detecting rage clicks, backtracking, hover pauses, and other indicators of poor UX will be built into components.
  • Analytics by series or intent, with the ability to test and optimize components in different contexts. User interfaces may be dynamically regenerated to minimize frustration or time to completion. Note: this same optimization capacity could enable the discovery of new "dark patterns" and may be subject to abuse.

Documentation

  • On a micro level: components will be accompanied by rich documentation outlining their states and usage in detail.
  • On a macro level: the design system as a whole — rules around component usage and composition — will be written up at hash.design alongside instructions for agents (e.g. as skills), and will contain important principles such as "don't auto-regenerate components mid-use" (data can update but composition cannot) and "restrict trust components appropriately" (when users see a confidence chip or verification badge, they should know it is legitimate).

Examples and anti-examples

Components should be accompanied by a library of (i) positive usage examples and (ii) negative anti-examples — small, structured snippets agents can retrieve — demonstrating how they should and shouldn't be used, as well as the kinds of real-world scenarios they are or aren't suited for. These examples can be used for generative-model training or as searchable references, each with descriptions and outlined purpose. This helps facilitate good UX and prevent bad UX or dark patterns (e.g. avoiding pre-checked opt-ins for marketing, ensuring clear labeling of irreversible or destructive actions).

Last updated on 2026-03-06

Was this page helpful?

On this page