
business-rule-patterns
by groeimetai
🤖 AI-powered ServiceNow development with 400+ MCP tools. Works with Claude, GPT, Gemini, Ollama & 75+ providers. Deploy widgets, manage incidents, automate workflows - all through natural language. Open-source Build Agent alternative.
SKILL.md
name: business-rule-patterns description: This skill should be used when the user asks to "create a business rule", "before insert", "after update", "async business rule", "business rule not working", "current vs previous", or any Business Rule development. version: 1.0.0 tools:
- snow_create_business_rule
- snow_find_artifact
- snow_edit_artifact
- snow_execute_script_with_output
Business Rule Best Practices for ServiceNow
Business Rules are server-side scripts that execute when records are displayed, inserted, updated, or deleted.
When to Use Each Type
| Type | Timing | Use Case | Performance Impact |
|---|---|---|---|
| Before | Before database write | Validate, modify current record | Low |
| After | After database write | Create related records, notifications | Medium |
| Async | Background (after commit) | Heavy processing, integrations | None (background) |
| Display | When form loads | Modify form display, set defaults | Low |
Available Objects
// In Business Rules, these are always available:
current // The record being operated on
previous // The record BEFORE changes (update/delete only)
gs // GlideSystem utilities
Before Business Rules
Use for validation and field manipulation:
// Prevent update if condition not met
(function executeRule(current, previous) {
if (current.state == 7 && previous.state != 6) {
current.setAbortAction(true);
gs.addErrorMessage('Must resolve before closing');
}
})(current, previous);
// Auto-populate fields
(function executeRule(current, previous) {
if (current.isNewRecord()) {
current.setValue('caller_id', gs.getUserID());
current.setValue('opened_by', gs.getUserID());
}
})(current, previous);
Never do in Before rules:
- Call
current.update()(causes recursion!) - Query other tables (keep it fast)
- External API calls
After Business Rules
Use for related record operations:
// Create child record when priority is P1
(function executeRule(current, previous) {
if (current.priority.changesTo(1)) {
var task = new GlideRecord('task');
task.initialize();
task.setValue('short_description', 'P1 Follow-up: ' + current.number);
task.setValue('parent', current.sys_id);
task.insert();
}
})(current, previous);
// Update parent record
(function executeRule(current, previous) {
var parent = new GlideRecord('problem');
if (parent.get(current.problem_id)) {
parent.setValue('related_incidents', parent.related_incidents + 1);
parent.update();
}
})(current, previous);
Async Business Rules
Use for heavy processing that shouldn't block the transaction:
// External integration
(function executeRule(current, previous) {
var integrator = new ExternalSystemIntegration();
integrator.syncIncident(current.sys_id);
})(current, previous);
// Send custom notification
(function executeRule(current, previous) {
gs.eventQueue('incident.priority.high', current, current.assigned_to, gs.getUserID());
})(current, previous);
Useful Methods
current Methods
current.isNewRecord() // True if insert
current.isValidRecord() // True if record exists
current.getValue('field') // Get field value
current.setValue('field', val) // Set field value
current.setAbortAction(true) // Cancel the operation
current.operation() // 'insert', 'update', 'delete'
current.isActionAborted() // Check if aborted
Field Change Detection
current.priority.changes() // Field changed (any value)
current.priority.changesTo(1) // Changed TO this value
current.priority.changesFrom(3) // Changed FROM this value
current.priority.nil() // Field is empty
previous Comparisons
// Check if field was modified
if (current.state != previous.state) {
gs.info('State changed from ' + previous.state + ' to ' + current.state);
}
// Check specific change
if (current.assigned_to.changes() && !previous.assigned_to.nil()) {
gs.info('Reassignment occurred');
}
Condition Examples
Use conditions to limit when the rule runs:
| Condition | Meaning |
|---|---|
current.active == true | Only active records |
current.isNewRecord() | Only on insert |
current.priority.changes() | Only when priority changes |
gs.hasRole('admin') | Only for admins |
current.assignment_group.nil() | Only when unassigned |
Performance Best Practices
- Use conditions - Limit when the rule runs
- Keep Before rules fast - No queries if possible
- Use Async for integrations - Don't block transactions
- Avoid Display rules - Slows form load
- Set Order - Lower numbers run first (100-500 range)
- Check "when to run" - insert, update, delete, query
Common Patterns
Auto-Assignment
// Before Insert/Update
if (current.assignment_group.changes() && !current.assignment_group.nil()) {
var members = new GroupMembers(current.assignment_group);
current.assigned_to = members.getNextAvailable();
}
Cascade Updates
// After Update
if (current.state.changesTo(7)) { // Closed
var tasks = new GlideRecord('task');
tasks.addQuery('parent', current.sys_id);
tasks.addQuery('state', '!=', 7);
tasks.query();
while (tasks.next()) {
tasks.setValue('state', 7);
tasks.update();
}
}
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon


