oui-spec 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +94 -122
  2. package/dist/{chunk-CVUUSPF4.js → chunk-BMCL2K74.js} +2 -2
  3. package/dist/chunk-BMCL2K74.js.map +1 -0
  4. package/dist/{chunk-MTMEW6MM.cjs → chunk-DCVVTP3V.cjs} +72 -23
  5. package/dist/chunk-DCVVTP3V.cjs.map +1 -0
  6. package/dist/chunk-DGMKSJTY.cjs +573 -0
  7. package/dist/chunk-DGMKSJTY.cjs.map +1 -0
  8. package/dist/chunk-F3SKRAGU.cjs +98 -0
  9. package/dist/chunk-F3SKRAGU.cjs.map +1 -0
  10. package/dist/{chunk-YDMGV72W.js → chunk-F3WKIRAU.js} +72 -23
  11. package/dist/chunk-F3WKIRAU.js.map +1 -0
  12. package/dist/chunk-GXTNZ44I.js +569 -0
  13. package/dist/chunk-GXTNZ44I.js.map +1 -0
  14. package/dist/chunk-IIZ6HL2L.js +89 -0
  15. package/dist/chunk-IIZ6HL2L.js.map +1 -0
  16. package/dist/chunk-NYCJZQSP.js +92 -0
  17. package/dist/chunk-NYCJZQSP.js.map +1 -0
  18. package/dist/chunk-ROGKEMLL.cjs +91 -0
  19. package/dist/chunk-ROGKEMLL.cjs.map +1 -0
  20. package/dist/{chunk-3DCIL4FV.cjs → chunk-ZKM4XWAB.cjs} +2 -2
  21. package/dist/chunk-ZKM4XWAB.cjs.map +1 -0
  22. package/dist/core/index.cjs +10 -6
  23. package/dist/core/index.d.cts +15 -8
  24. package/dist/core/index.d.ts +15 -8
  25. package/dist/core/index.js +3 -3
  26. package/dist/index.cjs +28 -12
  27. package/dist/index.d.cts +5 -4
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.js +5 -5
  30. package/dist/react/index.cjs +15 -3
  31. package/dist/react/index.d.cts +33 -50
  32. package/dist/react/index.d.ts +33 -50
  33. package/dist/react/index.js +1 -1
  34. package/dist/spec/index.cjs +2 -2
  35. package/dist/spec/index.d.cts +35 -7
  36. package/dist/spec/index.d.ts +35 -7
  37. package/dist/spec/index.js +1 -1
  38. package/dist/{define-surface-D6XPtoqu.d.cts → surface-runtime-BzIKgL_I.d.cts} +102 -2
  39. package/dist/{define-surface-DXBop-uB.d.ts → surface-runtime-DeByfbKg.d.ts} +102 -2
  40. package/dist/transport/index.cjs +4 -4
  41. package/dist/transport/index.d.cts +2 -2
  42. package/dist/transport/index.d.ts +2 -2
  43. package/dist/transport/index.js +2 -2
  44. package/dist/{websocket-CrI0yRNo.d.cts → websocket-YfWILdZ4.d.cts} +36 -18
  45. package/dist/{websocket-CiWvkaz_.d.ts → websocket-c5tIUWY5.d.ts} +36 -18
  46. package/package.json +5 -1
  47. package/spec/OUI-SPEC-v0.1.md +229 -155
  48. package/dist/chunk-2ON5IEXB.cjs +0 -167
  49. package/dist/chunk-2ON5IEXB.cjs.map +0 -1
  50. package/dist/chunk-3DCIL4FV.cjs.map +0 -1
  51. package/dist/chunk-5TQ6AVQH.cjs +0 -108
  52. package/dist/chunk-5TQ6AVQH.cjs.map +0 -1
  53. package/dist/chunk-CVUUSPF4.js.map +0 -1
  54. package/dist/chunk-HK7OXB2W.cjs +0 -157
  55. package/dist/chunk-HK7OXB2W.cjs.map +0 -1
  56. package/dist/chunk-ILUTAHUJ.js +0 -154
  57. package/dist/chunk-ILUTAHUJ.js.map +0 -1
  58. package/dist/chunk-MTMEW6MM.cjs.map +0 -1
  59. package/dist/chunk-O6EI77LD.js +0 -106
  60. package/dist/chunk-O6EI77LD.js.map +0 -1
  61. package/dist/chunk-UIGRLZOX.js +0 -164
  62. package/dist/chunk-UIGRLZOX.js.map +0 -1
  63. package/dist/chunk-YDMGV72W.js.map +0 -1
@@ -3,7 +3,7 @@
3
3
  **Version:** 0.1.0
4
4
  **Status:** Draft
5
5
  **Date:** 2026-07-27
6
- **Authors:** Closure Studio
6
+ **Authors:** Closure Studio
7
7
 
8
8
  ---
9
9
 
@@ -35,11 +35,13 @@ This document defines the **Open UI Specification (OUI)** — a machine-readable
35
35
  OUI defines a standard interface through which AI agents can programmatically control user interfaces. It replaces fragile vision-based or DOM-scraping approaches with an application-declared, typed, semantic contract.
36
36
 
37
37
  An application that implements OUI declares:
38
+
38
39
  - **What it can do** (Actions)
39
40
  - **What state is observable** (Observations)
40
41
  - **When capabilities are available** (Activation)
41
42
 
42
43
  An agent runtime that consumes OUI:
44
+
43
45
  - **Discovers** available capabilities at runtime
44
46
  - **Invokes** typed operations and receives structured results
45
47
  - **Observes** application state changes in real-time
@@ -48,12 +50,12 @@ An agent runtime that consumes OUI:
48
50
 
49
51
  Current approaches for AI agents to interact with user interfaces are fundamentally unreliable:
50
52
 
51
- | Approach | Failure Mode |
52
- |----------|-------------|
53
- | Screenshot + Vision Model | Breaks on theme changes, responsive layouts, overlays |
54
- | DOM Scraping | Breaks on framework updates, CSS refactors, dynamic rendering |
55
- | Coordinate Clicking | Breaks on window resize, scroll position, element reflow |
56
- | Accessibility Tree | Incomplete for custom components, missing semantics |
53
+ | Approach | Failure Mode |
54
+ | ------------------------- | ------------------------------------------------------------- |
55
+ | Screenshot + Vision Model | Breaks on theme changes, responsive layouts, overlays |
56
+ | DOM Scraping | Breaks on framework updates, CSS refactors, dynamic rendering |
57
+ | Coordinate Clicking | Breaks on window resize, scroll position, element reflow |
58
+ | Accessibility Tree | Incomplete for custom components, missing semantics |
57
59
 
