incident-management
SKILL.md
Incident Management for ServiceNow
Incident Management restores normal service operation as quickly as possible while minimizing business impact.
Incident Lifecycle
New (1)
↓
In Progress (2)
↓ ← On Hold (3)
Resolved (6)
↓
Closed (7)
Cancelled (8) ← Can occur from New/In Progress
Key Tables
| Table | Purpose |
|---|---|
incident |
Incident records |
incident_task |
Sub-tasks for incidents |
incident_alert |
Related alerts |
problem |
Related problems |
Creating Incidents (ES5)
Basic Incident Creation
// Create incident (ES5 ONLY!)
var incident = new GlideRecord("incident")
incident.initialize()
// Required fields
incident.setValue("caller_id", callerSysId)
incident.setValue("short_description", "Email not working")
incident.setValue("description", "User cannot send or receive emails since this morning")
// Classification
incident.setValue("category", "software")
incident.setValue("subcategory", "email")
incident.setValue("impact", 2)
incident.setValue("urgency", 2)
// Priority is calculated automatically from impact/urgency
// Assignment
incident.setValue("assignment_group", getGroupSysId("Email Support"))
// Optional: affected CI
incident.setValue("cmdb_ci", emailServerSysId)
var incidentSysId = incident.insert()
gs.info("Created incident: " + incident.getValue("number"))
Priority Matrix
// Priority calculation (ES5 ONLY!)
// Priority = Impact x Urgency matrix
var priorityMatrix = {
"1-1": 1, // High Impact + High Urgency = Critical
"1-2": 2, // High Impact + Medium Urgency = High
"1-3": 3, // High Impact + Low Urgency = Moderate
"2-1": 2, // Medium Impact + High Urgency = High
"2-2": 3, // Medium Impact + Medium Urgency = Moderate
"2-3": 4, // Medium Impact + Low Urgency = Low
"3-1": 3, // Low Impact + High Urgency = Moderate
"3-2": 4, // Low Impact + Medium Urgency = Low
"3-3": 5, // Low Impact + Low Urgency = Planning
}
function calculatePriority(impact, urgency) {
var key = impact + "-" + urgency
return priorityMatrix[key] || 4
}
Incident Assignment (ES5)
Auto-Assignment Rules
// Assignment rule script (ES5 ONLY!)
// Business Rule: before, insert, incident
;(function executeRule(current, previous) {
// Skip if already assigned
if (current.assignment_group) {
return
}
var group = determineAssignmentGroup(current)
if (group) {
current.assignment_group = group
// Optionally assign to on-call
var onCallUser = getOnCallUser(group)
if (onCallUser) {
current.assigned_to = onCallUser
}
}
})(current, previous)
function determineAssignmentGroup(incident) {
var category = incident.getValue("category")
var subcategory = incident.getValue("subcategory")
// Category-based assignment
var mapping = {
network: "Network Support",
hardware: "Desktop Support",
"software-email": "Email Support",
"software-erp": "ERP Support",
database: "Database Admins",
}
var key = category
if (subcategory) {
key = category + "-" + subcategory
}
var groupName = mapping[key] || mapping[category] || "Service Desk"
var group = new GlideRecord("sys_user_group")
if (group.get("name", groupName)) {
return group.getUniqueValue()
}
return null
}
Reassignment with Tracking
// Track reassignments (ES5 ONLY!)
// Business Rule: before, update, incident
;(function executeRule(current, previous) {
// Check if assignment group changed
if (current.assignment_group.changes()) {
// Increment reassignment count
var count = parseInt(current.getValue("reassignment_count"), 10) || 0
current.reassignment_count = count + 1
// Add work note
current.work_notes =
"Reassigned from " +
previous.assignment_group.getDisplayValue() +
" to " +
current.assignment_group.getDisplayValue()
// Alert if excessive reassignments
if (count >= 3) {
gs.eventQueue("incident.excessive.reassignments", current, count.toString(), "")
}
}
})(current, previous)
Major Incident Management (ES5)
Declare Major Incident
// Declare major incident (ES5 ONLY!)
function declareMajorIncident(incidentSysId, reason) {
var incident = new GlideRecord("incident")
if (!incident.get(incidentSysId)) {
return false
}
// Set major incident flag
incident.setValue("major_incident_state", "confirmed")
incident.setValue("priority", 1)
// Set major incident fields
incident.setValue("u_major_incident_start", new GlideDateTime())
incident.setValue("u_major_incident_reason", reason)
// Assign to Major Incident team
var miTeam = new GlideRecord("sys_user_group")
if (miTeam.get("name", "Major Incident Team")) {
incident.setValue("assignment_group", miTeam.getUniqueValue())
}
// Add work note
incident.work_notes = "MAJOR INCIDENT DECLARED\nReason: " + reason
incident.update()
// Trigger notifications
gs.eventQueue("incident.major.declared", incident, "", "")
// Create bridge call record
createBridgeCall(incident)
return true
}
function createBridgeCall(incident) {
var bridge = new GlideRecord("u_bridge_call")
bridge.initialize()
bridge.setValue("u_incident", incident.getUniqueValue())
bridge.setValue("u_dial_in", "1-800-555-0123")
bridge.setValue("u_pin", generatePin())
bridge.setValue("u_start_time", new GlideDateTime())
bridge.insert()
}
Major Incident Communication
// Send major incident update (ES5 ONLY!)
function sendMajorIncidentUpdate(incidentSysId, updateText, recipientGroups) {
var incident = new GlideRecord("incident")
if (!incident.get(incidentSysId)) {
return
}
// Add to work notes
incident.work_notes = "MAJOR INCIDENT UPDATE:\n" + updateText
incident.update()
// Build recipient list
var recipients = []
for (var i = 0; i < recipientGroups.length; i++) {
var members = getGroupMembers(recipientGroups[i])
recipients = recipients.concat(members)
}
// Send notification
var eventParams = JSON.stringify({
update: updateText,
recipients: recipients,
})
gs.eventQueue("incident.major.update", incident, eventParams, "")
}
Incident Escalation (ES5)
Time-Based Escalation
// Escalation script for scheduled job (ES5 ONLY!)
;(function executeScheduledJob() {
var LOG_PREFIX = "[IncidentEscalation] "
// Find incidents needing escalation
var now = new GlideDateTime()
// P1 not acknowledged in 15 minutes
escalateUnacknowledged("1", 15)
// P2 not acknowledged in 30 minutes
escalateUnacknowledged("2", 30)
// P1 not resolved in 4 hours
escalateUnresolved("1", 240)
// P2 not resolved in 8 hours
escalateUnresolved("2", 480)
function escalateUnacknowledged(priority, minutes) {
var threshold = new GlideDateTime()
threshold.addSeconds(-minutes * 60)
var gr = new GlideRecord("incident")
gr.addQuery("priority", priority)
gr.addQuery("state", 1) // New
gr.addQuery("sys_created_on", "<", threshold)
gr.addNullQuery("assigned_to")
gr.query()
while (gr.next()) {
gs.info(LOG_PREFIX + "Escalating unacknowledged P" + priority + ": " + gr.number)
gr.escalation = 1
gr.work_notes = "Auto-escalated: Not acknowledged within " + minutes + " minutes"
gr.update()
gs.eventQueue("incident.escalation.unacknowledged", gr, priority, "")
}
}
function escalateUnresolved(priority, minutes) {
var threshold = new GlideDateTime()
threshold.addSeconds(-minutes * 60)
var gr = new GlideRecord("incident")
gr.addQuery("priority", priority)
gr.addQuery("state", "IN", "1,2") // New or In Progress
gr.addQuery("sys_created_on", "<", threshold)
gr.query()
while (gr.next()) {
var currentEsc = parseInt(gr.getValue("escalation"), 10) || 0
if (currentEsc < 3) {
gr.escalation = currentEsc + 1
gr.work_notes = "Auto-escalated: Not resolved within target time"
gr.update()
notifyNextLevel(gr)
}
}
}
function notifyNextLevel(incident) {
var group = incident.assignment_group.getRefRecord()
if (group.manager) {
gs.eventQueue("incident.escalation.manager", incident, group.manager, "")
}
}
})()
Incident Resolution (ES5)
Resolve Incident
// Resolve incident with validation (ES5 ONLY!)
function resolveIncident(incidentSysId, resolution) {
var incident = new GlideRecord("incident")
if (!incident.get(incidentSysId)) {
return { success: false, message: "Incident not found" }
}
// Validate state transition
var currentState = incident.getValue("state")
if (currentState === "6" || currentState === "7") {
return { success: false, message: "Incident already resolved/closed" }
}
// Validate resolution fields
if (!resolution.code) {
return { success: false, message: "Resolution code is required" }
}
if (!resolution.notes) {
return { success: false, message: "Resolution notes are required" }
}
// Update incident
incident.setValue("state", 6) // Resolved
incident.setValue("resolution_code", resolution.code)
incident.setValue("close_notes", resolution.notes)
incident.setValue("resolved_at", new GlideDateTime())
incident.setValue("resolved_by", gs.getUserID())
// Link to problem/known error if provided
if (resolution.problem) {
incident.setValue("problem_id", resolution.problem)
}
if (resolution.knowledge) {
incident.setValue("u_resolution_article", resolution.knowledge)
}
incident.update()
// Notify caller
gs.eventQueue("incident.resolved", incident, "", "")
return {
success: true,
message: "Incident resolved",
number: incident.getValue("number"),
}
}
Incident Metrics (ES5)
Calculate MTTR
// Calculate Mean Time to Resolve (ES5 ONLY!)
function calculateMTTR(startDate, endDate, filters) {
var ga = new GlideAggregate("incident")
ga.addQuery("resolved_at", ">=", startDate)
ga.addQuery("resolved_at", "<=", endDate)
ga.addQuery("state", "IN", "6,7")
// Apply optional filters
if (filters.priority) {
ga.addQuery("priority", filters.priority)
}
if (filters.category) {
ga.addQuery("category", filters.category)
}
ga.addAggregate("AVG", "calendar_duration")
ga.addAggregate("COUNT")
ga.query()
if (ga.next()) {
var avgDuration = ga.getAggregate("AVG", "calendar_duration")
var count = ga.getAggregate("COUNT")
// Convert to hours
var durationObj = new GlideDuration(avgDuration)
var hours = durationObj.getNumericValue() / 3600000
return {
mttr_hours: Math.round(hours * 100) / 100,
incident_count: parseInt(count, 10),
}
}
return { mttr_hours: 0, incident_count: 0 }
}
MCP Tool Integration
Available Tools
| Tool | Purpose |
|---|---|
snow_query_incidents |
Query incident records |
snow_query_table |
Advanced incident queries |
snow_execute_script_with_output |
Test incident scripts |
snow_create_business_rule |
Create incident automation |
Example Workflow
// 1. Query open P1 incidents
await snow_query_incidents({
query: "priority=1^active=true",
fields: "number,short_description,assigned_to,opened_at",
})
// 2. Check incident metrics
await snow_execute_script_with_output({
script: `
var stats = calculateMTTR(gs.beginningOfThisMonth(), gs.endOfThisMonth(), {});
gs.info('MTTR: ' + stats.mttr_hours + ' hours');
`,
})
// 3. Find unassigned incidents
await snow_query_table({
table: "incident",
query: "active=true^assigned_toISEMPTY",
fields: "number,short_description,priority,assignment_group",
})
Best Practices
- Clear Classification - Proper category/subcategory
- Impact Assessment - Accurate impact/urgency
- Assignment Rules - Automated routing
- Escalation Paths - Defined procedures
- Communication - Regular updates
- Resolution Codes - Consistent categorization
- Knowledge Linking - Link to KB articles
- ES5 Only - No modern JavaScript syntax
Weekly Installs
51
Repository
groeimetai/snow-flowGitHub Stars
53
First Seen
Jan 22, 2026
Security Audits
Installed on
claude-code47
gemini-cli47
github-copilot46
codex46
cursor46
opencode46