Skip to content

UIAP Workflow Extension

FieldValue
StatusDraft
Version0.1
Date2026-03-27
Dependencies[UIAP-CORE], [UIAP-CAP], [UIAP-WEB], [UIAP-ACTION], [UIAP-POLICY]
EditorsPatrick

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.

UIAP Workflow Extension v0.1 defines how an application or a UIAP-compatible agent describes, starts, executes, pauses, resumes, and completes multi-step, semantic processes.

The extension is designed for things like:

  • Onboarding flows
  • Guided setup
  • Recurring product tasks
  • Support/recovery processes
  • Hybrid forms of explaining, showing, entering, and hand-off

It builds on the following specifications:

  • UIAP Core v0.1
  • UIAP Capability Model v0.1
  • UIAP Web Profile v0.1
  • UIAP Action Runtime Spec v0.1
  • UIAP Policy Extension v0.1

The Workflow Extension does not define:

  • how DOM or UI is technically read
  • how actions are technically executed
  • how policy is internally implemented
  • how an LLM plans or formulates

It defines the contract for structured processes, not the brain and not the browser mechanics.


type ExtensionId = "uiap.workflow";
type ExtensionVersion = "0.1";

A counterpart offering this extension MUST declare it during the handshake.

Example:

{
"id": "uiap.workflow",
"versions": ["0.1"],
"required": false
}

  1. A workflow MUST exist as a structured, machine-readable definition.
  2. A workflow MUST consist of clearly defined steps.
  3. A workflow MUST NOT execute actions directly by “magic”; instead, it MUST use the Action Runtime.
  4. A workflow MUST explicitly model inputs, conditions, success criteria, and recovery.
  5. A workflow MUST be pausable and resumable.
  6. A workflow SHOULD be robust against UI drift, i.e., not rely solely on raw click sequences.
  7. A workflow MAY be declarative, but not arbitrarily so. Otherwise, you end up with a programming language and politely call it an “Extension”.

A Workflow is a versioned definition of a domain-level or UX-level process.

Examples:

  • workspace.initial_setup
  • video.create_first_video
  • team.invite_member
  • billing.connect_payment_method

A Workflow Instance is a running or paused execution of a workflow.

A Step is a single executable or verifiable part of a workflow.

An Input is a required parameter that can come from the user, app, context, or derivation.

A Checkpoint is a declared resume point.

The Interaction Mode describes how actively the workflow is permitted to act.

type WorkflowInteractionMode =
| "explain" // explain only
| "guide" // show, highlight, navigate, but do not write
| "assist" // safe inputs / drafts / reversible steps
| "auto"; // all permitted actions according to policy

The Start Mode describes how a workflow is initiated.

type WorkflowStartMode =
| "manual" // explicitly started by the user
| "suggested" // suggested, but not automatically started
| "automatic"; // may start automatically if policy permits

type WorkflowStatus =
| "validating"
| "running"
| "waiting_input"
| "waiting_confirmation"
| "waiting_user"
| "paused"
| "succeeded"
| "failed"
| "cancelled";
  • validating: Definition, applicability, inputs, and policy are being checked.
  • running: Workflow is actively processing steps.
  • waiting_input: Required values are missing.
  • waiting_confirmation: Confirmation is needed.
  • waiting_user: Human handoff or user action is required.
  • paused: Deliberately suspended, resumable later.
  • succeeded: Successfully completed.
  • failed: Terminated with an error.
  • cancelled: Terminated by user, policy, or system.

interface WorkflowCatalog {
modelVersion: "0.1";
extension: "uiap.workflow";
revision?: string;
workflows: WorkflowDefinition[];
metadata?: Record<string, unknown>;
}

