关于 request-management
用于管理 ServiceNow 服务请求的技能,覆盖从目录条目到履行的流程。内容包括请求记录、目录任务、变量和审批,并提供面向管理员与开发者的 ES5 示例。
主要功能
- 01创建请求和请求条目
- 02查询用户的未完成请求
- 03创建履行任务
- 04读取并验证条目变量
- 05检查请求审批状态
适用场景
- 01根据目录条目创建请求
- 02查看用户待处理的请求
- 03协调请求条目的任务完成
- 04在处理请求前验证输入
MCP 相关
介绍用于查询请求和请求条目、查找目录条目、测试脚本及创建目录条目的 ServiceNow MCP 工具。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill request-management安装后在 Claude Code 中输入/request-management确认已加载。
详细介绍
ServiceNow 请求管理
请求管理用于处理服务请求,从目录项到完成交付。
请求层级
Request (sc_request)
├── Request Item (sc_req_item) - RITM
│ ├── Catalog Tasks (sc_task)
│ └── Variables (sc_item_option_mtom)
└── Request Item
└── Catalog Tasks
主要表
| 表 | 用途 |
|---|---|
sc_request | 父请求记录 |
sc_req_item | 请求的项目(RITM) |
sc_task | 履行任务 |
sc_item_option_mtom | 变量值 |
sc_cat_item | 目录项定义 |
请求项目(ES5)
以编程方式创建请求
// Create request and RITM (ES5 ONLY!)
function createServiceRequest(catalogItemName, requestedFor, variables) {
// Get catalog item
var catItem = new GlideRecord("sc_cat_item")
if (!catItem.get("name", catalogItemName)) {
gs.error("Catalog item not found: " + catalogItemName)
return null
}
// Create request
var request = new GlideRecord("sc_request")
request.initialize()
request.setValue("requested_for", requestedFor)
request.setValue("opened_by", gs.getUserID())
request.setValue("description", "Request for " + catalogItemName)
var requestSysId = request.insert()
// Create RITM
var ritm = new GlideRecord("sc_req_item")
ritm.initialize()
ritm.setValue("request", requestSysId)
ritm.setValue("cat_item", catItem.getUniqueValue())
ritm.setValue("requested_for", requestedFor)
ritm.setValue("quantity", 1)
var ritmSysId = ritm.insert()
// Set variables
if (variables) {
setRITMVariables(ritmSysId, variables)
}
return {
request: request.getValue("number"),
ritm: ritm.getValue("number"),
request_sys_id: requestSysId,
ritm_sys_id: ritmSysId,
}
}
function setRITMVariables(ritmSysId, variables) {
var ritm = new GlideRecord("sc_req_item")
if (!ritm.get(ritmSysId)) return
for (var varName in variables) {
if (variables.hasOwnProperty(varName)) {
ritm.variables[varName] = variables[varName]
}
}
ritm.update()
}
查询请求项目
// Get user's open requests (ES5 ONLY!)
function getUserRequests(userSysId, includeCompleted) {
var requests = []
var ritm = new GlideRecord("sc_req_item")
ritm.addQuery("requested_for", userSysId)
if (!includeCompleted) {
ritm.addQuery("state", "!=", "3") // Not Closed Complete
ritm.addQuery("state", "!=", "4") // Not Closed Incomplete
}
ritm.orderByDesc("sys_created_on")
ritm.query()
while (ritm.next()) {
requests.push({
sys_id: ritm.getUniqueValue(),
number: ritm.getValue("number"),
short_description: ritm.getValue("short_description"),
cat_item: ritm.cat_item.getDisplayValue(),
state: ritm.state.getDisplayValue(),
stage: ritm.stage.getDisplayValue(),
opened_at: ritm.getValue("sys_created_on"),
due_date: ritm.getValue("due_date"),
})
}
return requests
}
履行任务(ES5)
创建目录任务
// Create fulfillment tasks for RITM (ES5 ONLY!)
function createFulfillmentTasks(ritmSysId, taskDefinitions) {
var ritm = new GlideRecord("sc_req_item")
if (!ritm.get(ritmSysId)) {
return []
}
var createdTasks = []
for (var i = 0; i < taskDefinitions.length; i++) {
var taskDef = taskDefinitions[i]
var task = new GlideRecord("sc_task")
task.initialize()
task.setValue("request_item", ritmSysId)
task.setValue("request", ritm.getValue("request"))
task.setValue("short_description", taskDef.description)
task.setValue("assignment_group", taskDef.assignmentGroup)
task.setValue("order", (i + 1) * 100)
// Calculate due date if specified
if (taskDef.daysToComplete) {
var dueDate = new GlideDateTime()
dueDate.addDaysLocalTime(taskDef.daysToComplete)
task.setValue("due_date", dueDate)
}
var taskSysId = task.insert()
createdTasks.push({
sys_id: taskSysId,
number: task.getValue("number"),
})
}
return createdTasks
}
// Example usage
var tasks = createFulfillmentTasks(ritmSysId, [
{ description: "Verify request details", assignmentGroup: "Service Desk", daysToComplete: 1 },
{ description: "Provision access", assignmentGroup: "IAM Team", daysToComplete: 2 },
{ description: "Notify user", assignmentGroup: "Service Desk", daysToComplete: 1 },
])
任务完成后自动关闭 RITM
// Business Rule: after, update, sc_task (ES5 ONLY!)
;(function executeRule(current, previous) {
// Check if task was just closed
if (current.state.changesTo("3") || current.state.changesTo("4")) {
checkAndCloseRITM(current.getValue("request_item"))
}
})(current, previous)
function checkAndCloseRITM(ritmSysId) {
// Check if all tasks are complete
var openTasks = new GlideAggregate("sc_task")
openTasks.addQuery("request_item", ritmSysId)
openTasks.addQuery("state", "NOT IN", "3,4,7") // Not closed or cancelled
openTasks.addAggregate("COUNT")
openTasks.query()
if (openTasks.next()) {
var count = parseInt(openTasks.getAggregate("COUNT"), 10)
if (count === 0) {
// All tasks complete, close RITM
var ritm = new GlideRecord("sc_req_item")
if (ritm.get(ritmSysId)) {
ritm.state = 3 // Closed Complete
ritm.update()
}
}
}
}
变量管理(ES5)
访问 RITM 变量
// Get variable values from RITM (ES5 ONLY!)
function getRITMVariables(ritmSysId) {
var variables = {}
var ritm = new GlideRecord("sc_req_item")
if (!ritm.get(ritmSysId)) {
return variables
}
// Get all variable values
var varValue = new GlideRecord("sc_item_option_mtom")
varValue.addQuery("request_item", ritmSysId)
varValue.query()
while (varValue.next()) {
var varName = varValue.sc_item_option.item_option_new.name.toString()
var value = varValue.getValue("sc_item_option")
// Get display value for reference fields
var varDef = varValue.sc_item_option.item_option_new.getRefRecord()
if (varDef.getValue("type") === "8") {
// Reference
var refRecord = new GlideRecord(varDef.getValue("reference"))
if (refRecord.get(value)) {
variables[varName] = {
value: value,
display_value: refRecord.getDisplayValue(),
}
}
} else {
variables[varName] = {
value: value,
display_value: varValue.sc_item_option.getDisplayValue(),
}
}
}
return variables
}
验证变量
// Validate RITM variables (ES5 ONLY!)
function validateRITMVariables(ritmSysId) {
var errors = []
var ritm = new GlideRecord("sc_req_item")
if (!ritm.get(ritmSysId)) {
return ["RITM not found"]
}
// Get catalog item variable definitions
var catItem = ritm.cat_item.getRefRecord()
var varDef = new GlideRecord("item_option_new")
varDef.addQuery("cat_item", catItem.getUniqueValue())
varDef.addQuery("mandatory", true)
varDef.query()
while (varDef.next()) {
var varName = varDef.getValue("name")
var varValue = ritm.variables[varName]
if (!varValue || varValue.toString() === "") {
errors.push("Missing required variable: " + varDef.getValue("question_text"))
}
}
return errors
}
请求审批(ES5)
检查审批状态
// Get approval status for request (ES5 ONLY!)
function getRequestApprovalStatus(requestSysId) {
var approvals = []
var approval = new GlideRecord("sysapproval_approver")
approval.addQuery("sysapproval", requestSysId)
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"),
})
}
// Determine overall status
var pending = 0
var approved = 0
var rejected = 0
for (var i = 0; i < approvals.length; i++) {
var state = approvals[i].state
if (state === "Requested") pending++
else if (state === "Approved") approved++
else if (state === "Rejected") rejected++
}
return {
approvals: approvals,
summary: {
pending: pending,
approved: approved,
rejected: rejected,
overall: rejected > 0 ? "Rejected" : pending > 0 ? "Pending" : "Approved",
},
}
}
MCP 工具集成
可用工具
| 工具 | 用途 |
|---|---|
snow_query_table | 查询请求和 RITM |
snow_artifact_manage (action='find') | 查找目录项 |
snow_execute_script | 测试请求脚本 |
snow_create_catalog_item | 创建目录项 |
工作流示例
// 1. Query open requests
await snow_query_table({
table: "sc_req_item",
query: "state!=3^state!=4^requested_for=javascript:gs.getUserID()",
fields: "number,short_description,cat_item,state,stage",
})
// 2. Get request details
await snow_execute_script({
script: `
var vars = getRITMVariables('ritm_sys_id');
gs.info(JSON.stringify(vars));
`,
})
// 3. Check approvals
await snow_query_table({
table: "sysapproval_approver",
query: "sysapproval=request_sys_id",
fields: "approver,state,comments",
})
最佳实践
- 清晰的描述 - 使用便于用户理解的简短描述
- 变量验证 - 处理前先验证
- 任务排序 - 按逻辑顺序安排履行任务
- SLA 跟踪 - 设置适当的到期日期
- 通知 - 及时告知请求者
- 审批规则 - 配置适当的审批规则
- 自动关闭 - 任务完成后关闭 RITM
- 仅限 ES5 - 不使用现代 JavaScript 语法
评论
支持 Markdown