Capabilities, journeys and events

How product teams define what a product can do, which flows must hold, and what gets measured, when screens are generated.

When screens are generated, product managers and designers stop drawing screens and define what sits one level above them:

Today In Polyxd
Feature Capability: a registered thing the product can do
Flow or user journey Journey: a goal with required checkpoints
Acceptance criteria Checks that run against generated UIs
Analytics and funnels Semantic events, emitted automatically

All three have schemas in @polyxd/spec today. Capabilities and journeys are checked by the validator and verifier. The runtime that emits events is planned.

Capabilities#

A generated UI can only trigger capabilities the host has registered. The action intents in a UI document are capability names. A registry (schema/capabilities.schema.json) gives each one metadata:

{
  "name": "polyxd-examples",
  "capabilities": {
    "transfer.confirm": {
      "description": "Send money for a reviewed quote",
      "risk": "consequential",
      "inputs": {
        "type": "object",
        "properties": { "quoteId": { "type": "string" } },
        "required": ["quoteId"],
        "additionalProperties": false
      },
      "preconditions": ["Quote not expired"],
      "sideEffects": ["Moves money out of the account"],
      "agentMayInvoke": false
    }
  }
}
Field What it is
description What it does. Required.
risk none, low, consequential or destructive. Required.
inputs JSON Schema of the event context it accepts.
preconditions Plain-language conditions, e.g. "Payment method on file".
sideEffects Plain-language effects, e.g. "Charges the payment method".
flag An OpenFeature flag key. When the flag is off, the capability can't appear.
agentMayInvoke Whether an AI agent may trigger it without a human confirming. Defaults to true.

What risk levels enforce#

checkCapabilities(doc, registry, flags) checks every action in a document:

Risk Rule
none, low Can be triggered from anywhere
consequential Only from inside a Confirm, from a surface that declares the review-and-submit pattern, or from the finish of a Steps whose last step contains a DetailList review
destructive Only from inside a Confirm

It also reports an error for any action that isn't registered or whose flag is off, and a warning when the event context sends an input the capability doesn't declare, or leaves out a required one.

import { checkCapabilities } from "@polyxd/spec/capabilities";

const issues = checkCapabilities(doc, registry, { "reading-import": false });
// [{ severity: "error", at: "/components/6/action/event/name",
//    message: "\"books.import\" is switched off by flag \"reading-import\"" }]

agentMayInvoke is recorded in the schema; enforcing it at runtime is planned. The spec's example registry is packages/spec/examples/registry/capabilities.json, and the benchmark has a larger one (bench/registry.json, 58 capabilities).

Journeys#

A journey is a goal, required checkpoints and a done-condition (schema/journey.schema.json). The same file is a flow spec for PMs and designers, a set of acceptance tests, and an agent task.

{
  "id": "money.send",
  "goal": "Send money to someone I've paid before",
  "intent": "money.send",
  "mode": "guided",
  "capabilities": ["transfer.review", "transfer.confirm"],
  "checkpoints": [
    { "key": "details", "description": "Recipient and amount entered", "event": "transfer.review" },
    { "key": "fee-visible", "description": "The fee is shown before the user confirms",
      "rule": { "check": "contains", "component": "DetailList" } },
    { "key": "confirmed", "description": "User explicitly confirms the exact amount",
      "rule": { "check": "rootIs", "components": ["Confirm"] } }
  ],
  "done": { "event": "transfer.confirm" },
  "acceptance": [
    { "id": "confirm-names-amount", "description": "The confirm button states the amount being sent",
      "severity": "error",
      "rule": { "check": "labelMatches", "component": "Confirm", "pattern": "£[0-9]", "prop": "confirm.label" } }
  ],
  "task": {
    "instruction": "Send £250 to Alex Kim with the reference 'Rent share'.",
    "inputs": { "recipient": "Alex Kim", "amount": 250, "reference": "Rent share" },
    "maxSteps": 8
  }
}

Modes#

Mode What's fixed For
fixed The exact surfaces Regulated or legal flows such as KYC and consent. The example account.delete journey is fixed
guided The checkpoints; the layout between them is generated Most flows
open Only the goal and done-condition Exploratory tasks

Parts#

The verifier's scripted agent tasks (bench/tasks.json) use this goal and done-event shape. See People and agents.

Semantic analytics events#

Every generated UI already knows its intent, pattern, components and capabilities, so the planned runtime will emit standard events with no manual tracking (schema/event.schema.json):

Event When
surface.shown, surface.dismissed A UI appears or is closed
surface.regenerated The user had to ask again
action.taken A capability action is triggered
checkpoint.reached A journey checkpoint is reached
task.completed, task.abandoned A journey finishes or is given up
input.error A field fails validation
status.shown A Status is shown
undo The user undoes something
feedback Optional quick rating (−1, 0, 1)

Each event carries the surface (id, intent, pattern, journey, spec version, generator, Direction, experiment variants), the actor (human or agent, and whether assistive technology is in use), and where relevant the component, capability, checkpoint, duration and step count. So metrics can be split by human versus agent from the start.

{
  "type": "action.taken",
  "timestamp": "2026-09-19T21:04:11Z",
  "sessionId": "s_8f2",
  "surface": {
    "id": "send-confirm", "intent": "money.send", "pattern": "confirm-destructive",
    "journey": "money.send", "specVersion": "0.1.0",
    "generator": "polyxd-3b@0.1.0", "direction": "calm-finance@0.1.0"
  },
  "actor": { "kind": "human", "assistiveTech": false },
  "component": { "id": "confirm", "type": "Confirm" },
  "capability": "transfer.confirm",
  "durationMs": 5400,
  "steps": 1
}

This example is from packages/spec/examples/events/. The generator name in it is illustrative; no Polyxd model exists yet.

Privacy#

Events carry keys and semantics, never field values or personal data. reason is a short code, never free text from the user. Events go to the host's own analytics through adapters (PostHog, Amplitude, Segment or OpenTelemetry are the planned targets). Polyxd itself collects nothing and has no telemetry.

Polyxd is an early preview. Found something unclear? It will get better with your feedback.