SLA Management for ServiceNow
SLA (Service Level Agreement) Management tracks and ensures service commitments are met.
SLA Components
Component Table Purpose
SLA Definition contract_sla SLA rules and conditions
Task SLA task_sla SLA instance on a task
SLA Workflow wf_workflow SLA breach notifications
SLA Schedule cmn_schedule Business hours definition
SLA Flow
Task Created ↓ SLA Definition Conditions Match ↓ Task SLA Record Created ↓ Timer Starts (based on schedule) ↓ SLA Stages: In Progress → Breached (if not met) ↓ Task Resolved/Closed ↓ SLA Achieved or Breached
SLA Definition (ES5)
Create SLA Definition
// Create SLA Definition (ES5 ONLY!) var sla = new GlideRecord("contract_sla") sla.initialize()
// Basic info sla.setValue("name", "P1 Incident Response Time") sla.setValue("type", "SLA") // SLA, OLA, UC sla.setValue("table", "incident")
// Target duration sla.setValue("duration_type", "response") // response or resolution sla.setValue("duration", "PT15M") // 15 minutes (ISO 8601)
// Conditions - when SLA attaches sla.setValue("start_condition", "priority=1^active=true") sla.setValue("stop_condition", "work_notes.changesTo()") sla.setValue("pause_condition", "state=3") // Pause when On Hold sla.setValue("cancel_condition", "state=8") // Cancel when Cancelled
// Schedule (business hours) sla.setValue("schedule", getScheduleSysId("8-5 M-F"))
// Enable sla.setValue("active", true)
sla.insert()
SLA Conditions Explained
// Start Condition: When SLA timer begins // Example: P1 incidents when created var startCondition = "priority=1^active=true^sys_created_onRELATIVEGT@minute@ago@0"
// Stop Condition: When SLA is achieved // Example: When work notes are added (response) or resolved (resolution) var responseStop = "work_notes.changes()" var resolutionStop = "state=6^ORstate=7" // Resolved or Closed
// Pause Condition: Timer pauses // Example: On Hold or Awaiting User Info var pauseCondition = "state=3^ORstate=-5"
// Cancel Condition: SLA cancelled without breach // Example: Incident cancelled or duplicate var cancelCondition = "state=8^ORclose_code=Duplicate"
Task SLA Operations (ES5)
Query Task SLAs
// Find SLAs for an incident (ES5 ONLY!) var incidentSysId = "incident_sys_id"
var taskSla = new GlideRecord("task_sla") taskSla.addQuery("task", incidentSysId) taskSla.query()
while (taskSla.next()) { gs.info( "SLA: " + taskSla.sla.getDisplayValue() + " | Stage: " + taskSla.stage.getDisplayValue() + " | Breached: " + taskSla.getValue("has_breached") + " | Planned End: " + taskSla.getValue("planned_end_time"), ) }
Check SLA Status
// SLA Status Helper (ES5 ONLY!) var SLAHelper = Class.create() SLAHelper.prototype = { initialize: function () {},
/**
- Get SLA status for a task
- @param {string} taskSysId - Task sys_id
- @returns {Array} - Array of SLA status objects */ getSLAStatus: function (taskSysId) { var slaStatuses = []
var taskSla = new GlideRecord("task_sla")
taskSla.addQuery("task", taskSysId)
taskSla.addQuery("active", true)
taskSla.query()
while (taskSla.next()) {
var now = new GlideDateTime()
var plannedEnd = new GlideDateTime(taskSla.getValue("planned_end_time"))
var timeLeft = GlideDateTime.subtract(now, plannedEnd)
slaStatuses.push({
name: taskSla.sla.getDisplayValue(),
stage: taskSla.stage.getDisplayValue(),
hasBreached: taskSla.getValue("has_breached") === "true",
percentageComplete: taskSla.getValue("percentage"),
plannedEnd: taskSla.getValue("planned_end_time"),
timeLeft: this._formatDuration(timeLeft),
isAtRisk: this._isAtRisk(taskSla),
})
}
return slaStatuses
},
/**
- Check if any SLA is at risk (>75% elapsed) */ _isAtRisk: function (taskSla) { var percentage = parseFloat(taskSla.getValue("percentage")) return percentage >= 75 && taskSla.getValue("has_breached") !== "true" },
_formatDuration: function (duration) { var totalSeconds = duration.getNumericValue() / 1000 var hours = Math.floor(totalSeconds / 3600) var minutes = Math.floor((totalSeconds % 3600) / 60) return hours + "h " + minutes + "m" },
type: "SLAHelper", }
Pause/Resume SLA
// Pause SLAs when incident goes On Hold (ES5 ONLY!) // Business Rule: after, update, incident
;(function executeRule(current, previous) { // Check if state changed to On Hold if (current.state.changesTo("3")) { pauseIncidentSLAs(current.getUniqueValue()) }
// Check if state changed from On Hold if (previous.state == "3" && current.state != "3") { resumeIncidentSLAs(current.getUniqueValue()) } })(current, previous)
function pauseIncidentSLAs(incidentId) { var taskSla = new GlideRecord("task_sla") taskSla.addQuery("task", incidentId) taskSla.addQuery("active", true) taskSla.addQuery("stage", "!=", "breached") taskSla.query()
while (taskSla.next()) { var slaDef = new GlideRecord("contract_sla") if (slaDef.get(taskSla.getValue("sla"))) { // Only pause if SLA has pause condition if (slaDef.getValue("pause_condition")) { taskSla.pause = true taskSla.pause_time = new GlideDateTime() taskSla.update() } } } }
SLA Workflows
Breach Notification Script (ES5)
// SLA Workflow Activity: Send breach notification (ES5 ONLY!) ;(function executeActivity() { var taskSla = current var task = taskSla.task.getRefRecord()
// Get escalation recipients var recipients = []
// Add assigned user if (task.assigned_to) { recipients.push(task.assigned_to.getValue("email")) }
// Add assignment group manager if (task.assignment_group) { var group = task.assignment_group.getRefRecord() if (group.manager) { recipients.push(group.manager.email) } }
// Send notification if (recipients.length > 0) { gs.eventQueue("sla.breach.notification", task, recipients.join(","), taskSla.sla.getDisplayValue()) } })()
SLA Escalation Rules
// SLA Escalation Script Include (ES5 ONLY!) var SLAEscalation = Class.create() SLAEscalation.prototype = { initialize: function () {},
/**
- Escalate breached SLA */ escalateBreached: function (taskSlaSysId) { var taskSla = new GlideRecord("task_sla") if (!taskSla.get(taskSlaSysId)) { return false }
var task = taskSla.task.getRefRecord()
// Increase priority
var currentPriority = parseInt(task.getValue("priority"), 10)
if (currentPriority > 1) {
task.setValue("priority", currentPriority - 1)
}
// Set escalation flag
task.setValue("escalation", 1)
// Add work note
task.work_notes = "SLA Breached: " + taskSla.sla.getDisplayValue() + "\nAutomatic escalation applied."
task.update()
// Notify on-call
this._notifyOnCall(task)
return true
},
_notifyOnCall: function (task) { // Get on-call schedule var oncall = new OnCallRotation() var onCallUser = oncall.getOnCallUser(task.assignment_group)
if (onCallUser) {
gs.eventQueue("sla.oncall.notification", task, onCallUser.sys_id, "")
}
},
type: "SLAEscalation", }
SLA Reports
SLA Compliance Query (ES5)
// Calculate SLA compliance rate (ES5 ONLY!) function getSLAComplianceRate(slaName, startDate, endDate) { var ga = new GlideAggregate("task_sla") ga.addQuery("sla.name", slaName) ga.addQuery("end_time", ">=", startDate) ga.addQuery("end_time", "<=", endDate) ga.addQuery("active", false) // Completed SLAs only ga.addAggregate("COUNT") ga.addAggregate("COUNT", "has_breached") ga.groupBy("has_breached") ga.query()
var total = 0 var breached = 0
while (ga.next()) { var count = parseInt(ga.getAggregate("COUNT"), 10) total += count if (ga.getValue("has_breached") === "true") { breached = count } }
if (total === 0) { return { compliance: 100, total: 0, breached: 0 } }
var achieved = total - breached var compliance = Math.round((achieved / total) * 100 * 10) / 10
return { compliance: compliance, total: total, achieved: achieved, breached: breached, } }
// Usage var stats = getSLAComplianceRate("P1 Incident Response", gs.beginningOfThisMonth(), gs.endOfThisMonth()) gs.info("P1 Response SLA Compliance: " + stats.compliance + "%")
MCP Tool Integration
Available Tools
Tool Purpose
snow_find_artifact
Find SLA definitions
snow_query_table
Query task_sla records
snow_execute_script_with_output
Test SLA scripts
snow_create_business_rule
Create SLA triggers
Example Workflow
// 1. Find existing SLAs await snow_find_artifact({ type: "contract_sla", name: "P1", })
// 2. Query SLA breaches await snow_query_table({ table: "task_sla", query: "has_breached=true^end_time>=javascript:gs.beginningOfThisMonth()", fields: "sla,task,end_time,business_duration", })
// 3. Check SLA compliance await snow_execute_script_with_output({ script: 'var stats = getSLAComplianceRate("P1 Response", gs.beginningOfThisMonth(), gs.endOfThisMonth()); gs.info(JSON.stringify(stats));', })
Best Practices
-
Clear Names - "P1 Incident Response 15min"
-
Business Hours - Use appropriate schedules
-
Pause Conditions - Pause for external waits
-
Escalation - Notify before breach
-
Metrics - Track compliance rates
-
Testing - Test with various scenarios
-
Documentation - Document SLA terms
-
ES5 Only - No modern JavaScript syntax