skills/cmdb/relationship-mapping/SKILL.md
CI relationship management including creation, validation, dependency analysis, and orphan detection
npx skillsauth add happy-technologies-llc/happy-servicenow-skills relationship-mappingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
CI relationships form the backbone of CMDB value. Without relationships, CIs are isolated islands of data. This skill covers:
When to use: When modeling service dependencies, preparing for change impact analysis, auditing CMDB completeness, or troubleshooting service outages.
Value proposition: Well-mapped relationships enable accurate impact analysis, reducing change failures by up to 50% and decreasing MTTR during incidents.
cmdb_admin or itil with CMDB write accesscmdb/ci-discovery firstServiceNow provides relationship types in cmdb_rel_type. Each relationship has:
Common Relationship Types:
| Relationship | Parent Descriptor | Child Descriptor | Use Case | |--------------|-------------------|------------------|----------| | Runs on | Runs on | Hosts | Application on Server | | Depends on | Depends on | Used by | Service dependencies | | Contains | Contains | Contained by | Physical containment | | Connects to | Connects to | Connected by | Network connectivity | | Sends data to | Sends data to | Receives data from | Data flows | | Cluster of | Cluster of | Cluster member | Clusters | | Uses | Uses | Is used by | Generic dependency |
Query available relationship types:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: active=true
fields: sys_id,name,parent_descriptor,child_descriptor
limit: 100
REST API:
GET /api/now/table/cmdb_rel_type?sysparm_query=active=true&sysparm_fields=sys_id,name,parent_descriptor,child_descriptor&sysparm_limit=100
Before creating relationships, understand what exists:
Find all relationships for a CI:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent=[ci_sys_id]^ORchild=[ci_sys_id]
fields: parent,child,type,sys_created_on
limit: 50
Find downstream dependencies (what depends on this CI):
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: child=[ci_sys_id]^type.parent_descriptorLIKEDepends
fields: parent,parent.name,type,type.parent_descriptor
Find upstream dependencies (what this CI depends on):
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent=[ci_sys_id]^type.parent_descriptorLIKEDepends
fields: child,child.name,type,type.child_descriptor
Determine the correct relationship type first:
Decision Matrix:
| Parent CI Type | Child CI Type | Recommended Relationship | |----------------|---------------|--------------------------| | Application | Server | Runs on | | Business Service | Application | Depends on | | Server | Rack | Contained by | | Server | Server | Connects to (if network) | | Database | Server | Runs on | | Load Balancer | Server Pool | Contains |
Find relationship type sys_id:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: nameLIKERuns on::Runs on
fields: sys_id,name,parent_descriptor,child_descriptor
Create the relationship:
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: [parent_ci_sys_id]
child: [child_ci_sys_id]
type: [relationship_type_sys_id]
Example - Application runs on Server:
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: "abc123..." # Application CI sys_id
child: "def456..." # Server CI sys_id
type: "55c95bf6c0a8010e0118ec7056e1c57d" # Runs on::Hosts
Check for invalid relationships:
Find relationships with missing CIs:
Tool: SN-Execute-Background-Script
Parameters:
description: Find invalid relationships with missing CIs
script: |
var gr = new GlideRecord('cmdb_rel_ci');
gr.addQuery('parent.sys_idISEMPTY^ORchild.sys_idISEMPTY');
gr.query();
gs.info('Invalid relationships found: ' + gr.getRowCount());
while (gr.next()) {
gs.info('Invalid rel: ' + gr.sys_id + ' parent=' + gr.parent + ' child=' + gr.child);
}
Find duplicate relationships:
Tool: SN-Execute-Background-Script
Parameters:
description: Detect duplicate relationships
script: |
var duplicates = new GlideAggregate('cmdb_rel_ci');
duplicates.addAggregate('COUNT');
duplicates.groupBy('parent');
duplicates.groupBy('child');
duplicates.groupBy('type');
duplicates.addHaving('COUNT', '>', 1);
duplicates.query();
gs.info('Duplicate relationship combinations found: ' + duplicates.getRowCount());
while (duplicates.next()) {
gs.info('Duplicate: parent=' + duplicates.parent + ' child=' + duplicates.child + ' type=' + duplicates.type + ' count=' + duplicates.getAggregate('COUNT'));
}
Validate relationship type appropriateness:
Some relationship types are only valid for certain CI classes. Check the relationship type's parent_ci_class and child_ci_class fields if populated.
Understanding full dependency chains is critical for impact analysis.
Get complete dependency tree (recursive):
Tool: SN-Execute-Background-Script
Parameters:
description: Build dependency tree for CI
script: |
var ciSysId = 'YOUR_CI_SYS_ID';
var maxDepth = 5;
var visited = {};
var tree = [];
function getDependencies(parentId, depth, direction) {
if (depth > maxDepth || visited[parentId]) return;
visited[parentId] = true;
var gr = new GlideRecord('cmdb_rel_ci');
if (direction === 'down') {
gr.addQuery('child', parentId);
gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
} else {
gr.addQuery('parent', parentId);
gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
}
gr.query();
while (gr.next()) {
var targetId = direction === 'down' ? gr.parent.toString() : gr.child.toString();
var targetName = direction === 'down' ? gr.parent.name.toString() : gr.child.name.toString();
tree.push({
depth: depth,
direction: direction,
ci_name: targetName,
ci_sys_id: targetId
});
getDependencies(targetId, depth + 1, direction);
}
}
getDependencies(ciSysId, 1, 'down');
gs.info('Upstream dependencies (what depends on this CI):');
tree.forEach(function(item) {
gs.info(' '.repeat(item.depth) + item.ci_name);
});
Identify critical path:
Services with single points of failure have critical paths:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent.sys_class_name=cmdb_ci_service^type.parent_descriptorLIKEDepends
fields: parent.name,child.name,child.sys_class_name
Orphan CIs (those without relationships) reduce CMDB value and complicate impact analysis.
Find CIs with no relationships:
Tool: SN-Execute-Background-Script
Parameters:
description: Find orphan CIs with no relationships
script: |
var orphans = [];
var ciClasses = ['cmdb_ci_server', 'cmdb_ci_appl', 'cmdb_ci_database_instance'];
ciClasses.forEach(function(ciClass) {
var gr = new GlideRecord(ciClass);
gr.addQuery('operational_status', '1');
gr.query();
while (gr.next()) {
var relGr = new GlideRecord('cmdb_rel_ci');
relGr.addQuery('parent', gr.sys_id);
relGr.addOrCondition('child', gr.sys_id);
relGr.setLimit(1);
relGr.query();
if (!relGr.hasNext()) {
orphans.push({
sys_id: gr.sys_id.toString(),
name: gr.name.toString(),
class: ciClass
});
}
}
});
gs.info('Orphan CIs found: ' + orphans.length);
orphans.forEach(function(o) {
gs.info(' ' + o.class + ': ' + o.name + ' (' + o.sys_id + ')');
});
MCP Alternative - Query-based approach:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_ci_server
query: operational_status=1^sys_idNOT IN(SELECT parent FROM cmdb_rel_ci)^sys_idNOT IN(SELECT child FROM cmdb_rel_ci)
fields: name,ip_address,sys_class_name
limit: 50
Note: Complex subqueries may not work via REST API. Use background script for reliability.
Periodic cleanup script:
Tool: SN-Execute-Background-Script
Parameters:
description: Clean up invalid relationships
script: |
var deleted = 0;
// Delete relationships where parent CI was deleted
var gr = new GlideRecord('cmdb_rel_ci');
gr.addNullQuery('parent');
gr.query();
while (gr.next()) {
gr.deleteRecord();
deleted++;
}
// Delete relationships where child CI was deleted
gr = new GlideRecord('cmdb_rel_ci');
gr.addNullQuery('child');
gr.query();
while (gr.next()) {
gr.deleteRecord();
deleted++;
}
gs.info('Deleted ' + deleted + ' invalid relationships');
Update stale relationships: When a CI's operational status changes, relationships may need updates:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent.operational_status!=1^ORchild.operational_status!=1
fields: sys_id,parent.name,child.name,parent.operational_status,child.operational_status
| Operation | MCP Tool | REST Endpoint | |-----------|----------|---------------| | List relationship types | SN-Query-Table | GET /cmdb_rel_type | | Query relationships | SN-Query-Table | GET /cmdb_rel_ci | | Create relationship | SN-Create-Record | POST /cmdb_rel_ci | | Delete relationship | SN-Update-Record (set inactive) | DELETE /cmdb_rel_ci/{id} | | Complex queries | SN-Execute-Background-Script | POST /api/sn_chg_rest/change | | CI relationships API | N/A | GET /cmdb/instance/{id}/relation |
Symptom: Created relationship doesn't appear in CI dependency views
Cause: Relationship type not configured for dependency visualization
Solution: Check cmdb_rel_type record - ensure is_used_by and is_dependency flags are set appropriately
Symptom: Same relationship exists multiple times Cause: Manual creation overlapped with discovery Solution: Run duplicate detection script; delete duplicates keeping discovery-created records
Symptom: Impact analysis shows infinite loop warning Cause: CI A depends on B, B depends on C, C depends on A Solution: Review and break the circular chain; often indicates incorrect relationship type usage
Symptom: Cannot find appropriate relationship type for use case
Cause: OOB types may not cover all scenarios
Solution: Create custom relationship type via cmdb_rel_type table (requires cmdb_admin)
# 1. Identify the CIs
Business Service: "Customer Portal"
Web Application: "Portal Frontend"
App Server: "prod-app-01"
Database: "Portal DB"
DB Server: "prod-db-01"
# 2. Find relationship type sys_ids
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: nameLIKEDepends on^ORnameLIKERuns on
fields: sys_id,name,parent_descriptor
# 3. Create relationships (batch in one message)
# Service depends on Web App
SN-Create-Record: cmdb_rel_ci
parent: [service_sys_id], child: [webapp_sys_id], type: [depends_on_type]
# Web App runs on App Server
SN-Create-Record: cmdb_rel_ci
parent: [webapp_sys_id], child: [appserver_sys_id], type: [runs_on_type]
# Web App depends on Database
SN-Create-Record: cmdb_rel_ci
parent: [webapp_sys_id], child: [database_sys_id], type: [depends_on_type]
# Database runs on DB Server
SN-Create-Record: cmdb_rel_ci
parent: [database_sys_id], child: [dbserver_sys_id], type: [runs_on_type]
# 1. Find orphan servers
Tool: SN-Execute-Background-Script
Parameters:
script: [orphan detection script from Step 6]
# 2. For each orphan, determine what it hosts
Tool: SN-Query-Table
Parameters:
table_name: cmdb_ci_appl
query: install_dateLIKE[orphan_ip_address]
fields: name,sys_id
# 3. Create missing relationships
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: [app_sys_id]
child: [orphan_server_sys_id]
type: [runs_on_type_sys_id]
cmdb/ci-discovery - CI creation and classificationcmdb/impact-analysis - Using relationships for impact analysiscmdb/data-quality - CMDB data quality managementitsm/change-management - Changes and CI relationshipstesting
Manage supplier onboarding, qualification, performance monitoring, and offboarding with auditable lifecycle controls
tools
Identify emerging risks, prioritize intake signals, and route candidates into formal GRC risk assessment workflows
documentation
Screen inbound documents for completeness, policy risk, and routing readiness before extraction or case workflows
testing
Generate concise task summaries with status, timeline, blockers, SLA risk, and recommended next actions