Skip to content

UIAP Agent Cognition

FieldValue
StatusDraft
Version0.1
Date2026-03-29
DependenciesUIAP Core
EditorsPatrick

This specification extends UIAP with a read-only Cognition Layer for agents.

UIAP Agent Cognition v0.1 defines:

  • a global Entity Schema as data model
  • a Scope Context for currently visible or explicitly exposed records
  • a Navigation Map for spatial orientation within the app
  • an optional, limited Scope Query mechanism
  • a standardized Entity Reference that MAY be reused by Action/Runtime specifications

UIAP Agent Cognition v0.1 does not define:

  • mutations on data
  • direct database or backend access
  • free, unbound ad-hoc queries
  • relational joins across multiple entity types
  • detailed Action execution semantics

Mutations remain the responsibility of UI Actions or other specifications defined for that purpose. This extension provides only additional, controlled context.

The key words MUST, MUST NOT, SHOULD, MAY in this document are to be interpreted as described in RFC 2119 and BCP 14, when and only when they appear in ALL CAPS.

  1. Read-only by design. Agent Cognition provides context, not mutation.
  2. Schema global, records restrictive. The Entity Schema MAY be known session-wide; concrete records SHOULD by default only be delivered within the current scope.
  3. Secure default. If nothing else is declared, recordAccess = "visible_only" applies to records.
  4. UI-bound. Agent Cognition supplements UI understanding; it does not replace an app API.
  5. App-controlled. The app decides which schemas, fields, counts, and records are available.
  6. Progressive Enhancement. Schema, Navigation, Context, and Query MAY be provided independently of each other.
  7. No hidden full API. Scope Queries MUST remain limited, read-only, and bound to a scope or route.

The Entity Schema describes which business objects the app knows and which fields those objects have.

Examples:

  • contact
  • deal
  • member
  • activity

The schema describes structure, not necessarily visible values.

The Scope Context describes which entities are relevant in the current scope. A scope MAY be, for example:

  • a route such as /contacts
  • a list such as contacts-list
  • an embedded region such as dashboard-deals

The Scope Context contains by default only records that are visible in the current scope or explicitly exposed.

The Navigation Map describes where in the app which entity types typically live and how an agent can navigate there.

It is an orientation aid, not a mutation.

A Scope Query is an optional, limited mechanism for reading additional records within a declared scope or route.

A Scope Query is:

  • read-only
  • limited
  • policy-controlled
  • scope- or route-bound

A Scope Query is NOT:

  • a general database access
  • a free query language
  • a join engine
type EntityType = string; // z. B. "contact" oder "deal"
type EntityId = string; // app-definiert, innerhalb des EntityType eindeutig
type FieldName = string; // z. B. "name", "company", "status"
type ScopeId = string; // z. B. "contacts-list"
type RouteId = string; // z. B. "contacts"
type Revision = string; // app-definiert für Change Detection
type CognitionSurface = "schema" | "navigation" | "context";
type RecordAccessMode =
| "visible_only" // nur aktuell sichtbare Datensätze
| "scope_window" // aktueller logischer Listenbereich / Fenster
| "queryable"; // begrenzte read-only Queries erlaubt
type FieldType =
| "string"
| "number"
| "boolean"
| "date"
| "datetime"
| "enum"
| "currency"
| "email"
| "phone"
| "url"
| "json";
type FieldExposure =
| "readable" // Werte DÜRFEN geliefert werden
| "redacted" // Werte KÖNNEN maskiert oder ausgelassen werden
| "declared_only"; // Feld ist Teil des Schemas, Werte DÜRFEN nicht geliefert werden
type RecordSource =
| "visible"
| "scope_window"
| "query";
type FilterOp =
| "eq"
| "neq"
| "in"
| "contains"
| "starts_with"
| "gt"
| "gte"
| "lt"
| "lte"
| "exists";
interface EntityRef {
type: EntityType;
id: EntityId;
stableId?: string; // optionaler UI-Bezug, falls vorhanden
primaryText?: string; // z. B. "Elena Rossi"
}
interface EntityFieldSchema {
type: FieldType;
label?: string;
description?: string;
enumValues?: string[];
exposure?: FieldExposure; // Default: "readable"
searchable?: boolean;
sortable?: boolean;
}
interface EntityRelation {
field: FieldName; // z. B. "contactId"
targetEntity: EntityType; // z. B. "contact"
kind: "belongs_to" | "has_one" | "has_many" | string;
}