58
60
  All of these approaches attempt to **infer** application capabilities from implementation details. OUI inverts this: the application **declares** its capabilities explicitly.
59
61
 
@@ -66,13 +68,13 @@ OpenAPI Spec + HTTP Server = any client can consume the API
66
68
  OUI Manifest + UI App = any agent can control the UI
67
69
  ```
68
70
 
69
- | Dimension | OpenAPI | OUI |
70
- |-----------|---------|-----|
71
- | Describes | HTTP endpoints | UI capabilities |
72
- | Consumer | HTTP clients | Agent runtimes |
73
- | Transport | HTTP request/response | Protocol events (WebSocket, postMessage, etc.) |
74
- | Discovery | Static spec document (JSON/YAML) | Dynamic registration (surfaces appear/disappear) |
75
- | Statefulness | Stateless (per-request) | Stateful (observations persist, surfaces have lifecycle) |
71
+ | Dimension | OpenAPI | OUI |
72
+ | ------------ | -------------------------------- | -------------------------------------------------------- |
73
+ | Describes | HTTP endpoints | UI capabilities |
74
+ | Consumer | HTTP clients | Agent runtimes |
75
+ | Transport | HTTP request/response | Protocol events (WebSocket, postMessage, etc.) |
76
+ | Discovery | Static spec document (JSON/YAML) | Dynamic registration (surfaces appear/disappear) |
77
+ | Statefulness | Stateless (per-request) | Stateful (observations persist, surfaces have lifecycle) |
76
78
 
77
79
  An application MAY expose both an OpenAPI spec for its REST API and an OUI manifest for its UI. These serve different consumers: programmatic API clients vs. interactive agent runtimes.
78
80
 
@@ -97,18 +99,18 @@ Field types reference [JSON Schema Draft 2020-12](https://json-schema.org/draft/
97
99
 
98
100
  ## 2. Terminology
99
101
 
100
- | Term | Definition |
101
- |------|-----------|
102
- | **Surface** | A controllable boundary within an application that declares a set of actions and observations. Represents a cohesive unit of functionality (e.g., a page, a feature, a component) that an agent can interact with. |
103
- | **Action** | A single, named operation that an agent can invoke on a surface. Has typed input parameters and a typed return value. Becomes a "tool" in the agent runtime's tool set. |
104
- | **Observation** | A piece of application state that the agent can read. Observations are pushed to the agent when state changes, providing situational awareness without screenshots. |
105
- | **Manifest** | The serializable, schema-only representation of a surface — its metadata, actions (without handlers), and observations. This is what crosses the wire to the agent runtime. |
106
- | **Agent Runtime** | The system that consumes OUI manifests, presents actions as tools to an LLM, and coordinates invocations. Examples: Closure Agent SDK, LangChain, custom orchestrators. |
107
- | **Transport** | The communication layer between a surface and the agent runtime. OUI is transport-agnostic; bindings are defined for WebSocket, postMessage, and direct function call. |
108
- | **Activation** | Conditions under which a surface is available. A surface that is not activated MUST NOT be presented to the agent as available. |
109
- | **Protocol Event** | A typed message exchanged between surfaces and the agent runtime over the transport layer. |
110
- | **Correlation ID** | A unique identifier (`requestId`) that links an action request to its corresponding result, enabling asynchronous request/response over any transport. |
111
- | **Handler** | The implementation function that executes when an action is invoked. Handlers are local to the surface and never cross the wire. |
102
+ | Term | Definition |
103
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
104
+ | **Surface** | A controllable boundary within an application that declares a set of actions and observations. Represents a cohesive unit of functionality (e.g., a page, a feature, a component) that an agent can interact with. |
105
+ | **Action** | A single, named operation that an agent can invoke on a surface. Has typed input parameters and a typed return value. Becomes a "tool" in the agent runtime's tool set. |
106
+ | **Observation** | A piece of application state that the agent can read. Observations are pushed to the agent when state changes, providing situational awareness without screenshots. |
107
+ | **Manifest** | The serializable, schema-only representation of a surface — its metadata, actions (without handlers), and observations. This is what crosses the wire to the agent runtime. |
108
+ | **Agent Runtime** | The system that consumes OUI manifests, presents actions as tools to an LLM, and coordinates invocations. Examples: Closure Agent SDK, LangChain, custom orchestrators. |
109
+ | **Transport** | The communication layer between a surface and the agent runtime. OUI is transport-agnostic; bindings are defined for WebSocket, postMessage, and direct function call. |
110
+ | **Activation** | Conditions under which a surface is available. A surface that is not activated MUST NOT be presented to the agent as available. |
111
+ | **Protocol Event** | A typed message exchanged between surfaces and the agent runtime over the transport layer. |
112
+ | **Correlation ID** | A unique identifier (`requestId`) that links an action request to its corresponding result, enabling asynchronous request/response over any transport. |
113
+ | **Handler** | The implementation function that executes when an action is invoked. Handlers are local to the surface and never cross the wire. |
112
114
 
113
115
  ---
114
116
 
@@ -118,20 +120,21 @@ A Surface is the top-level object in OUI. It represents a self-contained, contro
118
120
 
119
121
  ### 3.1 Schema
120
122
 
121
- | Field | Type | Required | Description |
122
- |-------|------|----------|-------------|
123
- | `id` | `string` | ✅ | Unique identifier for this surface. MUST be unique within the application scope. SHOULD use kebab-case (e.g., `document-editor`, `dataviz-wizard`). |
124
- | `name` | `string` | ✅ | Human-readable display name for the surface. Used in agent UIs and logs. |
125
- | `description` | `string` | ✅ | Natural-language description of what this surface does. This text is included in the agent's LLM context to inform tool selection. SHOULD be concise but descriptive (1–3 sentences). |
126
- | `version` | `string` | | Semantic version of this surface's contract (e.g., `1.0.0`). When present, agent runtimes MAY use this for compatibility checking. |
127
- | `actions` | `OUIAction[]` | ✅ | Array of actions available on this surface. MUST contain at least one action. |
128
- | `observations` | `OUIObservation[]` | | Array of observable state exposed by this surface. MAY be empty or omitted. |
129
- | `activation` | `OUIActivation` | | Conditions under which this surface is active. If omitted, the surface is considered always active when registered. |
130
- | `metadata` | `object` | | Arbitrary key-value pairs for implementation-specific extensions. Agent runtimes SHOULD pass metadata to the LLM context if it aids decision-making. |
123
+ | Field | Type | Required | Description |
124
+ | -------------- | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
125
+ | `id` | `string` | ✅ | Unique identifier for this surface. MUST be unique within the application scope. SHOULD use kebab-case (e.g., `document-editor`, `dataviz-wizard`). |
126
+ | `name` | `string` | ✅ | Human-readable display name for the surface. Used in agent UIs and logs. |
127
+ | `description` | `string` | ✅ | Natural-language description of what this surface does. This text is included in the agent's LLM context to inform tool selection. SHOULD be concise but descriptive (1–3 sentences). |
128
+ | `version` | `string` | | Semantic version of this surface's contract (e.g., `1.0.0`). When present, agent runtimes MAY use this for compatibility checking. |
129
+ | `actions` | `OUIAction[]` | ✅ | Array of actions available on this surface. MUST contain at least one action. |
130
+ | `observations` | `OUIObservation[]` | | Array of observable state exposed by this surface. MAY be empty or omitted. |
131
+ | `activation` | `OUIActivation` | | Conditions under which this surface is active. If omitted, the surface is considered always active when registered. |
132
+ | `metadata` | `object` | | Arbitrary key-value pairs for implementation-specific extensions. Agent runtimes SHOULD pass metadata to the LLM context if it aids decision-making. |
131
133
 
132
134
  ### 3.2 Identifier Requirements
133
135
 
134
136
  Surface IDs:
137
+
135
138
  - MUST match the pattern `^[a-z][a-z0-9-]*[a-z0-9]$` (lowercase letters, digits, hyphens; must start with a letter and end with a letter or digit)
136
139
  - MUST be between 2 and 64 characters in length
137
140
  - MUST be unique within a single application's registration scope
@@ -139,6 +142,7 @@ Surface IDs:
139
142
  ### 3.3 Description Best Practices
140
143
 
141
144
  The `description` field is critical — it is the primary signal an LLM uses to decide whether to interact with a surface. Effective descriptions:
145
+
142
146
  - State the surface's **purpose** (what it lets you do)
143
147
  - Mention the **domain** (what kind of data/entities it works with)
144
148
  - Are **concise** (avoid implementation details)
@@ -187,22 +191,23 @@ An Action represents a single operation an agent can perform on a surface. Each
187
191
 
188
192
  ### 4.1 Schema
189
193
 
190
- | Field | Type | Required | Description |
191
- |-------|------|----------|-------------|
192
- | `id` | `string` | ✅ | Unique action identifier within this surface. Becomes the tool name in the agent runtime. MUST use snake_case (e.g., `create_document`, `set_font_size`). |
193
- | `description` | `string` | ✅ | Natural-language description of what this action does. Included in LLM context. SHOULD clearly state the effect and when to use it. |
194
- | `input` | `JSONSchema` | ✅ | JSON Schema defining the action's input parameters. The agent runtime validates payloads against this schema before dispatching. |
195
- | `output` | `JSONSchema` | | JSON Schema defining the action's return value. When present, agent runtimes MAY validate results. If omitted, the result is still returned to the agent as untyped data. |
196
- | `confirm` | `boolean` | | Default: `false`. If `true`, the agent runtime MUST obtain user confirmation before executing this action. Use for destructive, irreversible, or high-impact operations. |
197
- | `async` | `boolean` | | Default: `false`. If `true`, the action returns immediately with a tracking identifier. The actual result is delivered later via an `action:result` event. |
198
- | `usage` | `string` | | Human-readable hint about when this action is appropriate. Supplements `description` with situational guidance (e.g., "Use after the user has selected a document"). |
199
- | `preconditions` | `string` | | Natural-language description of conditions that should be met before invocation. Expressed for the LLM's benefit, not as executable validation logic. |
200
- | `estimatedDuration` | `string` | | Human-readable duration hint. One of: `"instant"`, `"< 1s"`, `"1-5s"`, `"5-30s"`, `"30-120s"`, `"> 2min"`, or a custom string. Helps agents manage user expectations. |
201
- | `tags` | `string[]` | | Categorization tags (e.g., `["write", "destructive"]`, `["read-only"]`). Agent runtimes MAY use tags for filtering or policy enforcement. |
194
+ | Field | Type | Required | Description |
195
+ | ------------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
196
+ | `id` | `string` | ✅ | Unique action identifier within this surface. Becomes the tool name in the agent runtime. MUST use snake_case (e.g., `create_document`, `set_font_size`). |
197
+ | `description` | `string` | ✅ | Natural-language description of what this action does. Included in LLM context. SHOULD clearly state the effect and when to use it. |
198
+ | `input` | `JSONSchema` | ✅ | JSON Schema defining the action's input parameters. The agent runtime validates payloads against this schema before dispatching. |
199
+ | `output` | `JSONSchema` | | JSON Schema defining the action's return value. When present, agent runtimes MAY validate results. If omitted, the result is still returned to the agent as untyped data. |
200
+ | `confirm` | `boolean` | | Default: `false`. If `true`, the agent runtime MUST obtain user confirmation before executing this action. Use for destructive, irreversible, or high-impact operations. |
201
+ | `async` | `boolean` | | Default: `false`. If `true`, the action returns immediately with a tracking identifier. The actual result is delivered later via an `action:result` event. |
202
+ | `usage` | `string` | | Human-readable hint about when this action is appropriate. Supplements `description` with situational guidance (e.g., "Use after the user has selected a document"). |
203
+ | `preconditions` | `string` | | Natural-language description of conditions that should be met before invocation. Expressed for the LLM's benefit, not as executable validation logic. |
204
+ | `estimatedDuration` | `string` | | Human-readable duration hint. One of: `"instant"`, `"< 1s"`, `"1-5s"`, `"5-30s"`, `"30-120s"`, `"> 2min"`, or a custom string. Helps agents manage user expectations. |
205
+ | `tags` | `string[]` | | Categorization tags (e.g., `["write", "destructive"]`, `["read-only"]`). Agent runtimes MAY use tags for filtering or policy enforcement. |
202
206
 
203
207
  ### 4.2 Identifier Requirements
204
208
 
205
209
  Action IDs:
210
+
206
211
  - MUST match the pattern `^[a-z][a-z0-9_]*[a-z0-9]$` (lowercase letters, digits, underscores; must start with a letter and end with a letter or digit)
207
212
  - MUST be between 2 and 64 characters in length
208
213
  - MUST be unique within a single surface
@@ -212,6 +217,7 @@ Action IDs:
212
217
  The `input` field MUST be a valid JSON Schema object. The top-level schema SHOULD have `type: "object"` with a `properties` map. The `required` array specifies which properties are mandatory.
213
218
 
214
219
  **Requirements:**
220
+
215
221
  - Every property SHOULD include a `description` field to inform the LLM
216
222
  - The schema MUST be self-contained (no external `$ref` references in manifest form)
217
223
  - Default values SHOULD be specified where applicable
@@ -305,16 +311,16 @@ When an action fails, the `action:result` MUST have `success: false` and include
305
311
 
306
312
  #### Standard Error Codes
307
313
 
308
- | Code | Description |
309
- |------|-------------|
310
- | `ACTION_NOT_FOUND` | The specified `actionId` does not exist on this surface |
311
- | `VALIDATION_ERROR` | Input parameters failed schema validation |
312
- | `PRECONDITION_FAILED` | Action preconditions are not met |
313
- | `ACTION_DENIED` | User denied confirmation for a `confirm: true` action |
314
- | `EXECUTION_ERROR` | Handler threw an unhandled exception |
315
- | `TIMEOUT` | Action exceeded its execution timeout |
316
- | `SURFACE_UNAVAILABLE` | The target surface is not currently active |
317
- | `INTERNAL_ERROR` | An unexpected internal error occurred |
314
+ | Code | Description |
315
+ | --------------------- | ------------------------------------------------------- |
316
+ | `ACTION_NOT_FOUND` | The specified `actionId` does not exist on this surface |
317
+ | `VALIDATION_ERROR` | Input parameters failed schema validation |
318
+ | `PRECONDITION_FAILED` | Action preconditions are not met |
319
+ | `ACTION_DENIED` | User denied confirmation for a `confirm: true` action |
320
+ | `EXECUTION_ERROR` | Handler threw an unhandled exception |
321
+ | `TIMEOUT` | Action exceeded its execution timeout |
322
+ | `SURFACE_UNAVAILABLE` | The target surface is not currently active |
323
+ | `INTERNAL_ERROR` | An unexpected internal error occurred |
318
324
 
319
325
  Implementations MAY define additional error codes. Custom codes SHOULD use a namespaced format (e.g., `app:quota_exceeded`).
320
326
 
@@ -327,8 +333,16 @@ Implementations MAY define additional error codes. Custom codes SHOULD use a nam
327
333
  "input": {
328
334
  "type": "object",
329
335
  "properties": {
330
- "title": { "type": "string", "description": "Document title", "minLength": 1 },
331
- "template": { "type": "string", "enum": ["blank", "meeting-notes", "project-brief"], "default": "blank" }
336
+ "title": {
337
+ "type": "string",
338
+ "description": "Document title",
339
+ "minLength": 1
340
+ },
341
+ "template": {
342
+ "type": "string",
343
+ "enum": ["blank", "meeting-notes", "project-brief"],
344
+ "default": "blank"
345
+ }
332
346
  },
333
347
  "required": ["title"]
334
348
  },
@@ -356,16 +370,17 @@ An Observation exposes a piece of application state to the agent runtime. Observ
356
370
 
357
371
  ### 5.1 Schema
358
372
 
359
- | Field | Type | Required | Description |
360
- |-------|------|----------|-------------|
361
- | `id` | `string` | ✅ | Unique identifier within the surface. MUST use snake_case. |
362
- | `description` | `string` | ✅ | Natural-language description of what this observation represents. Included in LLM context. |
363
- | `schema` | `JSONSchema` | ✅ | JSON Schema defining the shape of the observation's value. |
364
- | `updateFrequency` | `string` | | One of `"realtime"`, `"on-change"`, or `"polling"`. Defaults to `"on-change"`. Informs the agent runtime about expected update patterns. |
373
+ | Field | Type | Required | Description |
374
+ | ----------------- | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
375
+ | `id` | `string` | ✅ | Unique identifier within the surface. MUST use snake_case. |
376
+ | `description` | `string` | ✅ | Natural-language description of what this observation represents. Included in LLM context. |
377
+ | `schema` | `JSONSchema` | ✅ | JSON Schema defining the shape of the observation's value. |
378
+ | `updateFrequency` | `string` | | One of `"realtime"`, `"on-change"`, or `"polling"`. Defaults to `"on-change"`. Informs the agent runtime about expected update patterns. |
365
379
 
366
380
  ### 5.2 Identifier Requirements
367
381
 
368
382
  Observation IDs follow the same rules as action IDs:
383
+
369
384
  - MUST match `^[a-z][a-z0-9_]*[a-z0-9]$`
370
385
  - MUST be between 2 and 64 characters
371
386
  - MUST be unique within a single surface
@@ -377,11 +392,11 @@ Observations are state snapshots pushed from the surface to the agent runtime.
377
392
 
378
393
  #### 5.3.1 Update Frequencies
379
394
 
380
- | Frequency | Behavior |
381
- |-----------|----------|
382
- | `realtime` | Value is pushed on every frame/tick/render cycle. Use sparingly — appropriate for continuously changing values (cursor position, audio level). |
383
- | `on-change` | Value is pushed whenever the underlying state changes. This is the default and RECOMMENDED mode for most observations. |
384
- | `polling` | The agent runtime must explicitly request the value. The surface does not push updates proactively. |
395
+ | Frequency | Behavior |
396
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
397
+ | `realtime` | Value is pushed on every frame/tick/render cycle. Use sparingly — appropriate for continuously changing values (cursor position, audio level). |
398
+ | `on-change` | Value is pushed whenever the underlying state changes. This is the default and RECOMMENDED mode for most observations. |
399
+ | `polling` | The agent runtime must explicitly request the value. The surface does not push updates proactively. |
385
400
 
386
401
  #### 5.3.2 Push Model (Default)
387
402
 
@@ -420,7 +435,10 @@ Pull-mode observations are useful for expensive-to-compute state that shouldn't
420
435
  "documentId": { "type": "string" },
421
436
  "title": { "type": "string" },
422
437
  "wordCount": { "type": "integer" },
423
- "selectedText": { "type": "string", "description": "Currently selected text, empty if no selection" },
438
+ "selectedText": {
439
+ "type": "string",
440
+ "description": "Currently selected text, empty if no selection"
441
+ },
424
442
  "cursorPosition": {
425
443
  "type": "object",
426
444
  "properties": {
@@ -428,7 +446,10 @@ Pull-mode observations are useful for expensive-to-compute state that shouldn't
428
446
  "column": { "type": "integer" }
429
447
  }
430
448
  },
431
- "isDirty": { "type": "boolean", "description": "True if document has unsaved changes" }
449
+ "isDirty": {
450
+ "type": "boolean",
451
+ "description": "True if document has unsaved changes"
452
+ }
432
453
  }
433
454
  },
434
455
  "updateFrequency": "on-change"
@@ -443,13 +464,13 @@ Activation defines the conditions under which a surface is available to the agen
443
464
 
444
465
  ### 6.1 Schema
445
466
 
446
- | Field | Type | Required | Description |
447
- |-------|------|----------|-------------|
448
- | `routes` | `string \| string[]` | | URL path pattern(s) where this surface is active. Supports glob patterns (e.g., `/documents/*`, `/settings/**`). |
449
- | `entity` | `object` | | An entity that must be loaded/present for this surface to activate. |
450
- | `entity.type` | `string` | ✅ (if `entity` present) | The entity type (e.g., `"document"`, `"project"`, `"user-profile"`). |
451
- | `entity.id` | `string` | | A specific entity ID. If omitted, any entity of the given type satisfies the condition. |
452
- | `condition` | `string` | | Free-form natural-language description of additional activation conditions. Not executable — serves as documentation for the agent runtime and developers. |
467
+ | Field | Type | Required | Description |
468
+ | ------------- | -------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
469
+ | `routes` | `string \| string[]` | | URL path pattern(s) where this surface is active. Supports glob patterns (e.g., `/documents/*`, `/settings/**`). |
470
+ | `entity` | `object` | | An entity that must be loaded/present for this surface to activate. |
471
+ | `entity.type` | `string` | ✅ (if `entity` present) | The entity type (e.g., `"document"`, `"project"`, `"user-profile"`). |
472
+ | `entity.id` | `string` | | A specific entity ID. If omitted, any entity of the given type satisfies the condition. |
473
+ | `condition` | `string` | | Free-form natural-language description of additional activation conditions. Not executable — serves as documentation for the agent runtime and developers. |
453
474
 
454
475
  ### 6.2 Evaluation Rules
455
476
 
@@ -462,16 +483,17 @@ Activation defines the conditions under which a surface is available to the agen
462
483
 
463
484
  Route patterns follow simplified glob syntax:
464
485
 
465
- | Pattern | Matches |
466
- |---------|---------|
467
- | `/documents` | Exactly `/documents` |
468
- | `/documents/*` | `/documents/abc` but not `/documents/abc/edit` |
469
- | `/documents/**` | `/documents/abc`, `/documents/abc/edit`, `/documents/abc/edit/v2` |
470
- | `/users/*/settings` | `/users/123/settings` |
486
+ | Pattern | Matches |
487
+ | ------------------- | ----------------------------------------------------------------- |
488
+ | `/documents` | Exactly `/documents` |
489
+ | `/documents/*` | `/documents/abc` but not `/documents/abc/edit` |
490
+ | `/documents/**` | `/documents/abc`, `/documents/abc/edit`, `/documents/abc/edit/v2` |
491
+ | `/users/*/settings` | `/users/123/settings` |
471
492
 
472
493
  ### 6.4 Dynamic Activation
473
494
 
474
495
  Applications with complex activation logic SHOULD manage surface lifecycle explicitly:
496
+
475
497
  - Register the surface (via `surface:register`) when conditions are met
476
498
  - Deregister (via `surface:deregister`) when conditions are no longer met
477
499
 
@@ -499,13 +521,13 @@ The OUI Protocol defines the message exchange between agent runtimes and surface
499
521
 
500
522
  All communication consists of typed protocol events. Each event has a `type` string and a `payload` object.
501
523
 
502
- | Event Type | Direction | Description |
503
- |-----------|-----------|-------------|
504
- | `surface:register` | Surface → Runtime | A surface is announcing itself as available |
505
- | `surface:deregister` | Surface → Runtime | A surface is announcing it is no longer available |
506
- | `action:request` | Runtime → Surface | The agent is invoking an action |
507
- | `action:result` | Surface → Runtime | The surface is returning an action's result |
508
- | `observation:update` | Surface → Runtime | An observation value has changed |
524
+ | Event Type | Direction | Description |
525
+ | --------------------- | ----------------- | ------------------------------------------------------------- |
526
+ | `surface:register` | Surface → Runtime | A surface is announcing itself as available |
527
+ | `surface:deregister` | Surface → Runtime | A surface is announcing it is no longer available |
528
+ | `action:request` | Runtime → Surface | The agent is invoking an action |
529
+ | `action:result` | Surface → Runtime | The surface is returning an action's result |
530
+ | `observation:update` | Surface → Runtime | An observation value has changed |
509
531
  | `observation:request` | Runtime → Surface | The agent is requesting a polling observation's current value |
510
532
 
511
533
  ### 7.2 Surface Registration and Deregistration
@@ -533,6 +555,7 @@ When a surface becomes active, it MUST send a `surface:register` event:
533
555
  ```
