UIAP Capability Model
UIAP Capability Model v0.1
Section titled “UIAP Capability Model v0.1”| Field | Value |
|---|---|
| Status | Draft |
| Version | 0.1 |
| Date | 2026-03-27 |
| Dependencies | — |
| Editors | Patrick |
1. Purpose
Section titled “1. Purpose”The Capability Model describes what an application can semantically present, observe, and execute.
It cleanly separates:
- Roles: what a UI entity is
- States: what state it is in
- Affordances: which interactions it fundamentally offers
- Actions: which standardized requests the agent can send
- Risk: how strictly an action must be regulated
- Success Signals: how success can be observed
This is the difference between “there is some button” and “this is video.submit, activatable, requires confirmation, success = route changes and a toast appears”.
2. General Model Rules
Section titled “2. General Model Rules”- Capability values SHOULD be stable and machine-readable.
- Core values are reserved without prefix.
- Vendor-/app-specific extensions SHOULD begin with
x., e.g.x.videoland.asset-card. - A capability document MAY support only a subset of the core vocabulary; the actually supported values MUST be explicitly declared.
- Roles and affordances describe semantics, not concrete DOM structures or CSS.
3. Base Types
Section titled “3. Base Types”type ProfileId = string; // e.g. "web@0.1"type StableId = string; // stable, app-defined target IDtype ScopeId = string; // logical scope, e.g. "create-video-dialog"type ActionId = string; // e.g. "ui.activate" or "video.create"3.1 Target Reference
Section titled “3.1 Target Reference”type TargetRef = | { by: "stableId"; value: StableId } | { by: "scope"; value: ScopeId } | { by: "route"; value: string } | { by: "semantic"; role: UIRole; name?: string; scope?: ScopeId } | { by: "custom"; value: string };4. UI Roles
Section titled “4. UI Roles”UIRole is the canonical typing of visible or interactive UI objects.
type UIRole = // App / Structure | "app" | "route" | "region" | "group" | "form" | "dialog" | "drawer" | "popover" | "tabpanel"
// Navigation / Structured Selection | "link" | "menu" | "menuitem" | "tablist" | "tab" | "toolbar" | "breadcrumb" | "pagination"
// Collections | "list" | "listitem" | "table" | "row" | "cell" | "grid" | "tree" | "treeitem"
// Inputs / Controls | "button" | "textbox" | "textarea" | "searchbox" | "combobox" | "listbox" | "option" | "checkbox" | "radio" | "switch" | "slider" | "spinbutton" | "datepicker" | "timepicker" | "fileinput" | "label"
// Feedback / Status | "alert" | "toast" | "status" | "progress" | "spinner"
// Media / Special Cases | "image" | "video" | "audio" | "canvas"
// Escape hatch | "custom";4.1 Role Semantics
Section titled “4.1 Role Semantics”button: activatable commandtextbox/textarea: editable text inputcheckbox/radio/switch: discrete state selectioncombobox/listbox/option: selection from candidatesdialog/drawer/popover: temporary UI surfacestoast/alert/status: observable feedback signalscustom: only when no core role fits
5. UI States
Section titled “5. UI States”UIState describes the observable state of an element or scope.
interface UIState { visible?: boolean; enabled?: boolean; focusable?: boolean; focused?: boolean; editable?: boolean; readonly?: boolean; required?: boolean;
busy?: boolean; loading?: boolean; blocked?: boolean;
selected?: boolean; checked?: boolean | "mixed"; pressed?: boolean; expanded?: boolean; open?: boolean; modal?: boolean;
hovered?: boolean; dragged?: boolean;
current?: false | "page" | "step" | "location" | "date" | "time"; invalid?: false | true | "grammar" | "spelling";
multiline?: boolean; hasPopup?: false | "menu" | "listbox" | "dialog" | "grid" | "tree"; orientation?: "horizontal" | "vertical";
textValue?: string; numericValue?: number; min?: number; max?: number; step?: number;
placeholder?: string; description?: string;
sensitive?: boolean; obscured?: boolean;}5.1 State Keys
Section titled “5.1 State Keys”A capability document SHOULD additionally declare which state keys are actively emitted.
type UIStateKey = keyof UIState;5.2 State Rules
Section titled “5.2 State Rules”visible=falsedoes not automatically implyenabled=false.blocked=truemeans: formally present but currently not usable.sensitive=truemarks data or controls that require special policy treatment.obscured=truemarks content that is covered or intentionally masked.
6. Affordances
Section titled “6. Affordances”Affordances describe which type of interaction an element fundamentally offers.
type UIAffordance = | "read" | "focus" | "activate" | "edit" | "choose" | "toggle" | "expand" | "collapse" | "open" | "close" | "scroll" | "submit" | "dismiss" | "drag" | "drop" | "resize" | "upload" | "navigate" | "invoke";6.1 Affordance Semantics
Section titled “6.1 Affordance Semantics”activate: generic activation, e.g. button, link, cardedit: text or value can be modifiedchoose: selection from optionstoggle: binary or tri-state switchinvoke: domain-level app action beyond a simple click
6.2 Important Distinction
Section titled “6.2 Important Distinction”- Affordance = what an element can principally offer
- Action = standardized request from the agent
A button typically has the activate affordance. The agent then sends e.g. ui.activate.
7. Actions
Section titled “7. Actions”Actions are standardized executable operations.
7.1 Primitive Actions
Section titled “7.1 Primitive Actions”type PrimitiveActionType = | "ui.read" | "ui.focus" | "ui.highlight" | "ui.hover" | "ui.activate" | "ui.enterText" | "ui.clearText" | "ui.setValue" | "ui.choose" | "ui.toggle" | "ui.expand" | "ui.collapse" | "ui.open" | "ui.close" | "ui.scrollIntoView" | "ui.scroll" | "ui.submit" | "ui.upload" | "nav.navigate" | "app.invoke";7.2 Execution Modes
Section titled “7.2 Execution Modes”type ExecutionMode = | "appAction" // direct app function / registry | "semanticUi" // semantic UI target addressing | "inputSynthesis" // synthetic pointer/keyboard input | "externalDriver" // external automation driver | "visionAssist"; // vision-assisted fallback7.3 Action Descriptor
Section titled “7.3 Action Descriptor”interface ActionDescriptor { id: ActionId; // "ui.activate" or "video.create" kind: "primitive" | "domain"; title?: string; description?: string;
targetKinds: Array<"element" | "scope" | "route" | "entity" | "session" | "none">; requiredAffordances?: UIAffordance[]; executionModes: ExecutionMode[];
args?: ActionArgDescriptor[]; idempotency?: "idempotent" | "conditional" | "non_idempotent";
risk: RiskDescriptor; success?: SuccessSignal[];
metadata?: Record<string, unknown>;}interface ActionArgDescriptor { name: string; type: "string" | "number" | "boolean" | "enum" | "object" | "array"; required?: boolean; enum?: string[]; description?: string;}7.4 Domain Actions
Section titled “7.4 Domain Actions”In addition to primitive actions, an application MAY declare domain-specific actions, e.g.:
video.createworkspace.setupteam.invitebilling.openSettings
These SHOULD be stable, dot-segmented, and named with domain semantics.
8. Risk Model
Section titled “8. Risk Model”This is intentionally separated cleanly, because people otherwise tend to squeeze five entirely different risks into a single word.
8.1 Effective Risk Level
Section titled “8.1 Effective Risk Level”RiskLevel controls executability.
type RiskLevel = | "safe" // autonomously executable within granted scopes | "confirm" // explicit user confirmation required | "blocked"; // not automatically executable8.2 Risk Tags
Section titled “8.2 Risk Tags”RiskTag describes the domain-level cause or class of the risk.
type RiskTag = | "sensitive_data" | "destructive" | "external_effect" | "privileged" | "billing" | "security" | "identity" | "legal" | "irreversible";8.3 Risk Descriptor
Section titled “8.3 Risk Descriptor”interface RiskDescriptor { level: RiskLevel; tags?: RiskTag[]; reason?: string;}8.4 Risk Semantics
Section titled “8.4 Risk Semantics”safe: e.g. opening a route, switching a tab, writing a text suggestion into a draftconfirm: e.g. creating a record, sending an invitation, saving settingsblocked: e.g. changing a password, triggering a payment, deleting a user, irreversible publish action
8.5 Risk Rules
Section titled “8.5 Risk Rules”- When multiple risk tags apply, the strictest
levelwins. blockedMUST NOT be executed autonomously.confirmSHOULD require a human confirmation point before execution.
9. Success Signals
Section titled “9. Success Signals”Success Signals are observable predicates, not wishes and not prompt-based superstition.
9.1 Signal Classes
Section titled “9.1 Signal Classes”type SuccessSignal = | { kind: "element.appeared"; target: TargetRef } | { kind: "element.disappeared"; target: TargetRef } | { kind: "element.state"; target: TargetRef; state: Partial<UIState> } | { kind: "value.equals"; target: TargetRef; value: string | number | boolean } | { kind: "route.changed"; pattern?: string; exact?: string } | { kind: "dialog.opened"; target?: TargetRef } | { kind: "dialog.closed"; target?: TargetRef } | { kind: "toast.contains"; text: string } | { kind: "status.contains"; text: string } | { kind: "validation.none"; scope?: ScopeId } | { kind: "collection.count"; target: TargetRef; op: "eq" | "gte" | "lte"; value: number } | { kind: "entity.created"; entityType: string; idPath?: string } | { kind: "entity.updated"; entityType: string; idPath?: string } | { kind: "entity.deleted"; entityType: string; idPath?: string } | { kind: "network.response"; urlPattern?: string; status?: number } | { kind: "custom"; name: string; payload?: Record<string, unknown> };9.2 Signal Rules
Section titled “9.2 Signal Rules”- Signals SHOULD be declarative and observable.
- An action descriptor SHOULD contain at least one expected success signal.
customSHOULD only be used when no core signal fits.- For critical domain actions, multiple success signals SHOULD be combined.
Example: video.create
route.changedto/videos/:idtoast.contains = "erstellt"- optionally
entity.created = "video"
10. Capability Document
Section titled “10. Capability Document”The capability document is the comprehensive description of active capabilities.
interface CapabilityDocument { modelVersion: "0.1"; profile: ProfileId; // e.g. "web@0.1"
roles: UIRole[]; stateKeys: UIStateKey[]; affordances: UIAffordance[];
actions: ActionDescriptor[];
riskLevels: RiskLevel[]; riskTags?: RiskTag[];
successSignalKinds: string[];
metadata?: Record<string, unknown>;}10.1 Rules
Section titled “10.1 Rules”roles,stateKeys,affordances,actions,riskLevelsMUST be present.- An app MUST only declare values that are actually supported.
successSignalKindsSHOULD contain allkindvalues used in the document.
11. Example Capability Document
Section titled “11. Example Capability Document”{ "modelVersion": "0.1", "profile": "web@0.1", "roles": [ "route", "dialog", "form", "button", "textbox", "textarea", "toast", "status" ], "stateKeys": [ "visible", "enabled", "focused", "required", "open", "invalid", "textValue", "sensitive" ], "affordances": [ "read", "focus", "activate", "edit", "submit", "navigate", "invoke" ], "actions": [ { "id": "ui.activate", "kind": "primitive", "targetKinds": ["element"], "requiredAffordances": ["activate"], "executionModes": ["appAction", "semanticUi", "inputSynthesis"], "risk": { "level": "safe" } }, { "id": "ui.enterText", "kind": "primitive", "targetKinds": ["element"], "requiredAffordances": ["edit"], "executionModes": ["appAction", "semanticUi", "inputSynthesis"], "args": [ { "name": "text", "type": "string", "required": true } ], "risk": { "level": "safe" } }, { "id": "video.create", "kind": "domain", "title": "Video erstellen", "targetKinds": ["scope"], "executionModes": ["appAction", "semanticUi"], "args": [ { "name": "title", "type": "string", "required": true }, { "name": "useCase", "type": "string", "required": false } ], "idempotency": "non_idempotent", "risk": { "level": "confirm", "tags": ["external_effect"] }, "success": [ { "kind": "route.changed", "pattern": "/videos/:id" }, { "kind": "toast.contains", "text": "erstellt" } ] } ], "riskLevels": ["safe", "confirm", "blocked"], "riskTags": [ "sensitive_data", "destructive", "external_effect", "privileged" ], "successSignalKinds": [ "route.changed", "toast.contains", "element.state", "validation.none" ]}Normative References
Section titled “Normative References”- [UIAP-CORE] UIAP Core v0.1
- [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
Security Considerations
Section titled “Security Considerations”- Capability documents MAY contain security-relevant information (e.g. available admin actions). Access to capability information SHOULD be restricted to authorized agents.
- Risk levels MUST be declared correctly; incorrect classification can lead to unintended actions.
- Sensitive fields SHOULD be marked as such in the capability document.
Changelog
Section titled “Changelog”| Version | Date | Changes |
|---|---|---|
| 0.1 | 2026-03-27 | Initial draft |