Install
$ agentstack add skill-happy-technologies-llc-happy-platform-skills-ui-policies ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Catalog UI Policies
Overview
This skill covers creating and managing UI policies for Service Catalog items:
- Creating UI policies with conditions
- Show/hide/mandatory/disabled actions
- Scripted UI policy conditions
- UI Policy Actions and their REST API limitations
- Workarounds for linking actions via background scripts
- Testing and debugging UI policies
When to use: When building dynamic catalog forms that need to show/hide fields, make fields mandatory based on other selections, or implement complex conditional logic.
Who should use this: Catalog administrators and developers building service catalog items with dynamic form behavior.
Prerequisites
- Roles:
catalog_adminoradmin - Access: cataloguipolicy, cataloguipolicyaction, itemoption_new tables
- Knowledge: Basic catalog item structure, variables
- Related Skills:
catalog/variable-managementfor variable creation
Understanding Catalog UI Policies
UI Policy Components
┌─────────────────────────────────────────────────────────┐
│ Catalog UI Policy │
├─────────────────────────────────────────────────────────┤
│ Catalog Item: [reference to sc_cat_item] │
│ Short Description: "Show approval fields for >$1000" │
│ Conditions: amount>1000 │
│ On Load: true Reverse If False: true │
│ Script True: [optional advanced logic] │
│ Script False: [optional reverse logic] │
├─────────────────────────────────────────────────────────┤
│ UI Policy Actions │
├─────────────────────────────────────────────────────────┤
│ Action 1: manager_approval → visible=true, mandatory=true │
│ Action 2: justification → visible=true │
│ Action 3: cost_center → disabled=false │
└─────────────────────────────────────────────────────────┘
UI Policy Evaluation
User Opens Form
│
▼
┌─────────────────┐
│ On Load = true?│───No──► Conditions evaluated only on change
│
Yes
│
▼
┌─────────────────┐
│ Evaluate │
│ Conditions │
└────────┬────────┘
│
┌────┴────┐
│ │
True False
│ │
▼ ▼
┌────────┐ ┌────────────────┐
│ Apply │ │Reverse If False│───Yes──► Apply opposite actions
│Actions │ │ = true? │
└────────┘ └───────┬────────┘
│
No
│
▼
Do nothing
Procedure
Phase 1: Create Basic UI Policy
Step 1.1: Create UI Policy Record
Simple Condition-Based Policy:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy
data:
catalog_item: [catalog_item_sys_id]
short_description: "Show approval fields when amount exceeds $1000"
active: true
on_load: true
reverse_if_false: true
order: 100
global: false
run_scripts: false
Result: Returns sys_id of created UI policy (e.g., policy_sys_id)
Step 1.2: Understand UI Policy Fields
| Field | Type | Description | |-------|------|-------------| | catalogitem | Reference | Target catalog item | | shortdescription | String | Policy name/description | | active | Boolean | Enable/disable policy | | onload | Boolean | Evaluate when form loads | | reverseiffalse | Boolean | Apply opposite when condition false | | order | Integer | Execution order (lower = first) | | global | Boolean | Apply to all catalog items | | runscripts | Boolean | Enable Script True/Script False | | conditions | Conditions | Encoded query against variables |
Phase 2: Add UI Policy Conditions
Step 2.1: Simple Field Condition
Conditions compare variable values using encoded query syntax:
Create Policy with Condition:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy
data:
catalog_item: [catalog_item_sys_id]
short_description: "Show manager approval for external vendors"
conditions: "vendor_type=external"
active: true
on_load: true
reverse_if_false: true
order: 100
Condition Syntax Examples:
| Condition | Meaning | |-----------|---------| | priority=1 | Priority equals 1 | | amount>1000 | Amount greater than 1000 | | category=hardware^urgency=1 | Category is hardware AND urgency is 1 | | department=IT^ORdepartment=Security | Department is IT OR Security | | requested_for.active=true | Referenced user is active | | descriptionISNOTEMPTY | Description has a value | | quantityBETWEEN1@10 | Quantity between 1 and 10 |
Step 2.2: Multiple Conditions (AND/OR)
AND Conditions:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy
data:
catalog_item: [catalog_item_sys_id]
short_description: "Require justification for high-cost IT equipment"
conditions: "department=IT^hardware_type=laptop^estimated_cost>2000"
active: true
on_load: true
reverse_if_false: true
order: 200
OR Conditions:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy
data:
catalog_item: [catalog_item_sys_id]
short_description: "Show security review for sensitive departments"
conditions: "department=Finance^ORdepartment=Legal^ORdepartment=HR"
active: true
on_load: true
reverse_if_false: true
order: 300
Phase 3: Create UI Policy Actions
CRITICAL: UI Policy Actions cannot be fully linked to variables via REST API due to ServiceNow limitations. The catalog_variable field requires special handling.
Step 3.1: Understand the Limitation
When you create a catalog_ui_policy_action via REST API:
- The record is created successfully
- The
catalog_variablefield WILL NOT link properly - The action won't work until manually fixed or updated via background script
Why This Happens:
- The
catalog_variablefield expects a special format:IO:[variable_sys_id] - The REST API doesn't properly resolve this reference type
- This is a known ServiceNow platform limitation
Step 3.2: Create Action Record (Step 1 of 2)
First, create the UI policy action record:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy_action
data:
ui_policy: [policy_sys_id]
visible: true
mandatory: true
disabled: false
Result: Returns action sys_id (e.g., action_sys_id)
Note: The action is created but NOT linked to any variable yet.
Step 3.3: Link Action to Variable (Step 2 of 2)
REQUIRED: Use background script to properly link the action:
Tool: SN-Execute-Background-Script
Parameters:
script: |
// Link UI Policy Action to Catalog Variable
var actionSysId = '[action_sys_id]';
var variableSysId = '[variable_sys_id]';
var gr = new GlideRecord('catalog_ui_policy_action');
if (gr.get(actionSysId)) {
// The catalog_variable field requires IO: prefix
gr.setValue('catalog_variable', 'IO:' + variableSysId);
gr.update();
gs.info('Linked UI policy action ' + actionSysId + ' to variable ' + variableSysId);
} else {
gs.error('UI policy action not found: ' + actionSysId);
}
description: Link UI policy action to catalog variable
Step 3.4: Batch Link Multiple Actions
For multiple actions, batch them in one script:
Tool: SN-Execute-Background-Script
Parameters:
script: |
// Batch link UI Policy Actions
var links = [
{ action: '[action1_sys_id]', variable: '[var1_sys_id]' },
{ action: '[action2_sys_id]', variable: '[var2_sys_id]' },
{ action: '[action3_sys_id]', variable: '[var3_sys_id]' }
];
var success = 0;
var failed = 0;
links.forEach(function(link) {
var gr = new GlideRecord('catalog_ui_policy_action');
if (gr.get(link.action)) {
gr.setValue('catalog_variable', 'IO:' + link.variable);
gr.update();
gs.info('Linked: ' + link.action + ' -> ' + link.variable);
success++;
} else {
gs.error('Action not found: ' + link.action);
failed++;
}
});
gs.info('Batch link complete: ' + success + ' success, ' + failed + ' failed');
description: Batch link UI policy actions to variables
Phase 4: UI Policy Action Types
Step 4.1: Show/Hide Variables
Show a variable when condition is true:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy_action
data:
ui_policy: [policy_sys_id]
visible: true
mandatory: false
disabled: false
Then link to variable using background script (Step 3.3).
Hide a variable (with reverseiffalse):
- Set
visible: truein action - Set
reverse_if_false: trueon policy - When condition is FALSE, variable will be hidden
Step 4.2: Mandatory Actions
Make variable mandatory when condition is true:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy_action
data:
ui_policy: [policy_sys_id]
visible: true
mandatory: true
disabled: false
Common Pattern: Show AND make mandatory:
visible: true- Show the fieldmandatory: true- Require a value- With
reverse_if_false: true- When condition false, field hidden and not required
Step 4.3: Disabled/Read-Only Actions
Make variable read-only when condition is true:
Tool: SN-Create-Record
Parameters:
table_name: catalog_ui_policy_action
data:
ui_policy: [policy_sys_id]
visible: true
mandatory: false
disabled: true
Use Case: Lock calculated fields or display-only values.
Phase 5: Scripted UI Policies
Step 5.1: Enable Script Execution
For complex conditions that can't be expressed in simple encoded queries:
Tool: SN-Update-Record
Parameters:
table_name: catalog_ui_policy
sys_id: [policy_sys_id]
data:
run_scripts: true
script_true: |
// Runs when condition is TRUE
// Access variables via g_form
var amount = g_form.getValue('amount');
var dept = g_form.getValue('department');
if (parseFloat(amount) > 5000 && dept == 'IT') {
// Additional client-side logic
g_form.showFieldMsg('amount', 'Requires CIO approval', 'info');
}
script_false: |
// Runs when condition is FALSE (optional)
g_form.hideFieldMsg('amount');
Step 5.2: Script Examples
Complex Validation:
// script_true
var hardware = g_form.getValue('hardware_type');
var quantity = parseInt(g_form.getValue('quantity')) || 0;
// Show warning for bulk orders
if (hardware == 'laptop' && quantity > 10) {
g_form.showFieldMsg('quantity', 'Bulk orders require procurement approval', 'warning');
}
// Dynamic mandatory based on multiple fields
if (hardware == 'other') {
g_form.setMandatory('other_description', true);
}
Date Validation:
// script_true
var startDate = g_form.getValue('start_date');
var endDate = g_form.getValue('end_date');
if (startDate && endDate) {
var start = new Date(startDate);
var end = new Date(endDate);
if (end 5, require business justification
**Step 1: Get variable sys_ids:**
Tool: SN-Query-Table Parameters: tablename: itemoptionnew query: catitem=[catalogitemsysid] fields: sysid,name,question_text limit: 50
**Step 2: Create Policy 1 - Enterprise License:**
Tool: SN-Create-Record Parameters: tablename: cataloguipolicy data: catalogitem: [catalogitemsysid] shortdescription: "Show approval fields for Enterprise license" conditions: "licensetype=enterprise" active: true onload: true reverseiffalse: true order: 100
Result: policy1sysid
**Step 3: Create Actions for Policy 1:**
Tool: SN-Create-Record Parameters: tablename: cataloguipolicyaction data: uipolicy: [policy1sys_id] visible: true mandatory: true disabled: false
Result: action1asysid (for cost_center)
Tool: SN-Create-Record Parameters: tablename: cataloguipolicyaction data: uipolicy: [policy1sys_id] visible: true mandatory: true disabled: false
Result: action1bsysid (for manager_approval)
**Step 4: Link Actions to Variables:**
Tool: SN-Execute-Background-Script Parameters: script: | var links = [ { action: '[action1asysid]', variable: '[costcentervarsysid]' }, { action: '[action1bsysid]', variable: '[managerapprovalvarsysid]' } ];
links.forEach(function(link) { var gr = new GlideRecord('cataloguipolicyaction'); if (gr.get(link.action)) { gr.setValue('catalogvariable', 'IO:' + link.variable); gr.update(); gs.info('Linked: ' + gr.sys_id); } }); description: Link enterprise license policy actions
**Step 5: Create Policy 2 - Bulk Order:**
Tool: SN-Create-Record Parameters: tablename: cataloguipolicy data: catalogitem: [catalogitemsysid] shortdescription: "Require justification for bulk orders (>5)" conditions: "quantity>5" active: true onload: true reverseif_false: true order: 200
Result: policy2sysid
**Step 6: Create and Link Action for Policy 2:**
Tool: SN-Create-Record Parameters: tablename: cataloguipolicyaction data: uipolicy: [policy2sys_id] visible: true mandatory: true disabled: false
Result: action2sysid
Tool: SN-Execute-Background-Script Parameters: script: | var gr = new GlideRecord('cataloguipolicyaction'); if (gr.get('[action2sysid]')) { gr.setValue('catalogvariable', 'IO:[justificationvarsys_id]'); gr.update(); gs.info('Linked bulk order justification action'); } description: Link bulk order policy action
### Phase 7: Testing and Debugging
#### Step 7.1: Verify UI Policy Configuration
**Query all policies for a catalog item:**
Tool: SN-Query-Table Parameters: tablename: cataloguipolicy query: catalogitem=[catalogitemsysid]^active=true fields: sysid,shortdescription,conditions,onload,reverseiffalse,order,run_scripts limit: 50
**Query all actions for a policy:**
Tool: SN-Query-Table Parameters: tablename: cataloguipolicyaction query: uipolicy=[policysysid] fields: sysid,catalog_variable,visible,mandatory,disabled limit: 20
#### Step 7.2: Debug Action Links
**Check if catalog_variable is properly linked:**
Tool: SN-Query-Table Parameters: tablename: cataloguipolicyaction query: uipolicy=[policysysid] fields: sysid,catalog_variable.name,visible,mandatory,disabled limit: 20
If `catalog_variable.name` is empty, the link failed - run the background script again.
#### Step 7.3: Testing Checklist
**Before Testing:**
- [ ] All UI policies are active
- [ ] All policy actions have linked variables (catalog_variable not empty)
- [ ] Order numbers are set correctly (no conflicts)
- [ ] reverse_if_false is set appropriately
**Test Scenarios:**
1. **On Load:** Open form fresh - verify initial visibility
2. **True Condition:** Set values to make condition true - verify actions apply
3. **False Condition:** Change values to make condition false - verify reverse
4. **Multiple Policies:** Test combinations of conditions
5. **Script Policies:** Verify scripts execute without errors
#### Step 7.4: Common Debug Commands
**Find unlinked actions:**
Tool: SN-Query-Table Parameters: tablename: cataloguipolicyaction query: uipolicy.catalogitem=[catalogitemsysid]^catalogvariableISEMPTY fields: sysid,uipolicy.short_description limit: 50
**Get variable sys_ids by name:**
Tool: SN-Query-Table Parameters: tablename: itemoptionnew query: catitem=[catalogitemsysid]^name=managerapproval fields: sys_id,name
## Tool Usage Summary
| Operation | MCP Tool | Notes |
|-----------|----------|------
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [Happy-Technologies-LLC](https://github.com/Happy-Technologies-LLC)
- **Source:** [Happy-Technologies-LLC/happy-platform-skills](https://github.com/Happy-Technologies-LLC/happy-platform-skills)
- **License:** Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.