Agent Skills: Change Management for ServiceNow

This skill should be used when the user asks to "create change", "change request", "CAB", "change approval", "change task", "RFC", "normal change", "emergency change", or any ServiceNow Change Management development.

servicenowID: groeimetai/snow-flow/change-management

Repository

groeimetaiLicense: NOASSERTION
5722

Install this agent skill to your local

pnpm dlx add-skill https://github.com/groeimetai/snow-flow/tree/HEAD/packages/opencode/src/bundled-skills/change-management

Skill Files

Browse the full folder contents for change-management.

Download Skill

Loading file tree…

packages/opencode/src/bundled-skills/change-management/SKILL.md

Skill Metadata

Name
change-management
Description
This skill should be used when the user asks to "create change", "change request", "CAB", "change approval", "change task", "RFC", "normal change", "emergency change", or any ServiceNow Change Management development.

Change Management for ServiceNow

Change Management ensures controlled modifications to IT infrastructure through standardized processes and approvals.

Change Types

| Type | Approval | Risk | Example | | ------------- | ------------------- | ------ | ----------------------- | | Standard | Pre-approved | Low | Password reset template | | Normal | CAB approval | Medium | Server patching | | Emergency | Post-implementation | High | Production outage fix |

Change Request Structure

Change Request: CHG0010001
├── Risk Assessment
│   ├── Impact: Medium
│   ├── Risk: Low
│   └── Conflict Status: Clear
├── Schedule
│   ├── Planned Start: 2024-03-15 22:00
│   └── Planned End: 2024-03-15 23:00
├── Approvals
│   ├── Manager Approval: Approved
│   └── CAB Approval: Pending
├── Change Tasks
│   ├── Task 1: Backup current config
│   ├── Task 2: Apply patches
│   └── Task 3: Verify functionality
└── Affected CIs
    ├── PROD-WEB-001
    └── PROD-DB-001

Creating Changes

Normal Change (ES5)

// Create normal change request
var change = new GlideRecord("change_request")
change.initialize()

// Basic info
change.setValue("short_description", "Apply security patches to web servers")
change.setValue("description", "Monthly security patch deployment for production web tier")
change.setValue("type", "normal") // normal, standard, emergency

// Classification
change.setValue("category", "Software")
change.setValue("priority", 3)

// Risk assessment
change.setValue("risk", "low") // high, moderate, low
change.setValue("impact", 2) // 1-High, 2-Medium, 3-Low

// Schedule
var startDate = new GlideDateTime()
startDate.addDaysLocalTime(7)
startDate.setValue("2024-03-15 22:00:00")
change.setValue("start_date", startDate)

var endDate = new GlideDateTime(startDate)
endDate.addSeconds(3600) // 1 hour
change.setValue("end_date", endDate)

// Assignment
change.setValue("assignment_group", getGroupSysId("Change Management"))
change.setValue("assigned_to", getOnCallUser())

// Implementation plan
change.setValue(
  "implementation_plan",
  "1. Take backup of current configuration\\n" +
    "2. Stop web services\\n" +
    "3. Apply security patches\\n" +
    "4. Restart services\\n" +
    "5. Verify functionality",
)

change.setValue(
  "backout_plan",
  "1. Stop web services\\n" + "2. Restore from backup\\n" + "3. Restart services\\n" + "4. Verify rollback successful",
)

change.setValue(
  "test_plan",
  "1. Check web server response\\n" + "2. Verify all pages load\\n" + "3. Run automated health checks",
)

var changeSysId = change.insert()

Emergency Change (ES5)

// Create emergency change
var emergencyChange = new GlideRecord("change_request")
emergencyChange.initialize()

emergencyChange.setValue("short_description", "Emergency: Fix production database connection leak")
emergencyChange.setValue("type", "emergency")
emergencyChange.setValue("priority", 1)
emergencyChange.setValue("risk", "high")
emergencyChange.setValue("impact", 1)

// Emergency justification
emergencyChange.setValue(
  "justification",
  "Production database connections exhausted causing service outage. " + "Immediate fix required to restore service.",
)

