GRC Risk Event Summarization

SkillDev tools

Summarize risk events with impact assessment, affected controls, contributing factors, and recommended mitigation actions

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the GRC Risk Event Summarization skill

What this skill tells your AI

The instructions your AI receives, as published by happy-technologies-llc/happy-platform-skills in skills/grc/risk-event-summarization/SKILL.md and read by ahel’s review.

Overview

This skill generates comprehensive summaries of risk events in ServiceNow GRC, providing stakeholders with a complete picture of what happened, why it happened, what was affected, and what should be done in response.

Key capabilities:

  • Event Context: Aggregate risk event details including timeline, category, and triggering conditions
  • Impact Assessment: Quantify financial, operational, reputational, and regulatory impact of risk events
  • Control Analysis: Identify which controls failed, were bypassed, or were absent when the event occurred
  • Contributing Factor Analysis: Determine root causes and contributing factors leading to the event
  • Mitigation Recommendations: Generate prioritized mitigation actions based on event severity and control gaps
  • Trend Detection: Identify patterns across related risk events to surface systemic issues

When to use:

  • After a risk event materializes and stakeholders need a structured briefing
  • During risk committee meetings requiring event summaries
  • When building a risk event register or loss event database
  • For regulatory reporting on operational risk events
  • When conducting post-event reviews or lessons-learned sessions

Prerequisites

  • Roles: sn_grc.manager, sn_risk.manager, or admin
  • Plugins: com.sn_grc, com.sn_risk, com.sn_compliance
  • Access: Read access to sn_risk_event, sn_grc_risk, sn_compliance_control, sn_grc_issue, sn_grc_profile
  • Knowledge: Understanding of organizational risk taxonomy and event categorization standards

Key GRC Tables

TablePurposeKey Fields
sn_risk_eventRisk events / loss eventsnumber, short_description, state, category, event_date, impact, likelihood, financial_impact, risk, profile
sn_grc_riskAssociated risk recordsnumber, risk_score, residual_risk, inherent_risk, treatment, state, category
sn_compliance_controlControls that should have mitigated the eventnumber, state, effectiveness, test_result, control_objective, owner
sn_grc_issueIssues generated from eventsnumber, state, priority, risk_rating, source
sn_risk_definitionRisk definitions and categoriesnumber, short_description, risk_type, category
sn_grc_profileEntity profilesnumber, profile_type, applies_to

Procedure

Step 1: Retrieve Risk Event Details

Fetch the target risk event with full context fields.

Using MCP (Claude Code/Desktop):

Tool: SN-Get-Record
Parameters:
  table_name: sn_risk_event
  sys_id: [EVENT_SYS_ID]
  fields: sys_id,number,short_description,description,state,category,subcategory,event_date,discovered_date,impact,likelihood,financial_impact,operational_impact,reputational_impact,regulatory_impact,risk,profile,assigned_to,assignment_group,root_cause,contributing_factors,sys_created_on

Using REST API:

GET /api/now/table/sn_risk_event?sysparm_query=number=[EVENT_NUMBER]&sysparm_fields=sys_id,number,short_description,description,state,category,subcategory,event_date,discovered_date,impact,likelihood,financial_impact,operational_impact,reputational_impact,regulatory_impact,risk,profile,assigned_to,root_cause,contributing_factors&sysparm_limit=1&sysparm_display_value=all

Step 2: Gather Associated Risk Context

Pull the risk record linked to the event to understand the broader risk landscape.

Using MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: sys_id=[event_risk_sys_id]
  fields: sys_id,number,short_description,risk_score,state,treatment,residual_risk,inherent_risk,category,owner,risk_appetite,risk_tolerance
  limit: 1

For all risks under the same profile:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_risk
  query: profile=[event_profile_sys_id]^active=true
  fields: sys_id,number,short_description,risk_score,residual_risk,inherent_risk,treatment,category
  limit: 25

Using REST API:

GET /api/now/table/sn_grc_risk?sysparm_query=profile=[profile_sys_id]^active=true&sysparm_fields=sys_id,number,short_description,risk_score,residual_risk,inherent_risk,treatment,category&sysparm_limit=25&sysparm_display_value=all

