You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Proposal] Guided policy forms in the AI Workspace from UI hints in policy definitions
#3766
Policy forms in the AI Workspace are generated from each policy's parameters JSON Schema, and policy authors have no control over how they look or behave. This proposal lets a policy carry optional UI hints inside parameters, under one key, x-wso2-policy-ui. The AI Workspace renders the form with react-jsonschema-form (RJSF), and generates sensible defaults for every field without a hint.
parameters stays the single source of truth. The gateway validates exactly what it validates today. No API, model or database change is needed.
Related: #3582 (feature request), #3583 (prototype, to be updated to this design).
What is the problem that we are trying to solve?
A policy's form is generated from its parameters JSON Schema, and the policy author has no say in how it looks or behaves:
Every field is always shown. A field can't depend on another field's value, so a yes/no question still shows criteria and blockOn, which only apply to other question types (Figure 1).
Raw key names and fixed validation messages.
No choice of components, such as a slider for a 0 to 1 threshold, a text area or a field order.
Figure 1: TypeSafe Jev Content Safety v0.8 in today's editor (left) and in the RJSF prototype from #3583 (middle and right).
Who are we solving the problem for?
AI Workspace users who configure policies on LLM providers, LLM proxies and MCP proxies. They should see only the fields that apply, in plain words, and know what's wrong before they save.
Policy authors, at WSO2 and in teams writing custom policies. They should be able to shape the form without changing what the gateway validates.
Why should it be solved?
Policies such as the TypeSafe Jev guardrails hold lists of rules that each hold lists of typed questions, and they are hard to fill in with today's form.
UI hints live inside parameters, on the fields they describe, under one optional key: x-wso2-policy-ui.
flowchart LR
D["policy-definition.yaml<br/>parameters (JSON Schema)<br/>+ optional x-wso2-policy-ui hints"]
subgraph W[AI Workspace]
direction LR
S1["1. Split schema<br/>hints to uiSchema"] --> S2["2. Fill defaults"] --> S3["3. Render with RJSF"] --> S4["4. Check against parameters"]
end
G["Gateway<br/>validates params against parameters<br/>and ignores the hints"]
D -->|Policy Hub or Platform API| S1
S4 -->|params| G
D -.->|the same parameters| G
Loading
For each policy, the AI Workspace:
Splits the schema. Each hint becomes RJSF uiSchema at the field's path, and the rest becomes a form-only copy of the schema.
Fills in defaults for fields without hints. A hint wins over the default, field by field.
Checks the output against parameters before saving. The saved params have the same shape as today.
No API, model or database change is needed. Built-in definitions come from Policy Hub as YAML, and the gateway manifest already carries the full parameters block of custom policies. So the UI model field and the Platform API changes in #3583 are dropped.
Authoring
Hint keys are RJSF uiSchema options without the ui: prefix, plus errorMessage:
threshold:
type: numbertitle: Threshold # standard JSON Schemaminimum: 0maximum: 1x-wso2-policy-ui: # optionalwidget: slider # ui:widget, from our widget registryhelp: A probability from 0 to 1.errorMessage: Enter a probability from 0 to 1.
Options such as widget, placeholder, help, order and enumNames become ui:<name> at the field's path. errorMessage goes into the form copy as the ajv-errors keyword.
Labels and help text come from the standard title and description keywords.
The existing x-wso2-policy-advanced-param, x-wso2-policy-deprecated-param and x-wso2-policy-property-order keys stay as they are.
Generated defaults
A policy with no hints still gets a complete form, so released policies need no change. The generator:
takes labels and help from title and description, or puts the key in words;
uses RJSF's default widget for each type, and x-wso2-policy-property-order for field order;
keeps today's Advanced settings section and Deprecated badge, and readable default messages;
attaches a field's custom message to its parent's required check, because Ajv reports a missing field on the parent;
leaves rule-only anyOf/oneOf, such as "request or response is required", out of the form copy, so RJSF doesn't draw them as option pickers. The check on save still enforces them.
Conditional fields
Authors write plain JSON Schema. The field stays in properties, and an if/then names it:
The gateway then requires criteria for score and choice questions. The form copy moves the field into the then branch, so RJSF shows it only when that branch applies.
The field must not be declared only inside then. With additionalProperties: false, the gateway rejects it (Additional property criteria is not allowed).
Validation
Live checks run on the form copy, with the custom messages. The save is checked against parameters.
Figure 2: custom error messages in the RJSF prototype (TypeSafe Jev Model Routing).
Alternatives considered
Option
Why not
A separate block with its own form schema and uiSchema (#3583)
It repeats parameters, so the two can drift, and it needs backend model changes.
The UI schema in a separate file
Two fetches per policy, a new path for custom policies, and the same drift.
Flat keys, such as x-wso2-policy-ui-widget
It works the same way. One nested key mirrors a uiSchema node and is one key to strip and allowlist.
An explicit visibility hint, such as visibleWhen
The condition can drift from the rule the gateway enforces.
only plain values, and widgets only from our registry;
no ui:field, templates, ui:options.mui, ui:style or ui:classNames, and Markdown stays off.
Built-in and custom policies get the same rules.
Compatibility. The gateway's validator (gojsonschema) ignores the hints, and so does the API control plane portal's own policy form. Adding hints or if/then rules to a policy means a new policy version. A rule should only enforce what the policy code already requires.
Rendering all 69 policies with RJSF. 24 definitions use anyOf, 7 use oneOf and 9 use allOf. Today's editor stays as the fallback, and a CI test renders every definition before the switch.
Field order. Custom definitions pass through Go maps, which don't keep key order, so x-wso2-policy-property-order decides the order. It's in 2 policies today, but nothing reads it yet.
Size and reuse. RJSF loads as a separate chunk of about 143 KB gzipped. The split and the generator are plain TypeScript, so another portal can reuse them.
Trade-off. The form can't take a different shape from what the gateway validates. The form copy covers conditional fields and rule-only branches.
Area/PoliciesIssues related to any policy, policy hub, policy engine etcArea/AIPoliciesIssues related to policies,guardrails in AI GatewayArea/AIWorkspaceIssues related to AI Workspace
1 participant
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
Policy forms in the AI Workspace are generated from each policy's
parametersJSON Schema, and policy authors have no control over how they look or behave. This proposal lets a policy carry optional UI hints insideparameters, under one key,x-wso2-policy-ui. The AI Workspace renders the form with react-jsonschema-form (RJSF), and generates sensible defaults for every field without a hint.parametersstays the single source of truth. The gateway validates exactly what it validates today. No API, model or database change is needed.Related: #3582 (feature request), #3583 (prototype, to be updated to this design).
What is the problem that we are trying to solve?
A policy's form is generated from its
parametersJSON Schema, and the policy author has no say in how it looks or behaves:criteriaandblockOn, which only apply to other question types (Figure 1).Figure 1: TypeSafe Jev Content Safety v0.8 in today's editor (left) and in the RJSF prototype from #3583 (middle and right).
Who are we solving the problem for?
Why should it be solved?
Proposed solution
UI hints live inside
parameters, on the fields they describe, under one optional key:x-wso2-policy-ui.flowchart LR D["policy-definition.yaml<br/>parameters (JSON Schema)<br/>+ optional x-wso2-policy-ui hints"] subgraph W[AI Workspace] direction LR S1["1. Split schema<br/>hints to uiSchema"] --> S2["2. Fill defaults"] --> S3["3. Render with RJSF"] --> S4["4. Check against parameters"] end G["Gateway<br/>validates params against parameters<br/>and ignores the hints"] D -->|Policy Hub or Platform API| S1 S4 -->|params| G D -.->|the same parameters| GFor each policy, the AI Workspace:
parametersbefore saving. The saved params have the same shape as today.No API, model or database change is needed. Built-in definitions come from Policy Hub as YAML, and the gateway manifest already carries the full
parametersblock of custom policies. So theUImodel field and the Platform API changes in #3583 are dropped.Authoring
Hint keys are RJSF uiSchema options without the
ui:prefix, pluserrorMessage:widget,placeholder,help,orderandenumNamesbecomeui:<name>at the field's path.errorMessagegoes into the form copy as the ajv-errors keyword.titleanddescriptionkeywords.x-wso2-policy-advanced-param,x-wso2-policy-deprecated-paramandx-wso2-policy-property-orderkeys stay as they are.Generated defaults
A policy with no hints still gets a complete form, so released policies need no change. The generator:
titleanddescription, or puts the key in words;x-wso2-policy-property-orderfor field order;requiredcheck, because Ajv reports a missing field on the parent;anyOf/oneOf, such as "request or response is required", out of the form copy, so RJSF doesn't draw them as option pickers. The check on save still enforces them.Conditional fields
Authors write plain JSON Schema. The field stays in
properties, and anif/thennames it:The gateway then requires
criteriafor score and choice questions. The form copy moves the field into thethenbranch, so RJSF shows it only when that branch applies.The field must not be declared only inside
then. WithadditionalProperties: false, the gateway rejects it (Additional property criteria is not allowed).Validation
Live checks run on the form copy, with the custom messages. The save is checked against
parameters.Figure 2: custom error messages in the RJSF prototype (TypeSafe Jev Model Routing).
Alternatives considered
parameters, so the two can drift, and it needs backend model changes.x-wso2-policy-ui-widgetvisibleWhenThe challenges and how the design handles them
Security. Custom definitions are user-authored, so hints are reduced to the allowlist from Render a policy's optional form with react-jsonschema-form in the AI Workspace #3583:
ui:field, templates,ui:options.mui,ui:styleorui:classNames, and Markdown stays off.Built-in and custom policies get the same rules.
Compatibility. The gateway's validator (
gojsonschema) ignores the hints, and so does the API control plane portal's own policy form. Adding hints orif/thenrules to a policy means a new policy version. A rule should only enforce what the policy code already requires.Rendering all 69 policies with RJSF. 24 definitions use
anyOf, 7 useoneOfand 9 useallOf. Today's editor stays as the fallback, and a CI test renders every definition before the switch.Field order. Custom definitions pass through Go maps, which don't keep key order, so
x-wso2-policy-property-orderdecides the order. It's in 2 policies today, but nothing reads it yet.Size and reuse. RJSF loads as a separate chunk of about 143 KB gzipped. The split and the generator are plain TypeScript, so another portal can reuse them.
Trade-off. The form can't take a different shape from what the gateway validates. The form copy covers conditional fields and rule-only branches.
Next steps
Open questions
thenbranch be able to stay visible all the time, through an opt-out hint?All reactions