interface WorkflowDefinition {
id: string;
version: string;
title: LocalizedText;
description?: LocalizedText;
category?: WorkflowCategory;
startMode?: WorkflowStartMode;
interactionModes: WorkflowInteractionMode[];
intents?: WorkflowIntent[];
triggers?: WorkflowTrigger[];
applicability?: WorkflowApplicability;
inputs?: WorkflowParameter[];
outputs?: WorkflowOutput[];
requiredGrants?: PolicyGrant[];
initialStepId: string;
steps: WorkflowStep[];
success?: WorkflowSuccessCriteria;
failure?: WorkflowFailurePolicy;
metadata?: Record<string, unknown>;
}
type WorkflowCategory =
| "onboarding"
| "setup"
| "task"
| "support"
| "education"
| "recovery"
| "custom";
type LocalizedText =
| string
| {
default: string;
byLocale?: Record<string, string>;
};
  1. id MUST be unique within a catalog.
  2. version MUST be incremented for semantic changes.
  3. initialStepId MUST reference an existing step.
  4. Every workflow MUST have at least one terminal complete or handoff/failed path.
  5. Cyclic flows ARE ONLY permitted if they are explicitly bounded, e.g., via retry limits.

interface WorkflowIntent {
phrases: string[];
locale?: string;
weight?: number; // default 1.0
}

Intents serve to match user intentions to workflows.

Examples:

{
"phrases": [
"hilf mir beim ersten video",
"erstes video anlegen",
"video erstellen"
],
"locale": "de-CH",
"weight": 1.0
}

type WorkflowTrigger =
| {
kind: "intent";
intents?: string[];
}
| {
kind: "route.entered";
routeIds: string[];
}
| {
kind: "first_run";
feature?: string;
}
| {
kind: "signal";
signalKinds: string[];
}
| {
kind: "custom";
name: string;
payload?: Record<string, unknown>;
};
  • Triggers describe when a workflow can be suggested or started.
  • A trigger alone MUST NOT force a start if policy or applicability objects.

interface WorkflowApplicability {
routeIds?: string[];
scopeIds?: ScopeId[];
principalRoles?: string[];
requiredGrants?: PolicyGrant[];
requiredActions?: ActionId[];
conditions?: WorkflowCondition[];
}
  • A workflow is only applicable if all specified applicability conditions are met.
  • requiredActions MUST be checked against the Capability Model.
  • requiredGrants MUST be checked against the current policy/principal context.

interface WorkflowParameter {
name: string;
title?: LocalizedText;
description?: LocalizedText;
type: WorkflowValueType;
required?: boolean;
meaning?: string;
sensitive?: boolean;
sourceOrder?: WorkflowValueSource[];
default?: WorkflowValueExpr;
validation?: ParameterValidation[];
prompt?: LocalizedText;
bindTo?: ParameterBinding;
}
type WorkflowValueType =
| "string"
| "number"
| "boolean"
| "enum"
| "object"
| "array";
type WorkflowValueSource =
| "provided"
| "context"
| "route"
| "derive"
| "suggest"
| "user";
interface ParameterBinding {
stableIds?: StableId[];
actionArg?: string;
}
interface ParameterValidation {
kind: "required" | "minLength" | "maxLength" | "pattern" | "enum" | "custom";
value?: unknown;
message?: LocalizedText;
}
  1. sourceOrder defines the order in which values are resolved.
  2. provided means values from workflow.start.inputs.
  3. context means values from session, route, or app context.
  4. derive means machine-readable derivation from the current UI/state context.
  5. suggest means suggestions generated by the agent or a template.
  6. user means values explicitly supplied by the user.
  7. Sensitive inputs SHOULD be automatically linked to policy and redaction rules.

interface WorkflowOutput {
name: string;
type: WorkflowValueType;
from: WorkflowValueExpr;
}

type WorkflowValueExpr =
| { from: "literal"; value: unknown }
| { from: "param"; name: string }
| { from: "route"; path: string }
| { from: "context"; path: string }
| { from: "actionResult"; stepId: string; path?: string }
| { from: "signal"; stepId?: string; kind?: string; path?: string };

