About notification-events
A ServiceNow notification events skill for developers, covering event registration and queuing, script actions, email notifications, and queue debugging through ES5 examples.
Key features
- 01Register and queue events
- 02Configure event script actions
- 03Create conditional email notifications
- 04Schedule delayed and reminder events
- 05Query pending events
Use cases
- 01Trigger scripts or notifications from events
- 02Schedule delayed reminders
- 03Queue batch-processing work
- 04Inspect pending items in the event queue
MCP support
The README lists MCP tools for queuing events, querying the event queue, finding event configurations, and testing event scripts.
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill notification-eventsAfter installing, type/notification-eventsin Claude Code to confirm it loaded.
Details
From the project READMENotification Events for ServiceNow
Events trigger notifications, scripts, and workflows in ServiceNow.
Event Architecture
gs.eventQueue() → Event Queue (sysevent)
↓
Event Registry (sysevent_register)
↓
Script Actions (sysevent_script_action)
Notifications (sysevent_email_action)
Key Tables
| Table | Purpose |
|---|---|
sysevent | Event queue |
sysevent_register | Event registry |
sysevent_script_action | Script actions |
sysevent_email_action | Email notifications |
Creating Events (ES5)
Register Event
// Register event in sysevent_register (ES5 ONLY!)
var event = new GlideRecord("sysevent_register")
event.initialize()
event.setValue("event_name", "x_myapp.incident.escalated")
event.setValue("table", "incident")
event.setValue("description", "Fired when an incident is escalated")
event.setValue("fired_by", "Business Rules, Scripts")
// Parameters
event.setValue("parm1", "escalation_level")
event.setValue("parm2", "previous_group")
event.insert()
Queue Event
// Queue event from script (ES5 ONLY!)
// gs.eventQueue(event_name, gr, parm1, parm2)
// In a Business Rule
;(function executeRule(current, previous) {
// Check if escalated
if (current.escalation.changesTo("1")) {
gs.eventQueue(
"x_myapp.incident.escalated",
current,
current.getValue("escalation"),
previous.assignment_group.getDisplayValue(),
)
}
})(current, previous)
Event Parameters
// Access event parameters in script action (ES5 ONLY!)
// event.parm1 = first parameter
// event.parm2 = second parameter
// In Script Action
;(function executeEvent(event) {
var escalationLevel = event.parm1
var previousGroup = event.parm2
var incident = event.getGlideRecord()
gs.info(
"Incident " + incident.getValue("number") + " escalated to level " + escalationLevel + " from " + previousGroup,
)
// Perform action based on event
if (escalationLevel === "1") {
notifyManager(incident)
} else if (escalationLevel === "2") {
notifyDirector(incident)
} else if (escalationLevel === "3") {
notifyVP(incident)
}
})(event)
Script Actions (ES5)
Create Script Action
// Create script action for event (ES5 ONLY!)
var action = new GlideRecord("sysevent_script_action")
action.initialize()
action.setValue("name", "Handle Incident Escalation")
action.setValue("event_name", "x_myapp.incident.escalated")
action.setValue("active", true)
// Condition (optional)
action.setValue("condition", "event.parm1 >= 2")
// Script (ES5 ONLY!)
action.setValue(
"script",
"(function executeEvent(event) {\n" +
" var incident = event.getGlideRecord();\n" +
" var escalationLevel = event.parm1;\n" +
" \n" +
" // Create escalation task\n" +
' var task = new GlideRecord("task");\n' +
" task.initialize();\n" +
" task.parent = incident.getUniqueValue();\n" +
' task.short_description = "Review escalated incident";\n' +
" task.assignment_group = getEscalationGroup(escalationLevel);\n" +
" task.insert();\n" +
" \n" +
' gs.info("Created escalation task for " + incident.number);\n' +
"})(event);",
)
action.insert()
Delayed Event
// Queue event with delay (ES5 ONLY!)
// Will be processed after specified time
var delay = new GlideDateTime()
delay.addSeconds(3600) // 1 hour delay
var event = new GlideRecord("sysevent")
event.initialize()
event.setValue("name", "x_myapp.reminder.send")
event.setValue("instance", recordSysId)
event.setValue("table", "incident")
event.setValue("parm1", "first_reminder")
event.setValue("parm2", "")
event.setValue("claimed", false)
event.setValue("process_on", delay)
event.insert()
Email Notifications (ES5)
Create Email Action
// Create notification for event (ES5 ONLY!)
var notification = new GlideRecord("sysevent_email_action")
notification.initialize()
notification.setValue("name", "Incident Escalation Notification")
notification.setValue("event_name", "x_myapp.incident.escalated")
notification.setValue("active", true)
// Recipients
notification.setValue("recipient_users", "")
notification.setValue("recipient_groups", getGroupSysId("IT Management"))
notification.setValue("send_self", false)
// Use event.parm1 to get escalation manager
notification.setValue("recipient_fields", "assignment_group.manager")
// Email content
notification.setValue("subject", "Incident ${number} Escalated - Level ${event.parm1}")
notification.setValue(
"message_html",
"<p>Incident <b>${number}</b> has been escalated.</p>" +
"<p>Short Description: ${short_description}</p>" +
"<p>Escalation Level: ${event.parm1}</p>" +
"<p>Previous Group: ${event.parm2}</p>" +
'<p><a href="${URI_REF}">View Incident</a></p>',
)
notification.insert()
Conditional Notification
// Notification with advanced condition (ES5 ONLY!)
var notification = new GlideRecord("sysevent_email_action")
notification.initialize()
notification.setValue("name", "VIP Incident Alert")
notification.setValue("event_name", "incident.created")
// Advanced condition script
notification.setValue("advanced_condition", true)
notification.setValue("condition", "current.caller_id.vip == true && current.priority <= 2")
// Send to specific recipients for VIP
notification.setValue("recipient_groups", getGroupSysId("VIP Support"))
notification.insert()
Common Event Patterns (ES5)
Reminder Event
// Schedule reminder events (ES5 ONLY!)
function scheduleReminder(tableName, recordSysId, reminderType, delayMinutes) {
var eventTime = new GlideDateTime()
eventTime.addSeconds(delayMinutes * 60)
var reminder = new GlideRecord("sysevent")
reminder.initialize()
reminder.setValue("name", "x_myapp.reminder")
reminder.setValue("instance", recordSysId)
reminder.setValue("table", tableName)
reminder.setValue("parm1", reminderType)
reminder.setValue("process_on", eventTime)
reminder.insert()
return reminder.getUniqueValue()
}
// Cancel scheduled reminder
function cancelReminder(eventSysId) {
var reminder = new GlideRecord("sysevent")
if (reminder.get(eventSysId)) {
reminder.deleteRecord()
return true
}
return false
}
Batch Processing Event
// Queue batch processing (ES5 ONLY!)
// Business Rule: after, insert, u_import_batch
;(function executeRule(current, previous) {
// Queue processing for each record in batch
var record = new GlideRecord("u_import_record")
record.addQuery("batch", current.getUniqueValue())
record.query()
while (record.next()) {
gs.eventQueue("x_myapp.import.process_record", record, current.getUniqueValue(), "")
}
// Queue completion check
var delay = new GlideDateTime()
delay.addSeconds(300) // Check in 5 minutes
var event = new GlideRecord("sysevent")
event.initialize()
event.setValue("name", "x_myapp.import.check_complete")
event.setValue("instance", current.getUniqueValue())
event.setValue("table", "u_import_batch")
event.setValue("process_on", delay)
event.insert()
})(current, previous)
State Change Event
// Generic state change event (ES5 ONLY!)
// Business Rule: after, update
;(function executeRule(current, previous) {
if (current.state.changes()) {
gs.eventQueue(
"x_myapp." + current.getTableName() + ".state_change",
current,
previous.getValue("state"),
current.getValue("state"),
)
}
})(current, previous)
Event Debugging (ES5)
Check Event Queue
// Query pending events (ES5 ONLY!)
function getPendingEvents(eventName) {
var events = []
var event = new GlideRecord("sysevent")
event.addQuery("name", eventName)
event.addQuery("claimed", false)
event.orderByDesc("sys_created_on")
event.setLimit(100)
event.query()
while (event.next()) {
events.push({
sys_id: event.getUniqueValue(),
name: event.getValue("name"),
instance: event.getValue("instance"),
parm1: event.getValue("parm1"),
parm2: event.getValue("parm2"),
process_on: event.getValue("process_on"),
created: event.getValue("sys_created_on"),
})
}
return events
}
MCP Tool Integration
Available Tools
| Tool | Purpose |
|---|---|
snow_create_event | Queue events |
snow_query_table | Query event queue |
snow_artifact_manage (action='find') | Find event configurations |
snow_execute_script | Test event scripts |
Example Workflow
// 1. Queue an event
await snow_create_event({
name: "x_myapp.test.event",
table: "incident",
instance: incidentSysId,
parm1: "test_value",
})
// 2. Check event queue
await snow_query_table({
table: "sysevent",
query: "name=x_myapp.test.event^claimed=false",
fields: "name,instance,parm1,parm2,process_on",
})
// 3. Find script actions
await snow_query_table({
table: "sysevent_script_action",
query: "event_nameLIKEx_myapp",
fields: "name,event_name,active,condition",
})
Best Practices
- Namespace Events - Use app prefix (x_myapp.*)
- Register Events - Document in sysevent_register
- Meaningful Names - Clear event purpose
- Parameters - Use parm1/parm2 wisely
- Conditions - Filter before processing
- Async Processing - Don't block transactions
- Error Handling - Handle script failures
- ES5 Only - No modern JavaScript syntax
Comments
Markdown supported