relations are in v0.1 primarily semantic declarations. They describe that a field references another entity but do not define their own traversal language.

interface EntitySchema {
label?: string;
primaryField?: FieldName;
recordAccess?: RecordAccessMode; // Default: "visible_only"
fields: Record<FieldName, EntityFieldSchema>;
relations?: EntityRelation[];
actions?: string[]; // semantische oder konkrete Action-IDs
}
interface EntitySchemaDocument {
revision?: Revision;
entities: Record<EntityType, EntitySchema>;
}
interface EntityRecord {
ref: EntityRef;
fields: Record<FieldName, unknown>;
redactions?: Record<FieldName, "masked" | "withheld" | "omitted">;
source: RecordSource;
actions?: string[];
}
interface SortSpec {
field: FieldName;
direction?: "asc" | "desc"; // Default: "asc"
}
interface FilterSpec {
field: FieldName;
op: FilterOp;
value?: string | number | boolean | Array<string | number | boolean>;
}
interface ScopeCollection {
entity: EntityType;
access: RecordAccessMode;
visibleCount: number; // Anzahl aktuell sichtbarer Datensätze im Scope
totalCount?: number; // optional; nur wenn die App dies freigibt
offset?: number; // bei virtuellen Listen/Fenstern
limit?: number; // bei virtuellen Listen/Fenstern
hasMore?: boolean;
filters?: FilterSpec[];
sort?: SortSpec[];
items: EntityRecord[];
}
interface ScopeContext {
revision?: Revision;
scopeId: ScopeId;
routeId?: RouteId;
routePath?: string;
routeLabel?: string;
collections: ScopeCollection[];
}
interface RouteActivation {
kind: "path" | "action" | "app_defined";
value: string; // z. B. "/contacts" oder "nav.contacts.open"
}
interface NavigationRoute {
id: RouteId;
path: string; // z. B. "/contacts" oder "/contacts/:id"
label?: string;
entities?: EntityType[];
capabilities?: string[];
activation?: RouteActivation;
}
interface NavigationMap {
revision?: Revision;
routes: NavigationRoute[];
}

The Navigation Map is descriptive. It does not define its own mutation or navigation channel.

If an agent wants to switch to a route, this SHOULD happen via the existing Action Runtime.

Recommended mapping:

  • activation.kind = "path" — the consumer SHOULD execute an existing navigation action, typically nav.navigate, addressing the route via NavigationRoute.id, NavigationRoute.path, or an app-defined runtime binding.
  • activation.kind = "action" — the consumer SHOULD execute the declared action referenced in activation.value via action.request.
  • activation.kind = "app_defined" — the concrete execution is app-specific and MUST only occur if a matching declared capability or action is present.

Agent Cognition deliberately does not define a separate message type such as uiap.cognition.navigate.

interface CognitionBootstrap {
revision?: Revision;
schema?: EntitySchemaDocument;
navigation?: NavigationMap;
context?: ScopeContext;
}

Agent Cognition clearly distinguishes between:

  • Schema knowledge: Which entities and fields exist?
  • Record knowledge: Which concrete records and field values are currently available?

These two levels MUST be considered separately.

If an app declares nothing else:

  • The schema MAY be delivered in full.
  • Records MAY only be delivered within the current scope and only if visible.
  • recordAccess is implicitly visible_only.
  • Only currently visible records MAY be delivered.
  • Querying outside the visible range MUST NOT occur.
  • An agent SHOULD in this case use the Navigation Map to switch to the relevant route or list.
  • The app MAY deliver a limited logical list range in addition to the visible viewport.
  • Typical cases are virtualization, pagination, or lazy loading.
  • Filtering outside the already declared scope logic MUST NOT occur freely.
  • The app MAY allow limited read-only queries.
  • Queries MUST be bound to a scope or route.
  • Queries MUST respect limits, redaction, and policy rules.

This specification uses the Extension ID:

"uiap.cognition"

