Loading...
Loading...
This skill should be used when the user asks to "create application", "scoped application", "custom app", "application scope", "x_" prefix, "app scope", "application properties", "cross-scope", or any ServiceNow scoped application development.
npx skill4agent add groeimetai/snow-flow scoped-apps| Feature | Global Scope | Scoped App |
|---|---|---|
| Naming conflicts | Possible | Prevented (x_prefix) |
| Portability | Difficult | Easy (Update Sets) |
| Security | Open | Controlled (Cross-scope) |
| Store publishing | No | Yes |
| Dependencies | Implicit | Explicit |
1. Navigate: System Applications > Studio
2. Click: Create Application
3. Enter:
- Name: "My Custom App"
- Scope: "x_mycom_myapp" (auto-generated)
- Version: 1.0.0
4. Configure:
- Runtime access: Check tables needing cross-scope accesssnow_create_application({
name: "My Custom Application",
scope: "x_mycom_custom",
version: "1.0.0",
description: "Custom application for..."
});x_[vendor]_[app]
Examples:
- x_acme_hr (ACME Corp HR App)
- x_mycom_inventory (My Company Inventory)
- x_snc_global (ServiceNow Global)// Scoped tables are automatically prefixed
// Table name in Studio: "task_tracker"
// Actual table name: "x_mycom_myapp_task_tracker"
// Creating records
var gr = new GlideRecord('x_mycom_myapp_task_tracker');
gr.initialize();
gr.setValue('name', 'My Task');
gr.insert();var TaskManager = Class.create();
TaskManager.prototype = {
initialize: function() {
this.tableName = 'x_mycom_myapp_task_tracker';
},
createTask: function(name, description) {
var gr = new GlideRecord(this.tableName);
gr.initialize();
gr.setValue('name', name);
gr.setValue('description', description);
return gr.insert();
},
// Mark as accessible from other scopes
// Requires: "Accessible from: All application scopes"
getTask: function(sysId) {
var gr = new GlideRecord(this.tableName);
if (gr.get(sysId)) {
return {
name: gr.getValue('name'),
description: gr.getValue('description')
};
}
return null;
},
type: 'TaskManager'
};// From scope: x_mycom_otherapp
// Calling: x_mycom_myapp.TaskManager
// Option 1: Direct call (if accessible)
var tm = new x_mycom_myapp.TaskManager();
var task = tm.getTask(sysId);
// Option 2: GlideScopedEvaluator
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable('sysId', sysId);
var result = evaluator.evaluateScript(
'x_mycom_myapp',
'new TaskManager().getTask(sysId)'
);// Check if cross-scope access is allowed
var gr = new GlideRecord('x_other_app_table');
if (!gr.isValid()) {
gs.error('No access to x_other_app_table');
return;
}
// If accessible, query normally
gr.addQuery('active', true);
gr.query();// In Application > Properties
// Name: x_mycom_myapp.default_priority
// Value: 3
// Type: string
// In Application > Modules
// Create "Properties" module pointing to:
// /sys_properties_list.do?sysparm_query=name=x_mycom_myapp// Get property value
var defaultPriority = gs.getProperty('x_mycom_myapp.default_priority', '3');
// Set property value (requires admin)
gs.setProperty('x_mycom_myapp.default_priority', '2');x_mycom_myapp/
├── Tables
│ ├── x_mycom_myapp_task
│ └── x_mycom_myapp_config
├── Script Includes
│ ├── TaskManager
│ └── ConfigUtils
├── Business Rules
│ └── Validate Task
├── UI Pages
│ └── task_dashboard
├── REST API
│ └── Task API
├── Scheduled Jobs
│ └── Daily Cleanup
└── Application Properties
├── default_priority
└── enable_notifications// Resource: /api/x_mycom_myapp/tasks
// HTTP Method: GET
(function process(request, response) {
var tasks = [];
var gr = new GlideRecord('x_mycom_myapp_task_tracker');
gr.addQuery('active', true);
gr.query();
while (gr.next()) {
tasks.push({
sys_id: gr.getUniqueValue(),
name: gr.getValue('name'),
status: gr.getValue('status')
});
}
response.setBody({
result: tasks,
count: tasks.length
});
})(request, response);curl -X GET \
"https://instance.service-now.com/api/x_mycom_myapp/tasks" \
-H "Authorization: Bearer token"Application > Dependencies
Add:
- sn_hr_core (HR Core)
- sn_cmdb (CMDB)// Check if plugin is active
if (GlidePluginManager.isActive('com.snc.hr.core')) {
// HR Core is available
var hrCase = new sn_hr_core.hr_case();
}□ All tables have proper ACLs
□ No hard-coded sys_ids
□ No hard-coded instance URLs
□ All dependencies declared
□ Properties have default values
□ Documentation complete
□ Test cases pass
□ No global scope modifications
□ Update Set tested on clean instanceMajor.Minor.Patch
1.0.0 - Initial release
1.1.0 - New feature added
1.1.1 - Bug fix
2.0.0 - Breaking change| Mistake | Problem | Solution |
|---|---|---|
| Global modifications | Won't deploy cleanly | Keep changes in scope |
| Hard-coded sys_ids | Fails on other instances | Use properties or lookups |
| Missing ACLs | Security vulnerabilities | Create ACLs for all tables |
| No error handling | Silent failures | Add try/catch, logging |
| Accessing global tables directly | Upgrade conflicts | Use references, not copies |