These expressions are used for action arguments, defaults, and outputs.


interface WorkflowStepBase {
id: string;
type: WorkflowStepType;
title?: LocalizedText;
if?: WorkflowCondition[];
timeoutMs?: number;
checkpoint?: boolean;
next?: string;
onError?: WorkflowRecoveryRule[];
metadata?: Record<string, unknown>;
}
type WorkflowStepType =
| "instruction"
| "collect"
| "suggest"
| "action"
| "ensure"
| "branch"
| "handoff"
| "complete";
  • id MUST be unique within a workflow.
  • If if is set and not satisfied, the step is considered skipped and the flow proceeds to next or the lexically next step.
  • checkpoint=true marks a potential resume point.
  • onError defines step-local recovery.

interface InstructionStep extends WorkflowStepBase {
type: "instruction";
text: LocalizedText;
presentation?: PresentationHints;
}
  • Pure explanation or contextualization.
  • May contain overlay/narration hints.
  • Does not alter any domain state.

interface CollectStep extends WorkflowStepBase {
type: "collect";
parameters: string[];
prompt?: LocalizedText;
allowPartial?: boolean;
autoAcceptIfResolved?: boolean;
}
  • Resolves missing parameters.
  • First checks sourceOrder.
  • If values are still missing afterwards, the workflow enters waiting_input and emits uiap.workflow.input.request.

interface SuggestStep extends WorkflowStepBase {
type: "suggest";
parameter: string;
source: "agent" | "template" | "app";
template?: string;
confirm?: "always" | "if_changed" | "never";
}
  • Generates a suggested value for exactly one parameter.
  • The actual generation is an implementation concern.
  • confirm="always" requires explicit acceptance of the suggestion.
  • confirm="never" is only recommended for non-sensitive, reversible, or clearly non-critical cases.

interface WorkflowActionStep extends WorkflowStepBase {
type: "action";
actionId: ActionId;
target?: ActionTarget;
args?: Record<string, WorkflowValueExpr>;
preferredExecutionModes?: ExecutionMode[];
verification?: VerificationSpec;
presentation?: PresentationHints;
saveResultAs?: string;
}
  • Delegates to the UIAP Action Runtime.
  • Policy MUST be checked before execution.
  • saveResultAs stores structured return data for subsequent steps.

interface EnsureStep extends WorkflowStepBase {
type: "ensure";
conditions: WorkflowCondition[];
policy?: "all" | "any";
waitFor?: boolean;
pollMs?: number;
}
  • Evaluates conditions.

  • If waitFor=true, it MAY wait for the conditions to be met.

  • Typical use cases:

    • “Dialog is open”
    • “Route has changed”
    • “Toast was shown”
    • “Field is no longer invalid”

interface BranchStep extends WorkflowStepBase {
type: "branch";
branches: Array<{
when: WorkflowCondition[];
next: string;
}>;
otherwise?: string;
}
  • Evaluates branches in declared order.
  • The first matching branch wins.
  • If no branch matches, otherwise is used.
  • If otherwise is missing, the workflow MUST fail.

interface HandoffStep extends WorkflowStepBase {
type: "handoff";
reason: LocalizedText;
message?: LocalizedText;
resumeWhen?: WorkflowCondition[];
}
  • Forces user takeover or external intervention.
  • The workflow transitions to waiting_user.
  • Resumption occurs via workflow.resume, workflow.input.provide, or when resumeWhen conditions are met.

Typical cases:

  • Login / re-auth
  • CAPTCHA
  • Payment approval
  • Legal confirmation
  • Browser or platform boundaries

interface CompleteStep extends WorkflowStepBase {
type: "complete";
summary?: LocalizedText;
outputs?: Record<string, WorkflowValueExpr>;
}
  • Finalizes the workflow.
  • Sets status to succeeded, provided no global success rules are violated.
  • Returns output values.