Extension-specific handshake data is transported in the envelope field ext.

interface CognitionInitializeExt {
bootstrapDelivery?: "inline" | "deferred" | "none";
requestedSurfaces?: CognitionSurface[]; // Default: ["schema", "navigation", "context"]
requestedQuery?: boolean; // Default: false
}
interface CognitionInitializedExt {
bootstrapDelivery: "inline" | "deferred" | "none";
enabledSurfaces: CognitionSurface[];
queryEnabled?: boolean;
maxQueryLimit?: number; // empfohlen: <= 50
bootstrap?: CognitionBootstrap; // nur bei bootstrapDelivery="inline"
}
  1. If uiap.cognition was not negotiated, no uiap.cognition.* messages MUST be processed.
  2. If bootstrapDelivery = "inline" is selected, bootstrap MAY be included directly in session.initialized.ext["uiap.cognition"].
  3. If bootstrapDelivery = "deferred" is selected, the agent SHOULD use uiap.cognition.bootstrap.get.
  4. requestedSurfaces SHOULD default to ["schema", "navigation", "context"] when absent.
  5. queryEnabled MUST be explicitly true before uiap.cognition.query MAY be used.

Requests Cognition data after session establishment.

interface CognitionBootstrapGetPayload {
include?: CognitionSurface[]; // Default: alle aktivierten Surfaces
}
interface CognitionBootstrapPayload extends CognitionBootstrap {}
  • If include is absent, all enabled surfaces MUST be delivered.
  • Surfaces that are not enabled MUST NOT be delivered.
  • If only non-enabled surfaces are requested, an error with code="capability_unavailable" or a namespaced Cognition error MUST be returned.

Reports changed Cognition data.

interface CognitionChangedPayload {
revision: Revision;
changed: CognitionSurface[];
reason?: "route_change" | "data_change" | "selection_change" | "configuration" | string;
bootstrap: CognitionBootstrap;
}
  • In v0.1, uiap.cognition.changed MUST deliver a full replacement object for each surface listed in changed.
  • Receivers SHOULD fully replace the affected surfaces.
  • uiap.cognition.changed is intended for coarse-grained semantic changes, not for high-frequency UI churn at the element level.
  • Fine-grained UI changes SHOULD continue to be handled primarily via web.state.delta or other profile-specific delta mechanisms.
  • Publishers SHOULD batch multiple fine-grained changes and only emit uiap.cognition.changed when schema, navigation, or scope context have changed in a semantically relevant way.
  • For large collections, context.collections[].items SHOULD remain limited to the currently visible or declared window range.
  • Query results are considered transient response data in v0.1 and MUST NOT be automatically republished via uiap.cognition.changed.
  • Typical triggers are route changes, filter/sort changes, collection membership changes, or configuration changes.

Note: Delta-based Cognition updates MAY be added as a separate message type in a future version.


Executes a limited read-only query within a scope or route.

interface CognitionQueryPayload {
entity: EntityType;
scopeId?: ScopeId; // Default: aktueller Scope
routeId?: RouteId; // optionaler Route-Bezug
filters?: FilterSpec[]; // implizites AND
sort?: SortSpec[];
offset?: number; // Default: 0
limit?: number; // Default: app-definiert
fields?: FieldName[]; // optionaler Feld-Subset
}
interface CognitionQueryResultPayload {
entity: EntityType;
scopeId?: ScopeId;
routeId?: RouteId;
offset: number;
limit: number;
returned: number;
totalCount?: number;
hasMore?: boolean;
items: EntityRecord[];
}
  1. uiap.cognition.query MUST only be used when queryEnabled = true.
  2. Queries MUST remain bound to an active scope or a declared route.
  3. Queries MUST refer to exactly one entity type.
  4. Queries MUST NOT contain joins, transitive relation resolution, or free script expressions.
  5. If the recordAccess of the relevant entity type or scope collection is not at least queryable, the request MUST fail.
  6. The app MUST enforce an effective maximum value for limit.
  7. Fields with exposure = "declared_only" MUST NOT appear in items.fields.
  8. Fields with exposure = "redacted" MAY be masked, omitted, or marked as withheld in redactions.
  9. Query results MUST use source = "query".
  10. A query MAY be restricted to directly related records by filtering on a declared relation field, e.g. deal.contactId = c1.
  11. Such direct relation-bound filters are not considered a join or transitive relation resolution.
  12. Multi-hop traversal, reverse expansion, nested includes, or automatic relation-following semantics are not defined in v0.1.
  13. Fields with exposure = "declared_only" MAY be filterable if the app allows it, but MUST still be omitted from items.fields.