Step 3: Identify Affected Controls

Query controls linked to the risk profile to determine which should have prevented the event.

Using MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_compliance_control
  query: profile=[event_profile_sys_id]^active=true
  fields: sys_id,number,short_description,state,control_objective,owner,effectiveness,test_result,test_date
  limit: 50

Using REST API:

GET /api/now/table/sn_compliance_control?sysparm_query=profile=[profile_sys_id]^active=true&sysparm_fields=sys_id,number,short_description,state,control_objective,owner,effectiveness,test_result,test_date&sysparm_limit=50&sysparm_display_value=all

Step 4: Retrieve Work Notes and Investigation History

Pull investigation notes to capture analyst findings and contributing factor analysis.

Using MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sys_journal_field
  query: name=sn_risk_event^element_id=[EVENT_SYS_ID]^element=work_notes^ORDERBYDESCsys_created_on
  fields: value,sys_created_on,sys_created_by
  limit: 25

Using REST API:

GET /api/now/table/sys_journal_field?sysparm_query=name=sn_risk_event^element_id=[event_sys_id]^element=work_notes^ORDERBYDESCsys_created_on&sysparm_fields=value,sys_created_on,sys_created_by&sysparm_limit=25

Step 5: Check for Related Issues and Historical Events

Identify GRC issues spawned from the event and similar past events.

Using MCP:

Tool: SN-Query-Table
Parameters:
  table_name: sn_grc_issue
  query: source_record=[EVENT_SYS_ID]^ORprofile=[event_profile_sys_id]
  fields: sys_id,number,short_description,state,priority,risk_rating,source,sys_created_on
  limit: 20

For historical pattern analysis:

Tool: SN-Query-Table
Parameters:
  table_name: sn_risk_event
  query: category=[event_category]^sys_id!=[EVENT_SYS_ID]^event_date>=javascript:gs.daysAgo(365)^ORDERBYDESCevent_date
  fields: sys_id,number,short_description,category,event_date,financial_impact,state
  limit: 25

Step 6: Generate Comprehensive Risk Event Summary