// Immediate start
emergencyChange.setValue("start_date", new GlideDateTime())

var endDate = new GlideDateTime()
endDate.addSeconds(7200) // 2 hours
emergencyChange.setValue("end_date", endDate)

emergencyChange.insert()

// Emergency changes bypass normal CAB
gs.eventQueue("change.emergency.created", emergencyChange)

Standard Change (ES5)

// Create from standard change template
function createStandardChange(templateName, variables) {
  // Find template
  var template = new GlideRecord("std_change_producer")
  template.addQuery("name", templateName)
  template.query()

  if (!template.next()) {
    gs.error("Standard change template not found: " + templateName)
    return null
  }

  // Create change from template
  var change = new GlideRecord("change_request")
  change.initialize()

  // Copy template values
  change.setValue("short_description", template.getValue("short_description"))
  change.setValue("description", template.getValue("description"))
  change.setValue("type", "standard")
  change.setValue("std_change_producer", template.getUniqueValue())

  // Apply variables
  for (var key in variables) {
    if (variables.hasOwnProperty(key) && change.isValidField(key)) {
      change.setValue(key, variables[key])
    }
  }

  return change.insert()
}

// Usage
createStandardChange("Password Reset", {
  requested_by: userSysId,
  cmdb_ci: applicationSysId,
})

Change Tasks

Creating Change Tasks (ES5)

// Add tasks to change
function addChangeTask(changeSysId, taskConfig) {
  var task = new GlideRecord("change_task")
  task.initialize()
  task.setValue("change_request", changeSysId)
  task.setValue("short_description", taskConfig.description)
  task.setValue("order", taskConfig.order)
  task.setValue("assignment_group", taskConfig.group)
  task.setValue("planned_start_date", taskConfig.start)
  task.setValue("planned_end_date", taskConfig.end)
  return task.insert()
}

// Create implementation tasks
var tasks = [
  { description: "Pre-implementation backup", order: 100, group: "Database Team" },
  { description: "Apply patches", order: 200, group: "Server Team" },
  { description: "Verify functionality", order: 300, group: "QA Team" },
  { description: "Update documentation", order: 400, group: "Change Management" },
]

for (var i = 0; i < tasks.length; i++) {
  addChangeTask(changeSysId, tasks[i])
}

Affected CIs

Linking CIs to Change (ES5)

// Add affected CIs
function addAffectedCI(changeSysId, ciSysId) {
  var task = new GlideRecord("task_ci")
  task.initialize()
  task.setValue("task", changeSysId)
  task.setValue("ci_item", ciSysId)
  return task.insert()
}

// Add all affected servers
var servers = ["server1_sys_id", "server2_sys_id", "db_sys_id"]
for (var i = 0; i < servers.length; i++) {
  addAffectedCI(changeSysId, servers[i])
}

Approvals

Check Approval Status (ES5)

// Get approval status
function getApprovalStatus(changeSysId) {
  var approvals = []

  var approval = new GlideRecord("sysapproval_approver")
  approval.addQuery("sysapproval", changeSysId)
  approval.query()

  while (approval.next()) {
    approvals.push({
      approver: approval.approver.getDisplayValue(),
      state: approval.state.getDisplayValue(),
      comments: approval.getValue("comments"),
      sys_updated_on: approval.getValue("sys_updated_on"),
    })
  }

  return approvals
}

Request Approval (ES5)

// Add approval request
function requestApproval(changeSysId, approverSysId) {
  var approval = new GlideRecord("sysapproval_approver")
  approval.initialize()
  approval.setValue("sysapproval", changeSysId)
  approval.setValue("approver", approverSysId)
  approval.setValue("state", "requested")
  return approval.insert()
}

Change Conflict Detection

Check for Conflicts (ES5)