This extension MAY use additional, namespaced error codes.

Recommended error codes:

type CognitionErrorCode =
| "uiap.cognition.unknown_entity"
| "uiap.cognition.unknown_scope"
| "uiap.cognition.query_not_allowed"
| "uiap.cognition.route_required"
| "uiap.cognition.ambiguous_entity";

An agent SHOULD be able to not only read entities but also reference them unambiguously when needed, so that Action specifications can use more precise targets.

interface CognitionTarget {
entityRef: EntityRef;
targetRef?: string; // optionaler UI-Target-Bezug
}
  1. Action/Runtime specifications MAY support entityRef as an additional or alternative target.
  2. If entityRef and targetRef are used together, both MUST point to the same underlying entity.
  3. If resolving an entityRef is ambiguous or stale, the action MUST fail with state_conflict, bad_request, or uiap.cognition.ambiguous_entity.
  4. Support for entityRef only extends target precision; it does not grant additional permissions.
  5. Mutations remain normatively defined in Action/Runtime specifications.
  1. Secure Default. recordAccess SHOULD default to visible_only.
  2. Schema does not equal data disclosure. A field MAY be visible in the schema without its values ever being delivered.
  3. Field Exposure. declared_only and redacted SHOULD be used for sensitive fields such as email, phone, or internal IDs.
  4. Query Limits. Implementations SHOULD use conservative limits; 50 records per query is a reasonable upper recommendation for v0.1.
  5. Audit. Apps SHOULD be able to document which scope queries and Cognition bootstrap data were delivered to agents.
  6. Least Surprise. If the agent is not permitted to see a record, that record SHOULD not be reconstructable implicitly through unexplained counts or side channels.

This specification is profile-neutral.

A web profile MAY derive the visible entity records from DOM annotations, for example. Recommended attribute names are:

  • data-uiap-entity
  • data-uiap-entity-id
  • data-uiap-field
  • data-uiap-collection
  • data-uiap-primary
  • data-uiap-redact

The concrete normative definition of these attributes SHOULD occur in the respective profile, not in Core.