534
556
 
535
557
  **Requirements:**
558
+
536
559
  - The `surface` field contains the complete manifest (schema only, no handlers)
537
560
  - The agent runtime MUST acknowledge registration by making the surface's actions available as tools
538
561
  - If a surface with the same `id` is already registered, the new registration MUST replace the old one (hot-reload semantics)
@@ -552,6 +575,7 @@ When a surface becomes inactive or is destroyed, it MUST send a `surface:deregis
552
575
  ```
553
576
 
554
577
  **Requirements:**
578
+
555
579
  - The agent runtime MUST remove the surface's actions from the available tool set
556
580
  - Any pending action requests targeting this surface MUST be resolved with error code `SURFACE_UNAVAILABLE`
557
581
  - Observation state for this surface MUST be discarded
@@ -579,6 +603,7 @@ When the agent invokes an action, the runtime sends an `action:request`:
579
603
  ```
580
604
 
581
605
  **Requirements:**
606
+
582
607
  - `requestId` MUST be a globally unique string. UUID v4 is RECOMMENDED.
583
608
  - `params` MUST conform to the action's declared `input` schema
584
609
  - The agent runtime SHOULD validate `params` before sending; the surface MUST validate upon receipt
@@ -622,11 +647,45 @@ When the agent invokes an action, the runtime sends an `action:request`:
622
647
  ```