Using MCP:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var eventNumber = 'RE0001234'; // Replace with target event
    var gr = new GlideRecord('sn_risk_event');
    gr.addQuery('number', eventNumber);
    gr.query();

    if (!gr.next()) { gs.info('Event not found'); return; }

    var summary = {
      event: {
        number: gr.number.toString(),
        title: gr.short_description.toString(),
        description: gr.description.toString(),
        state: gr.state.getDisplayValue(),
        category: gr.category.getDisplayValue(),
        event_date: gr.event_date.getDisplayValue(),
        discovered_date: gr.discovered_date.getDisplayValue(),
        detection_lag_days: 0
      },
      impact_assessment: {
        overall_impact: gr.impact.getDisplayValue(),
        financial: gr.financial_impact.toString() || 'Not quantified',
        operational: gr.operational_impact.getDisplayValue() || 'Not assessed',
        reputational: gr.reputational_impact.getDisplayValue() || 'Not assessed',
        regulatory: gr.regulatory_impact.getDisplayValue() || 'Not assessed'
      },
      affected_controls: [],
      contributing_factors: [],
      related_issues: [],
      historical_pattern: { similar_events_12mo: 0, total_financial_loss: 0 },
      mitigation_recommendations: []
    };

    // Detection lag
    if (gr.event_date.toString() && gr.discovered_date.toString()) {
      var evtDate = new GlideDateTime(gr.event_date.toString());
      var discDate = new GlideDateTime(gr.discovered_date.toString());
      summary.event.detection_lag_days = parseInt(gs.dateDiff(evtDate.toString(), discDate.toString(), true)) || 0;
    }

    // Contributing factors from record
    if (gr.root_cause.toString()) summary.contributing_factors.push('Root Cause: ' + gr.root_cause.toString());
    if (gr.contributing_factors.toString()) summary.contributing_factors.push('Factors: ' + gr.contributing_factors.toString());

    var profileId = gr.profile.toString();

    // Affected controls
    var ctrl = new GlideRecord('sn_compliance_control');
    ctrl.addQuery('profile', profileId);
    ctrl.addQuery('active', true);
    ctrl.query();
    while (ctrl.next()) {
      var ctrlStatus = ctrl.state.getDisplayValue();
      var wasEffective = (ctrlStatus == 'Compliant' || ctrlStatus == 'Passed');
      summary.affected_controls.push({
        control: ctrl.number.toString(),
        title: ctrl.short_description.toString(),
        state: ctrlStatus,
        effectiveness: ctrl.effectiveness.getDisplayValue(),
        prevented_event: wasEffective,
        owner: ctrl.owner.getDisplayValue()
      });
      if (!wasEffective) {
        summary.contributing_factors.push('Control failure: ' + ctrl.number.toString() + ' (' + ctrlStatus + ')');
      }
    }

    // Related issues
    var issue = new GlideRecord('sn_grc_issue');
    issue.addQuery('profile', profileId);
    issue.addQuery('active', true);
    issue.query();
    while (issue.next()) {
      summary.related_issues.push({
        number: issue.number.toString(),
        title: issue.short_description.toString(),
        priority: issue.priority.getDisplayValue(),
        state: issue.state.getDisplayValue()
      });
    }

    // Historical pattern
    var hist = new GlideRecord('sn_risk_event');
    hist.addQuery('category', gr.category.toString());
    hist.addQuery('sys_id', '!=', gr.sys_id.toString());
    hist.addQuery('event_date', '>=', gs.daysAgo(365));
    hist.query();
    while (hist.next()) {
      summary.historical_pattern.similar_events_12mo++;
      summary.historical_pattern.total_financial_loss += parseFloat(hist.financial_impact.toString()) || 0;
    }

    // Generate mitigation recommendations
    var failedControls = summary.affected_controls.filter(function(c) { return !c.prevented_event; });
    if (failedControls.length > 0) {
      summary.mitigation_recommendations.push('IMMEDIATE: Remediate ' + failedControls.length + ' failed controls identified during event analysis');
    }
    if (summary.event.detection_lag_days > 7) {
      summary.mitigation_recommendations.push('SHORT-TERM: Improve detection capabilities - ' + summary.event.detection_lag_days + ' day detection lag exceeds acceptable threshold');
    }
    if (summary.historical_pattern.similar_events_12mo >= 3) {
      summary.mitigation_recommendations.push('STRATEGIC: Investigate systemic root cause - ' + summary.historical_pattern.similar_events_12mo + ' similar events in past 12 months indicates pattern');
    }
    summary.mitigation_recommendations.push('ONGOING: Update risk assessment to reflect materialized event and adjust residual risk scores');

    gs.info('RISK EVENT SUMMARY:\n' + JSON.stringify(summary, null, 2));
  description: "GRC: Generate comprehensive risk event summary with impact assessment"

Step 7: Generate Executive Narrative

Using MCP:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var narrative = [];
    narrative.push('=== RISK EVENT EXECUTIVE SUMMARY ===');
    narrative.push('');

    var agg = new GlideAggregate('sn_risk_event');
    agg.addQuery('event_date', '>=', gs.daysAgo(90));
    agg.addAggregate('COUNT');
    agg.groupBy('category');
    agg.query();

    narrative.push('RISK EVENTS - LAST 90 DAYS BY CATEGORY:');
    while (agg.next()) {
      narrative.push('  ' + agg.category.getDisplayValue() + ': ' + agg.getAggregate('COUNT') + ' events');
    }
    narrative.push('');

    // Top events by financial impact
    narrative.push('TOP EVENTS BY FINANCIAL IMPACT:');
    var top = new GlideRecord('sn_risk_event');
    top.addQuery('event_date', '>=', gs.daysAgo(90));
    top.addNotNullQuery('financial_impact');
    top.orderByDesc('financial_impact');
    top.setLimit(5);
    top.query();
    var idx = 1;
    while (top.next()) {
      narrative.push('  ' + idx + '. ' + top.number + ' - ' + top.short_description);
      narrative.push('     Financial Impact: $' + top.financial_impact + ' | Category: ' + top.category.getDisplayValue());
      idx++;
    }

    gs.info(narrative.join('\n'));
  description: "GRC: Generate quarterly risk event narrative for leadership"