{
"uiap": "0.1",
"kind": "request",
"type": "session.initialize",
"id": "msg_1",
"ts": "2026-03-29T09:00:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"payload": {
"supportedVersions": ["0.1"],
"supportedProfiles": ["[email protected]"],
"supportedExtensions": [
{ "id": "uiap.cognition", "versions": ["0.1"], "required": false }
],
"capabilityDelivery": "deferred",
"peer": {
"role": "agent",
"name": "cascade-agent",
"version": "0.1.0",
"locale": "de-CH",
"timezone": "Europe/Zurich"
}
},
"ext": {
"uiap.cognition": {
"bootstrapDelivery": "inline",
"requestedSurfaces": ["schema", "navigation", "context"],
"requestedQuery": false
}
}
}
{
"uiap": "0.1",
"kind": "response",
"type": "session.initialized",
"id": "msg_2",
"correlationId": "msg_1",
"sessionId": "sess_123",
"ts": "2026-03-29T09:00:00.040Z",
"source": { "role": "app", "id": "cascade-crm" },
"payload": {
"sessionId": "sess_123",
"selectedVersion": "0.1",
"selectedProfiles": ["[email protected]"],
"selectedExtensions": [
{ "id": "uiap.cognition", "version": "0.1" }
],
"capabilityDelivery": "deferred",
"heartbeatMs": 15000
},
"ext": {
"uiap.cognition": {
"bootstrapDelivery": "inline",
"enabledSurfaces": ["schema", "navigation", "context"],
"queryEnabled": false,
"bootstrap": {
"schema": {
"revision": "schema_1",
"entities": {
"contact": {
"label": "Kontakt",
"primaryField": "name",
"recordAccess": "visible_only",
"fields": {
"name": { "type": "string", "searchable": true, "sortable": true },
"company": { "type": "string", "searchable": true },
"status": { "type": "enum", "enumValues": ["active", "inactive", "prospect"] },
"email": { "type": "email", "exposure": "declared_only" }
}
}
}
},
"navigation": {
"revision": "nav_1",
"routes": [
{
"id": "contacts",
"path": "/contacts",
"label": "Kontakte",
"entities": ["contact"],
"capabilities": ["list", "search", "create"],
"activation": { "kind": "path", "value": "/contacts" }
}
]
},
"context": {
"revision": "ctx_7",
"scopeId": "contacts-list",
"routeId": "contacts",
"routePath": "/contacts",
"routeLabel": "Kontakte",
"collections": [
{
"entity": "contact",
"access": "visible_only",
"visibleCount": 2,
"items": [
{
"ref": { "type": "contact", "id": "c1", "stableId": "uiap-contact-c1", "primaryText": "Elena Rossi" },
"fields": { "name": "Elena Rossi", "company": "TechNova AG", "status": "active" },
"source": "visible"
},
{
"ref": { "type": "contact", "id": "c2", "stableId": "uiap-contact-c2", "primaryText": "Daniel Meier" },
"fields": { "name": "Daniel Meier", "company": "Nordstern GmbH", "status": "inactive" },
"source": "visible"
}
]
}
]
}
}
}
}
}
{
"uiap": "0.1",
"kind": "request",
"type": "uiap.cognition.query",
"id": "msg_41",
"sessionId": "sess_123",
"ts": "2026-03-29T09:05:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "contact",
"scopeId": "contacts-list",
"filters": [
{ "field": "status", "op": "eq", "value": "inactive" }
],
"sort": [
{ "field": "name", "direction": "asc" }
],
"offset": 0,
"limit": 20
}
}
{
"uiap": "0.1",
"kind": "response",
"type": "uiap.cognition.query.result",
"id": "msg_42",
"correlationId": "msg_41",
"sessionId": "sess_123",
"ts": "2026-03-29T09:05:00.015Z",
"source": { "role": "app", "id": "cascade-crm" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "contact",
"scopeId": "contacts-list",
"offset": 0,
"limit": 20,
"returned": 2,
"totalCount": 2,
"hasMore": false,
"items": [
{
"ref": { "type": "contact", "id": "c2", "primaryText": "Daniel Meier" },
"fields": { "name": "Daniel Meier", "company": "Nordstern GmbH", "status": "inactive" },
"source": "query"
},
{
"ref": { "type": "contact", "id": "c8", "primaryText": "Priya Shah" },
"fields": { "name": "Priya Shah", "company": "Aster Labs", "status": "inactive" },
"source": "query"
}
]
}
}

13.3 Navigation via Existing Action Runtime

Section titled “13.3 Navigation via Existing Action Runtime”

Example of switching to the Contacts route via the existing runtime:

{
"uiap": "0.1",
"kind": "request",
"type": "action.request",
"id": "msg_51",
"sessionId": "sess_123",
"ts": "2026-03-29T09:06:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"payload": {
"actionId": "nav.navigate",
"target": {
"ref": { "by": "route", "value": "contacts" }
}
}
}

Example: Load all deals whose contactId points to contact c1.

{
"uiap": "0.1",
"kind": "request",
"type": "uiap.cognition.query",
"id": "msg_61",
"sessionId": "sess_123",
"ts": "2026-03-29T09:07:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "deal",
"routeId": "deals",
"filters": [
{ "field": "contactId", "op": "eq", "value": "c1" }
],
"limit": 20
}
}

This is a direct filter on a declared relation field in v0.1, but not a general relation traversal.

A UIAP Agent Cognition v0.1-conformant implementation MUST, if it offers this extension:

  • negotiate the extension cleanly
  • be able to deliver CognitionBootstrap in inline or deferred form
  • respect recordAccess
  • respect FieldExposure
  • send uiap.cognition.changed as full replacement for changed surfaces
  • process uiap.cognition.query as read-only and limited when query mode is enabled

An implementation does not need to support all surfaces or querying to be conformant.

  • [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
VersionDateChanges
0.12026-03-29Initial draft