623
648
 
624
649
  **Requirements:**
650
+
625
651
  - The `requestId` in the result MUST exactly match the request's `requestId`
626
652
  - Exactly one `action:result` MUST be sent for each `action:request` (for sync actions)
627
653
  - For async actions: one immediate acknowledgment result, then one final result (both with the same `requestId`)
628
654
  - If `success` is `false`, the `error` field MUST be present
629
655
  - If `success` is `true`, the `error` field MUST NOT be present
656
+ - An async action's acknowledgment result MUST set `interim: true`; its final result MUST set `interim: false`
657
+
658
+ #### 7.3.4 The Client's State After an Action
659
+
660
+ A result MAY carry the client's state once the action's effects settled:
661
+
662
+ | Field | Type | Description |
663
+ | -------------- | --------------------------------------------- | ------------------------------------------------------------- |
664
+ | `surfaces` | `OUISurface[]` | Every surface active on the client after the action |
665
+ | `observations` | `{ [surfaceId]: { [observationId]: value } }` | The latest observation values of those surfaces |
666
+ | `settled` | `boolean` | `false` if the client's deadline passed before its UI settled |
667
+
668
+ An action can change what the agent may do next: navigating unmounts one
669
+ page's surfaces and mounts another's. A client that reports `surfaces` lets
670
+ the agent act on the page the action led to, rather than on the capability set
671
+ it had before.
672
+
673
+ A client SHOULD wait until its UI settles before answering: no surface mounted
674
+ or unmounted and no observation changed for a quiet window, and no known work
675
+ (such as a route's code loading) still pending. It MUST answer by a deadline
676
+ regardless, with `settled: false`.
677
+
678
+ #### 7.3.5 Client Snapshot
679
+
680
+ A client MAY provide its surfaces and observations to the agent runtime as a
681
+ snapshot (`{ surfaces, observations }`), for example with each request the
682
+ user makes of the agent, instead of through registration events (§7.2). A
683
+ runtime that works from snapshots needs no registry of its own, and cannot
684
+ hold a registration the client no longer has.
685
+
686
+ A client's snapshot is authoritative for that client. A runtime MUST NOT merge
687
+ snapshots from different clients of the same user into one capability set:
688
+ each client can act only on what it has mounted.
630
689
 
631
690
  ### 7.4 Observation Updates
632
691
 
@@ -668,6 +727,7 @@ When the agent invokes an action, the runtime sends an `action:request`:
668
727
  The surface responds with a standard `observation:update` event.
669
728
 
670
729
  **Requirements:**
730
+
671
731
  - The `value` MUST conform to the observation's declared `schema`
672
732
  - Surfaces SHOULD batch rapid observation updates (e.g., debounce to max 10 updates/second for `on-change` observations)
673
733
  - The agent runtime MUST handle out-of-order updates gracefully — always use the latest `timestamp`
@@ -676,14 +736,15 @@ The surface responds with a standard `observation:update` event.
676
736
 
677
737
  Timeouts prevent resource leaks and provide predictable failure modes.
678
738
 
679
- | Scenario | Default Timeout | Configurable |
680
- |----------|----------------|--------------|
681
- | Synchronous action execution | 30,000 ms | Yes |
682
- | Action acknowledgment (async) | 5,000 ms | Yes |
683
- | Surface registration response | 10,000 ms | Yes |
684
- | Observation pull request | 5,000 ms | Yes |
739
+ | Scenario | Default Timeout | Configurable |
740
+ | ----------------------------- | --------------- | ------------ |
741
+ | Synchronous action execution | 30,000 ms | Yes |
742
+ | Action acknowledgment (async) | 5,000 ms | Yes |
743
+ | Surface registration response | 10,000 ms | Yes |
744
+ | Observation pull request | 5,000 ms | Yes |
685
745
 
686
746
  When a timeout expires:
747
+
687
748
  - The agent runtime MUST generate a synthetic `action:result` with `success: false` and error code `TIMEOUT`
688
749
  - The agent runtime MUST NOT retry automatically (retry policy is the agent's decision)
689
750
  - The surface MAY still complete the operation; late results SHOULD be silently discarded by the runtime
@@ -693,6 +754,7 @@ When a timeout expires:
693
754
  #### 7.6.1 Transport-Level Errors
694
755
 
695
756
  If the transport connection is lost:
757
+
696
758
  - All registered surfaces MUST be considered deregistered
697
759
  - All pending action requests MUST be resolved with error code `SURFACE_UNAVAILABLE`
698
760
  - On reconnection, surfaces MUST re-register
@@ -700,6 +762,7 @@ If the transport connection is lost:
700
762
  #### 7.6.2 Protocol-Level Errors
701
763
 
702
764
  If a protocol event is malformed:
765
+
703
766
  - The receiving party MUST ignore the event
704
767
  - The receiving party SHOULD log a warning
705
768
  - The receiving party MUST NOT crash or close the connection
@@ -739,7 +802,7 @@ interface OUITransport {
739
802
  disconnect(): void;
740
803
 
741
804
  /** Current connection state */
742
- readonly state: 'disconnected' | 'connecting' | 'connected';
805
+ readonly state: "disconnected" | "connecting" | "connected";
743
806
  }
744
807
  ```
745
808
 
@@ -855,6 +918,7 @@ interface DirectTransport {
855
918
  #### 8.4.2 Synchronous vs. Asynchronous
856
919
 
857
920
  Even in direct-call mode:
921
+
858
922
  - Action handlers MUST be invoked asynchronously (via `await` or microtask)
859
923
  - The protocol's event-based semantics are preserved — the runtime still receives `action:result` events
860
924
  - This ensures behavioral consistency regardless of transport
@@ -862,6 +926,7 @@ Even in direct-call mode:
862
926
  #### 8.4.3 Testing
863
927
 
864
928
  Direct function call transport is the RECOMMENDED approach for unit and integration testing of surfaces. It allows tests to:
929
+
865
930
  - Register a surface
866
931
  - Send action requests
867
932
  - Assert on action results
@@ -871,16 +936,16 @@ All without network overhead or browser infrastructure.
871
936
 
872
937
  ### 8.5 Transport Selection
873
938
 
874
- | Scenario | Recommended Transport |
875
- |----------|----------------------|
876
- | Web app ↔ remote agent server | WebSocket |
877
- | Iframe plugin ↔ host app | postMessage |
878
- | Web worker ↔ main thread | postMessage |
879
- | Same-process SDK integration | Direct function call |
880
- | Server-side rendering | Direct function call |
881
- | Automated testing | Direct function call |
882
- | Electron main ↔ renderer | postMessage or WebSocket |
883
- | React Native | WebSocket |
939
+ | Scenario | Recommended Transport |
940
+ | ----------------------------- | ------------------------ |
941
+ | Web app ↔ remote agent server | WebSocket |
942
+ | Iframe plugin ↔ host app | postMessage |
943
+ | Web worker ↔ main thread | postMessage |
944
+ | Same-process SDK integration | Direct function call |
945
+ | Server-side rendering | Direct function call |
946
+ | Automated testing | Direct function call |
947
+ | Electron main ↔ renderer | postMessage or WebSocket |
948
+ | React Native | WebSocket |
884
949
 
885
950
  ---
886
951
 
@@ -907,17 +972,18 @@ OUI surfaces expose application capabilities to external agent runtimes. Securit
907
972
 
908
973
  The `confirm: true` flag is the primary mechanism for protecting high-impact operations:
909
974
 
910
- | Operation Type | Confirm Recommended |
911
- |---------------|-------------------|
912
- | Read-only / query | No |
913
- | Create / add | Situational |
914
- | Update / modify | Situational |
915
- | Delete / destroy | Yes |
916
- | External side effects (send email, publish) | Yes |
917
- | Financial transactions | Yes |
918
- | Permission changes | Yes |
975
+ | Operation Type | Confirm Recommended |
976
+ | ------------------------------------------- | ------------------- |
977
+ | Read-only / query | No |
978
+ | Create / add | Situational |
979
+ | Update / modify | Situational |
980
+ | Delete / destroy | Yes |
981
+ | External side effects (send email, publish) | Yes |
982
+ | Financial transactions | Yes |
983
+ | Permission changes | Yes |
919
984
 
920
985
  Agent runtimes MUST NOT bypass confirmation. The confirmation prompt MUST clearly describe:
986
+
921
987
  - Which action is being invoked
922
988
  - What parameters are being passed
923
989
  - The expected effect (from the action's `description`)
@@ -927,6 +993,7 @@ Agent runtimes MUST NOT bypass confirmation. The confirmation prompt MUST clearl
927
993
  #### 9.3.1 Surface Scoping
928
994
 
929
995
  Applications SHOULD scope surfaces narrowly:
996
+
930
997
  - One surface per feature or page (not one monolithic surface for the entire app)
931
998
  - Only expose actions relevant to the surface's domain
932
999
  - Prefer many small surfaces over few large ones
@@ -945,11 +1012,11 @@ Applications SHOULD scope surfaces narrowly:
945
1012
 
946
1013
  ### 9.4 Transport Security
947
1014
 
948
- | Transport | Security Requirement |
949
- |-----------|---------------------|
950
- | WebSocket | MUST use TLS (`wss://`) in production. SHOULD authenticate the connection (e.g., via token in initial handshake). |
951
- | postMessage | MUST validate `origin`. MUST NOT use `targetOrigin: "*"` in production. |
952
- | Direct call | Inherits the process's security context. No additional requirements. |
1015
+ | Transport | Security Requirement |
1016
+ | ----------- | ----------------------------------------------------------------------------------------------------------------- |
1017
+ | WebSocket | MUST use TLS (`wss://`) in production. SHOULD authenticate the connection (e.g., via token in initial handshake). |
1018
+ | postMessage | MUST validate `origin`. MUST NOT use `targetOrigin: "*"` in production. |
1019
+ | Direct call | Inherits the process's security context. No additional requirements. |
953
1020
 
954
1021
  ### 9.5 Rate Limiting
955
1022
 
@@ -960,6 +1027,7 @@ Applications SHOULD scope surfaces narrowly:
960
1027
  ### 9.6 Capability Enumeration
961
1028
 
962
1029
  The manifest is readable by the agent runtime. This means:
1030
+
963
1031
  - Do not include security-sensitive information in action descriptions
964
1032
  - Do not expose admin-only actions to non-admin agent sessions
965
1033
  - Consider per-role surface variants if different users have different capabilities
@@ -1026,12 +1094,12 @@ Surfaces and runtimes SHOULD declare which spec version they implement. Compatib
1026
1094
 
1027
1095
  The specification provides explicit extension mechanisms:
1028
1096
 
1029
- | Extension Point | Mechanism |
1030
- |----------------|-----------|
1031
- | Surface metadata | The `metadata` field on `OUISurface` accepts arbitrary key-value pairs |
1032
- | Custom error codes | Namespaced codes (e.g., `app:custom_error`) alongside standard codes |
1097
+ | Extension Point | Mechanism |
1098
+ | ---------------------- | ------------------------------------------------------------------------------------------------ |
1099
+ | Surface metadata | The `metadata` field on `OUISurface` accepts arbitrary key-value pairs |
1100
+ | Custom error codes | Namespaced codes (e.g., `app:custom_error`) alongside standard codes |
1033
1101
  | Custom protocol events | Implementations MAY define additional event types prefixed with `x-` (e.g., `x-analytics:track`) |
1034
- | Transport extensions | Custom transports that implement the `OUITransport` interface |
1102
+ | Transport extensions | Custom transports that implement the `OUITransport` interface |
1035
1103
 
1036
1104
  Extensions MUST NOT conflict with the standard protocol. Receivers that encounter unknown event types MUST silently ignore them.
1037
1105
 
@@ -1053,20 +1121,20 @@ Until the compliance suite is available, implementations SHOULD self-verify agai
1053
1121
 
1054
1122
  ```typescript
1055
1123
  type OUIProtocolEvent =
1056
- | { type: 'surface:register'; payload: OUISurfaceRegistration }
1057
- | { type: 'surface:deregister'; payload: OUISurfaceDeregistration }
1058
- | { type: 'action:request'; payload: OUIActionRequest }
1059
- | { type: 'action:result'; payload: OUIActionResult }
1060
- | { type: 'observation:update'; payload: OUIObservationUpdate }
1061
- | { type: 'observation:request'; payload: OUIObservationRequest };
1124
+ | { type: "surface:register"; payload: OUISurfaceRegistration }
1125
+ | { type: "surface:deregister"; payload: OUISurfaceDeregistration }
1126
+ | { type: "action:request"; payload: OUIActionRequest }
1127
+ | { type: "action:result"; payload: OUIActionResult }
1128
+ | { type: "observation:update"; payload: OUIObservationUpdate }
1129
+ | { type: "observation:request"; payload: OUIObservationRequest };
1062
1130
  ```
1063
1131
 
1064
1132
  ### OUISurfaceRegistration
1065
1133
 
1066
1134
  ```typescript
1067
1135
  {
1068
- surface: OUISurface; // Complete manifest
1069
- timestamp: number; // Unix epoch milliseconds
1136
+ surface: OUISurface; // Complete manifest
1137
+ timestamp: number; // Unix epoch milliseconds
1070
1138
  }
1071
1139
  ```
1072
1140
 
@@ -1074,7 +1142,7 @@ type OUIProtocolEvent =
1074
1142
 
1075
1143
  ```typescript
1076
1144
  {
1077
- surfaceId: string; // ID of surface being removed
1145
+ surfaceId: string; // ID of surface being removed
1078
1146
  timestamp: number;
1079
1147
  }
1080
1148
  ```
@@ -1083,10 +1151,10 @@ type OUIProtocolEvent =
1083
1151
 
1084
1152
  ```typescript
1085
1153
  {
1086
- requestId: string; // UUID v4 recommended
1087
- surfaceId: string; // Target surface
1088
- actionId: string; // Target action
1089
- params: object; // Input conforming to action's input schema
1154
+ requestId: string; // UUID v4 recommended
1155
+ surfaceId: string; // Target surface
1156
+ actionId: string; // Target action
1157
+ params: object; // Input conforming to action's input schema
1090
1158
  timestamp: number;
1091
1159
  }
1092
1160
  ```
@@ -1114,7 +1182,7 @@ type OUIProtocolEvent =
1114
1182
  {
1115
1183
  surfaceId: string;
1116
1184
  observationId: string;
1117
- value: unknown; // Conforms to observation's schema
1185
+ value: unknown; // Conforms to observation's schema
1118
1186
  timestamp: number;
1119
1187
  }
1120
1188
  ```
@@ -1273,8 +1341,14 @@ This appendix shows a full OUI manifest for a todo application, demonstrating al
1273
1341
  "schema": {
1274
1342
  "type": "object",
1275
1343
  "properties": {
1276
- "status": { "type": "string", "enum": ["all", "active", "completed"] },
1277
- "priority": { "type": "string", "enum": ["all", "low", "medium", "high"] }
1344
+ "status": {
1345
+ "type": "string",
1346
+ "enum": ["all", "active", "completed"]
1347
+ },
1348
+ "priority": {
1349
+ "type": "string",
1350
+ "enum": ["all", "low", "medium", "high"]
1351
+ }
1278
1352
  }
1279
1353
  },
1280
1354
  "updateFrequency": "on-change"
@@ -1308,16 +1382,16 @@ This appendix shows a full OUI manifest for a todo application, demonstrating al
1308
1382
 
1309
1383
  ## Appendix C: Relationship to Existing Standards
1310
1384
 
1311
- | Standard | Relationship to OUI |
1312
- |----------|-------------------|
1313
- | [OpenAPI](https://spec.openapis.org/oas/latest.html) | Complementary. OpenAPI describes HTTP APIs; OUI describes UI capabilities. An app may expose both. |
1314
- | [JSON Schema](https://json-schema.org/) | Foundation. OUI uses JSON Schema for all input/output/observation type definitions. |
1315
- | [JSON-RPC](https://www.jsonrpc.org/specification) | Inspiration. OUI's request/result correlation is similar to JSON-RPC's `id` field, but OUI adds lifecycle (registration, observations). |
1316
- | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) | Inspiration. LSP's capability negotiation and typed messages influenced OUI's protocol design. |
1317
- | [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) | Orthogonal. Web Components define UI encapsulation at the DOM level; OUI defines semantic capability exposure at the agent level. |
1318
- | [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) | Related. MCP defines tools/resources for LLMs in a server context. OUI is specifically designed for UI surfaces with lifecycle, activation, and real-time observations. |
1319
- | [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/) | Complementary. ARIA describes UI semantics for assistive technology; OUI describes UI capabilities for agent technology. |
1385
+ | Standard | Relationship to OUI |
1386
+ | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1387
+ | [OpenAPI](https://spec.openapis.org/oas/latest.html) | Complementary. OpenAPI describes HTTP APIs; OUI describes UI capabilities. An app may expose both. |
1388
+ | [JSON Schema](https://json-schema.org/) | Foundation. OUI uses JSON Schema for all input/output/observation type definitions. |
1389
+ | [JSON-RPC](https://www.jsonrpc.org/specification) | Inspiration. OUI's request/result correlation is similar to JSON-RPC's `id` field, but OUI adds lifecycle (registration, observations). |
1390
+ | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) | Inspiration. LSP's capability negotiation and typed messages influenced OUI's protocol design. |
1391
+ | [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) | Orthogonal. Web Components define UI encapsulation at the DOM level; OUI defines semantic capability exposure at the agent level. |
1392
+ | [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) | Related. MCP defines tools/resources for LLMs in a server context. OUI is specifically designed for UI surfaces with lifecycle, activation, and real-time observations. |
1393
+ | [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/) | Complementary. ARIA describes UI semantics for assistive technology; OUI describes UI capabilities for agent technology. |
1320
1394
 
1321
1395
  ---
1322
1396
 
1323
- *End of specification.*
1397
+ _End of specification._