type WorkflowCondition =
| { kind: "param.present"; name: string }
| { kind: "param.equals"; name: string; value: unknown }
| { kind: "route.is"; routeId: string }
| { kind: "scope.present"; scopeId: ScopeId }
| { kind: "element.present"; target: TargetRef }
| { kind: "element.state"; target: TargetRef; state: Partial<UIState> }
| { kind: "signal.observed"; signal: SuccessSignal }
| { kind: "action.status"; stepId: string; status: "succeeded" | "failed" | "cancelled" }
| { kind: "policy.effect"; effect: PolicyEffect }
| { kind: "custom"; name: string; args?: Record<string, unknown> };
  • Conditions MUST be deterministically evaluable.
  • custom is permitted but only for implementations that recognize it.
  • Unknown custom conditions MUST NOT silently evaluate to true.

interface WorkflowSuccessCriteria {
policy?: "all" | "any";
conditions?: WorkflowCondition[];
signals?: SuccessSignal[];
}

A workflow is successful when:

  1. a complete step has been reached, and
  2. global success criteria are met, if defined.

interface WorkflowFailurePolicy {
onUnhandledError: "fail" | "handoff" | "cancel";
maxWorkflowRetries?: number;
resumable?: boolean;
}

interface WorkflowRecoveryRule {
on: WorkflowFailureMatcher;
strategy: "retry_step" | "goto_step" | "handoff" | "cancel" | "fail";
gotoStepId?: string;
maxAttempts?: number;
note?: LocalizedText;
}
interface WorkflowFailureMatcher {
runtimeCodes?: string[];
verificationFailed?: boolean;
timeout?: boolean;
policyEffects?: PolicyEffect[];
statuses?: Array<"failed" | "cancelled">;
}
  • Recovery is evaluated at the step level before the global failure policy.
  • Non-idempotent actions MUST NOT be blindly retried via retry_step when sideEffectState="unknown".
  • goto_step MUST reference an existing step.
  • maxAttempts limits local retries.

interface WorkflowInstance {
instanceId: string;
workflowId: string;
workflowVersion: string;
status: WorkflowStatus;
mode: WorkflowInteractionMode;
currentStepId?: string;
completedStepIds: string[];
inputs: Record<string, unknown>;
outputs?: Record<string, unknown>;
checkpoint?: WorkflowCheckpoint;
history?: WorkflowHistoryEntry[];
metadata?: Record<string, unknown>;
}
interface WorkflowCheckpoint {
checkpointId: string;
stepId: string;
createdAt: string;
}
interface WorkflowHistoryEntry {
stepId: string;
status: "started" | "skipped" | "succeeded" | "failed" | "cancelled";
startedAt?: string;
finishedAt?: string;
note?: string;
}

interface WorkflowGetPayload {
category?: WorkflowCategory;
ids?: string[];
}
interface WorkflowDocumentPayload {
catalog: WorkflowCatalog;
}

Serves to match user intent and current context against workflow candidates.

interface WorkflowMatchPayload {
intent?: string;
routeId?: string;
mode?: WorkflowInteractionMode;
maxResults?: number;
}
interface WorkflowMatchCandidate {
workflowId: string;
score: number;
reason?: string;
missingInputs?: string[];
blockedByPolicy?: boolean;
}
interface WorkflowMatchesPayload {
candidates: WorkflowMatchCandidate[];
}
  • score SHOULD be between 0 and 1.
  • blockedByPolicy=true means: functionally matching, but currently not startable.

interface WorkflowStartPayload {
workflowId: string;
mode?: WorkflowInteractionMode;
inputs?: Record<string, unknown>;
resumeFromCheckpointId?: string;
}
interface WorkflowStartedPayload {
instance: WorkflowInstance;
}
  • The workflow MUST exist.
  • Applicability MUST be satisfied.
  • mode MUST be permitted by the workflow.
  • Policy MAY prevent start or set it to confirm/handoff.