// Check for scheduling conflicts
function checkChangeConflicts(changeSysId) {
  var change = new GlideRecord("change_request")
  if (!change.get(changeSysId)) return []

  var conflicts = []
  var startDate = change.getValue("start_date")
  var endDate = change.getValue("end_date")

  // Find overlapping changes on same CIs
  var affected = new GlideAggregate("task_ci")
  affected.addQuery("task", changeSysId)
  affected.groupBy("ci_item")
  affected.query()

  while (affected.next()) {
    var ciSysId = affected.ci_item.toString()

    // Find other changes affecting this CI
    var otherChanges = new GlideRecord("change_request")
    otherChanges.addQuery("sys_id", "!=", changeSysId)
    otherChanges.addQuery("state", "NOT IN", "closed,cancelled")
    otherChanges.addQuery("start_date", "<=", endDate)
    otherChanges.addQuery("end_date", ">=", startDate)

    // Join to task_ci
    otherChanges.addJoinQuery("task_ci", "sys_id", "task").addCondition("ci_item", ciSysId)

    otherChanges.query()

    while (otherChanges.next()) {
      conflicts.push({
        change: otherChanges.getValue("number"),
        ci: ciSysId,
        start: otherChanges.getValue("start_date"),
        end: otherChanges.getValue("end_date"),
      })
    }
  }

  return conflicts
}

State Transitions

Change States

| State | Next States | Conditions | | --------- | -------------------- | ------------------------- | | New | Assess | Submitted | | Assess | Authorize, Cancelled | Assessment complete | | Authorize | Scheduled, Cancelled | Approvals complete | | Scheduled | Implement, Cancelled | Within maintenance window | | Implement | Review, Cancelled | Tasks completed | | Review | Closed | PIR complete | | Closed | - | Final state |

Transition Change (ES5)

// Move change to next state
function transitionChange(changeSysId, newState, notes) {
  var change = new GlideRecord("change_request")
  if (!change.get(changeSysId)) {
    gs.error("Change not found: " + changeSysId)
    return false
  }

  // Validate transition
  var currentState = change.getValue("state")
  var validTransitions = {
    "-5": ["-4", "4"], // New -> Assess or Cancelled
    "-4": ["-3", "4"], // Assess -> Authorize or Cancelled
    "-3": ["-2", "4"], // Authorize -> Scheduled or Cancelled
    "-2": ["-1", "4"], // Scheduled -> Implement or Cancelled
    "-1": ["0", "4"], // Implement -> Review or Cancelled
    0: ["3"], // Review -> Closed
  }

  if (!validTransitions[currentState] || validTransitions[currentState].indexOf(newState) === -1) {
    gs.error("Invalid state transition: " + currentState + " -> " + newState)
    return false
  }

  change.setValue("state", newState)
  if (notes) {
    change.work_notes = notes
  }
  change.update()

  return true
}

MCP Tool Integration

Available Change Tools

| Tool | Purpose | | ----------------------------- | ---------------- | | snow_create_change_request | Create change | | snow_create_change_task | Add tasks | | snow_get_change_request | Get details | | snow_update_change_state | Transition state | | snow_search_change_requests | Find changes | | snow_schedule_cab_meeting | Schedule CAB |

Example Workflow

// 1. Create change
var changeId = await snow_create_change_request({
  short_description: "Database upgrade",
  type: "normal",
  risk: "moderate",
  start_date: "2024-03-20 22:00:00",
  end_date: "2024-03-21 02:00:00",
})

// 2. Add tasks
await snow_create_change_task({
  change: changeId,
  description: "Backup database",
  order: 100,
})

// 3. Check conflicts
var conflicts = await snow_check_change_conflicts({
  change: changeId,
})

// 4. Submit for approval
await snow_update_change_state({
  change: changeId,
  state: "assess",
})

Best Practices

  1. Complete Documentation - Implementation, backout, test plans
  2. Risk Assessment - Accurate risk and impact ratings
  3. CI Linking - All affected CIs attached
  4. Proper Scheduling - Within maintenance windows
  5. Task Breakdown - Clear implementation steps
  6. Approval Chain - All required approvals
  7. Conflict Check - Verify no overlapping changes
  8. PIR - Post-implementation review for lessons learned