Tool Usage

OperationMCP ToolREST Endpoint
Read EventSN-Get-RecordGET /api/now/table/sn_risk_event/{sys_id}
Query EventsSN-Query-TableGET /api/now/table/sn_risk_event
Query ControlsSN-Query-TableGET /api/now/table/sn_compliance_control
Query RisksSN-Query-TableGET /api/now/table/sn_grc_risk
Aggregate AnalysisSN-Execute-Background-ScriptPOST /api/now/table/sys_trigger
Search EventsSN-Natural-Language-SearchN/A

Best Practices

  • Timeliness: Generate summaries within 24 hours of event discovery while details are fresh
  • Quantify Impact: Always attempt to quantify financial impact, even as an estimate with confidence range
  • Root Cause Depth: Distinguish between immediate causes and systemic contributing factors
  • Control Mapping: Explicitly identify which controls should have prevented or detected the event
  • Historical Context: Include trend data to distinguish one-off events from systemic patterns
  • Actionable Recommendations: Every summary should end with specific, assignable mitigation actions
  • Regulatory Awareness: Flag events that may trigger regulatory notification requirements

Troubleshooting

Risk Event Table Not Found

Symptom: sn_risk_event returns no results or table not found Cause: The risk event table name may differ across ServiceNow versions; some use sn_risk_event while others use sn_grc_loss_event Solution:

Tool: SN-Discover-Table-Schema
Parameters:
  table_name: sn_risk_event

If not found, search for tables containing "risk_event" or "loss_event" in sys_db_object.

Financial Impact Field Empty

Symptom: Financial impact data is consistently null despite events having known costs Cause: Financial impact may be tracked in a related loss record rather than on the event itself Solution: Check for related tables like sn_risk_loss or custom financial impact assessment records linked via reference fields.

No Controls Linked to Event Profile

Symptom: Control analysis returns empty results for the event profile Cause: The event may not be linked to a GRC profile, or controls use a different relationship path Solution: Check the item field on the event instead of profile, or query sn_grc_m2m_item_profile for the relationship mapping.

Examples

Example 1: Operational Risk Event Summary

Scenario: System outage event RE0002345 affecting payment processing

  • Event: Unplanned outage of payment gateway, 4-hour duration
  • Detection Lag: 15 minutes (automated monitoring alert)
  • Financial Impact: $180,000 in lost transaction revenue
  • Failed Controls: 2 -- disaster recovery test (not tested in 14 months), capacity monitoring threshold (set too high)
  • Contributing Factors: Infrastructure change without proper testing, single point of failure in payment routing
  • Similar Events (12 months): 2 prior events totaling $95,000
  • Recommendations: Update DR testing schedule, lower capacity thresholds, implement redundant payment routing

Example 2: Compliance Risk Event Summary

Scenario: Data breach event RE0003001 involving customer PII exposure

  • Event: Unauthorized access to customer database via compromised service account
  • Detection Lag: 12 days (flagged by external security researcher)
  • Records Affected: 15,000 customer records
  • Regulatory Impact: GDPR Article 33 notification required within 72 hours
  • Failed Controls: 3 -- privileged access review, service account rotation, database activity monitoring
  • Recommendations: Immediate credential rotation, deploy database activity monitoring, establish 72-hour notification procedure

Related Skills

  • grc/issue-summarization - Summarize GRC issues generated from risk events
  • grc/risk-assessment-summarization - Broader risk assessment context
  • grc/suggest-remediation-tasks - Generate remediation tasks for event-related control gaps
  • grc/regulatory-alert-analysis - Identify regulatory implications of risk events
  • grc/control-objective-management - Manage controls affected by events

Signals

GitHub stars
37
Forks
13
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
risk-event-summarization
Source
github.com/happy-technologies-llc/happy-platform-skills