interface WorkflowProgressPayload {
instanceId: string;
workflowId: string;
status: WorkflowStatus;
currentStepId?: string;
currentStepType?: WorkflowStepType;
completedStepIds?: string[];
missingInputs?: string[];
note?: string;
checkpointId?: string;
}
  • Progress SHOULD be emitted on every status change and every step transition.

interface WorkflowInputRequestPayload {
instanceId: string;
parameters: WorkflowParameter[];
prompt?: LocalizedText;
}

interface WorkflowInputProvidePayload {
instanceId: string;
values: Record<string, unknown>;
}
interface WorkflowInputAcceptedPayload {
instanceId: string;
accepted: string[];
rejected?: Array<{
name: string;
reason: string;
}>;
}

interface WorkflowPausePayload {
instanceId: string;
reason?: string;
}
interface WorkflowPausedPayload {
instanceId: string;
status: "paused";
}

interface WorkflowResumePayload {
instanceId: string;
}
interface WorkflowResumedPayload {
instanceId: string;
status: "running";
currentStepId?: string;
}

interface WorkflowCancelPayload {
instanceId: string;
reason?: string;
}
interface WorkflowCancelledPayload {
instanceId: string;
status: "cancelled";
}

interface WorkflowResultPayload {
instanceId: string;
workflowId: string;
status: "succeeded" | "failed" | "cancelled";
outputs?: Record<string, unknown>;
finalStepId?: string;
error?: {
code: string;
message: string;
};
summary?: LocalizedText;
}

interface WorkflowChangedPayload {
revision: string;
catalog: WorkflowCatalog;
}

On start, the executor MUST:

  1. Find the workflow
  2. Check applicability
  3. Check interaction mode
  4. Accept initial inputs
  5. Validate inputs against schema
  6. Check start policy
  7. Create instance
  8. On success, emit uiap.workflow.started

If any of these steps fails, the start MUST terminate with an error.


Processing begins at initialStepId.

For each step:

  1. Evaluate if
  2. If if=false: skip step
  3. Execute step
  4. Handle success, failure, or handoff
  5. Determine next step

If next is set, it MUST be used. If next is absent, the lexically next step in the workflow SHOULD be used. branch determines the next step on its own. complete terminates the workflow.


  • Produces at most an explanation/presentation
  • Proceeds immediately
  • Resolves missing inputs
  • Enters waiting_input when required values are still missing
  • Computes a suggestion
  • Confirms or adopts depending on confirm
  • Delegates to action.request
  • Reflects action runtime status in workflow status
  • Stores result in history and optionally in saveResultAs
  • Evaluates conditions
  • Optionally waits
  • Fails on timeout or unmet conditions
  • Determines path
  • If nothing matches and otherwise is missing: error
  • Sets waiting_user
  • Resumption only after resume or met conditions
  • Finalizes outputs
  • Checks global success criteria
  • Emits workflow.result

Before every action execution, policy MUST be evaluated.

Rules:

  • allow -> step may proceed
  • confirm -> workflow MUST enter waiting_confirmation
  • deny -> step fails
  • handoff -> workflow MUST enter waiting_user

A workflow MAY additionally enforce stricter interaction logic than the current policy, but never more lenient.

Example: A workflow in guide mode MUST NOT execute write actions even if policy returns allow.


If a step has checkpoint=true, a checkpoint SHOULD be created after successful completion.

A resume MUST:

  • load the last valid checkpoint, or
  • use the specified resumeFromCheckpointId

A resume MUST NOT jump back before an incomplete, potentially non-idempotent side effect without the implementation reliably knowing its state. People tend to call that sort of thing a “data issue” later.


A conforming uiap.workflow@0.1 implementation MUST support:

  • uiap.workflow.get
  • uiap.workflow.start
  • uiap.workflow.progress
  • uiap.workflow.input.request
  • uiap.workflow.input.provide
  • uiap.workflow.pause
  • uiap.workflow.resume
  • uiap.workflow.cancel
  • uiap.workflow.result

It MUST additionally support at least these step types:

  • instruction
  • collect
  • action
  • branch
  • handoff
  • complete

It SHOULD additionally support:

  • ensure
  • suggest

{
"id": "video.create_first_video",
"version": "0.1.0",
"title": {
"default": "Erstes Video erstellen",
"byLocale": {
"de-CH": "Erstes Video erstellen"
}
},
"description": "Führt den Nutzer durch das Anlegen des ersten Videos.",
"category": "onboarding",
"startMode": "suggested",
"interactionModes": ["guide", "assist", "auto"],
"intents": [
{
"phrases": [
"hilf mir beim ersten video",
"erstes video erstellen",
"video anlegen"
],
"locale": "de-CH",
"weight": 1
}
],
"applicability": {
"routeIds": ["dashboard", "videos", "videos.new"],
"requiredActions": [
"nav.navigate",
"ui.enterText",
"ui.activate",
"video.create"
]
},
"inputs": [
{
"name": "title",
"title": "Videotitel",
"type": "string",
"required": true,
"meaning": "title",
"sourceOrder": ["provided", "user"],
"prompt": "Wie soll dein erstes Video heissen?"
},
{
"name": "useCase",
"title": "Anwendungszweck",
"type": "string",
"required": false,
"meaning": "use_case",
"sourceOrder": ["provided", "suggest", "user"],
"prompt": "Wofür soll das Video verwendet werden?"
}
],
"outputs": [
{
"name": "videoId",
"type": "string",
"from": {
"from": "actionResult",
"stepId": "create_video",
"path": "id"
}
}
],
"initialStepId": "intro",
"steps": [
{
"id": "intro",
"type": "instruction",
"text": "Ich helfe dir, dein erstes Video anzulegen.",
"next": "collect_title"
},
{
"id": "collect_title",
"type": "collect",
"parameters": ["title"],
"next": "suggest_use_case"
},
{
"id": "suggest_use_case",
"type": "suggest",
"parameter": "useCase",
"source": "agent",
"confirm": "if_changed",
"next": "go_to_form"
},
{
"id": "go_to_form",
"type": "action",
"actionId": "nav.navigate",
"args": {
"routeId": {
"from": "literal",
"value": "videos.new"
}
},
"checkpoint": true,
"next": "fill_title"
},
{
"id": "fill_title",
"type": "action",
"actionId": "ui.enterText",
"target": {
"ref": {
"by": "stableId",
"value": "video.title"
}
},
"args": {
"text": {
"from": "param",
"name": "title"
}
},
"next": "branch_use_case"
},
{
"id": "branch_use_case",
"type": "branch",
"branches": [
{
"when": [
{
"kind": "param.present",
"name": "useCase"
}
],
"next": "fill_use_case"
}
],
"otherwise": "create_video"
},
{
"id": "fill_use_case",
"type": "action",
"actionId": "ui.enterText",
"target": {
"ref": {
"by": "stableId",
"value": "video.use_case"
}
},
"args": {
"text": {
"from": "param",
"name": "useCase"
}
},
"next": "create_video"
},
{
"id": "create_video",
"type": "action",
"actionId": "video.create",
"target": {
"ref": {
"by": "stableId",
"value": "video.submit"
}
},
"verification": {
"policy": "all",
"signals": [
{
"kind": "route.changed",
"pattern": "/videos/:id"
},
{
"kind": "toast.contains",
"text": "erstellt"
}
],
"timeoutMs": 10000,
"requireRevisionAdvance": true
},
"checkpoint": true,
"saveResultAs": "create_video_result",
"onError": [
{
"on": {
"policyEffects": ["handoff"]
},
"strategy": "handoff",
"note": "Bitte übernimm den Bestätigungsschritt selbst."
},
{
"on": {
"runtimeCodes": ["verification_failed"]
},
"strategy": "goto_step",
"gotoStepId": "verify_result"
}
],
"next": "verify_result"
},
{
"id": "verify_result",
"type": "ensure",
"conditions": [
{
"kind": "signal.observed",
"signal": {
"kind": "route.changed",
"pattern": "/videos/:id"
}
}
],
"policy": "all",
"waitFor": true,
"timeoutMs": 4000,
"next": "done"
},
{
"id": "done",
"type": "complete",
"summary": "Dein erstes Video wurde angelegt.",
"outputs": {
"videoId": {
"from": "actionResult",
"stepId": "create_video",
"path": "id"
}
}
}
],
"success": {
"policy": "all",
"signals": [
{
"kind": "route.changed",
"pattern": "/videos/:id"
}
]
},
"failure": {
"onUnhandledError": "handoff",
"maxWorkflowRetries": 0,
"resumable": true
}
}

{
"uiap": "0.1",
"kind": "request",
"type": "uiap.workflow.start",
"id": "msg_301",
"sessionId": "sess_123",
"ts": "2026-03-26T15:10:00.000Z",
"source": { "role": "agent", "id": "onboarding-agent" },
"payload": {
"workflowId": "video.create_first_video",
"mode": "assist",
"inputs": {
"title": "Produktdemo für Kunde A"
}
}
}

{
"uiap": "0.1",
"kind": "event",
"type": "uiap.workflow.progress",
"id": "msg_302",
"sessionId": "sess_123",
"ts": "2026-03-26T15:10:01.200Z",
"source": { "role": "bridge", "id": "web-runtime" },
"payload": {
"instanceId": "wf_991",
"workflowId": "video.create_first_video",
"status": "running",
"currentStepId": "fill_title",
"currentStepType": "action",
"completedStepIds": ["intro", "collect_title", "suggest_use_case", "go_to_form"],
"checkpointId": "cp_2"
}
}

{
"uiap": "0.1",
"kind": "event",
"type": "uiap.workflow.result",
"id": "msg_303",
"sessionId": "sess_123",
"ts": "2026-03-26T15:10:08.900Z",
"source": { "role": "bridge", "id": "web-runtime" },
"payload": {
"instanceId": "wf_991",
"workflowId": "video.create_first_video",
"status": "succeeded",
"outputs": {
"videoId": "vid_12345"
},
"finalStepId": "done",
"summary": "Dein erstes Video wurde angelegt."
}
}

To prevent this from breaking after the third UI change in real products, I would treat these rules as quasi-mandatory:

  1. Workflows declarative first, not prompt-based Prompts may provide phrasing, but they must not be the sole source of truth for process flow and success criteria.

  2. Action steps only through Runtime No workflow step may “somehow” modify the UI directly without going through Action Runtime and Policy.

  3. Slice use cases into packages Better 20 small, reliable workflows than 3 omniscient monster processes.

  4. Checkpoints after side effects Especially after app.invoke, submit, create, delete, publish.

  5. Strictly separate guide/assist/auto Otherwise “showing” suddenly becomes “accidentally submitted”.


  • [UIAP-CORE] UIAP Core v0.1
  • [UIAP-CAP] UIAP Capability Model v0.1
  • [UIAP-WEB] UIAP Web Profile v0.1
  • [UIAP-ACTION] UIAP Action Runtime v0.1
  • [UIAP-POLICY] UIAP Policy Extension v0.1
  • [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
  • Workflow definitions SHOULD only be loaded from trusted sources.
  • Workflows MUST NOT bypass policy decisions; every step MUST be individually checked against policy.
  • Recovery mechanisms MUST ensure that partially executed workflows do not leave inconsistent states behind.
  • Workflow variables MAY contain sensitive data and SHOULD be redacted in audit logs.
VersionDateChanges
0.12026-03-27Initial draft