skills/legal/contract-metadata-extraction/SKILL.md
Extract metadata from contracts including parties, effective dates, value, auto-renewal terms, governing law, key contacts, and obligation summaries for portfolio management
npx skillsauth add happy-technologies-llc/happy-servicenow-skills contract-metadata-extractionInstall 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.
This skill extracts structured metadata from contracts in ServiceNow Contract Lifecycle Management (CLM). It covers:
When to use:
contract_manager, sn_clm.admin, sn_legal_case_manager, or admincom.sn_clm (Contract Lifecycle Management), com.snc.contract_management (Contract Management)| Table | Purpose | Key Fields |
|-------|---------|------------|
| ast_contract | Master contract records | number, short_description, vendor, contract_type, starts, ends, renewal_date, payment_amount, total_cost, auto_renew, notice_period, governing_law |
| clm_contract_doc | Contract document versions | contract, document_version, status, doc_type, effective_date, content |
| clm_obligation | Contractual obligations | contract, short_description, obligation_type, responsible_party, due_date, state, compliance_status, clause_reference |
| clm_clause | Contract clause library | name, clause_type, content, category, standard, risk_level |
| sys_attachment | Document attachments | table_name, table_sys_id, file_name, content_type, size_bytes |
| core_company | Party/vendor records | name, vendor_type, primary_contact, city, state, country |
Get the base contract record with existing metadata.
Using MCP (Claude Code/Desktop):
Tool: SN-Read-Record
Parameters:
table_name: ast_contract
sys_id: [contract_sys_id]
fields: sys_id,number,short_description,description,contract_type,vendor,starts,ends,renewal_date,payment_amount,total_cost,state,terms_and_conditions,auto_renew,notice_period,assigned_to,department,contract_administrator,parent_contract,governing_law,currency,payment_terms,subcontracting_allowed
Using REST API:
GET /api/now/table/ast_contract/[contract_sys_id]?sysparm_fields=sys_id,number,short_description,description,contract_type,vendor,starts,ends,renewal_date,payment_amount,total_cost,state,terms_and_conditions,auto_renew,notice_period,assigned_to,department,contract_administrator,parent_contract,governing_law,currency,payment_terms&sysparm_display_value=true
Fetch associated contract documents and attachments for content analysis.
Using MCP:
Tool: SN-Query-Table
Parameters:
table_name: clm_contract_doc
query: contract=[contract_sys_id]^ORDERBYDESCdocument_version
fields: sys_id,document_version,status,doc_type,effective_date,content,file_name
limit: 10
Using REST API:
GET /api/now/table/clm_contract_doc?sysparm_query=contract=[contract_sys_id]^ORDERBYDESCdocument_version&sysparm_fields=sys_id,document_version,status,doc_type,effective_date,content,file_name&sysparm_limit=10
Retrieve attachments:
Tool: SN-Query-Table
Parameters:
table_name: sys_attachment
query: table_name=ast_contract^table_sys_id=[contract_sys_id]
fields: sys_id,file_name,content_type,size_bytes,sys_created_on
limit: 20
Identify all contracting parties, signatories, and key contacts.
Using MCP:
Tool: SN-Query-Table
Parameters:
table_name: core_company
query: sys_id=[vendor_sys_id]
fields: sys_id,name,vendor_type,primary_contact,street,city,state,country,phone,website,stock_symbol,parent
limit: 1
Using REST API:
GET /api/now/table/core_company/[vendor_sys_id]?sysparm_fields=sys_id,name,vendor_type,primary_contact,street,city,state,country,phone,website&sysparm_display_value=true
Query existing obligations or create them from contract analysis.
Using MCP:
Tool: SN-Query-Table
Parameters:
table_name: clm_obligation
query: contract=[contract_sys_id]^active=true
fields: sys_id,short_description,obligation_type,responsible_party,due_date,state,compliance_status,clause_reference,frequency,penalty
limit: 50
Using REST API:
GET /api/now/table/clm_obligation?sysparm_query=contract=[contract_sys_id]^active=true&sysparm_fields=sys_id,short_description,obligation_type,responsible_party,due_date,state,compliance_status,clause_reference,frequency&sysparm_limit=50&sysparm_display_value=true
Generate a comprehensive metadata extraction:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var contractNumber = 'CON0045678'; // Replace with target contract
var gr = new GlideRecord('ast_contract');
gr.addQuery('number', contractNumber);
gr.query();
if (gr.next()) {
var metadata = {
extraction_date: new GlideDateTime().toString(),
contract_id: gr.number.toString(),
parties: {
buyer: {
name: gs.getProperty('glide.servlet.uri', 'Your Organization'),
contact: gr.contract_administrator.getDisplayValue()
},
vendor: {
name: gr.vendor.getDisplayValue(),
contact: ''
}
},
dates: {
effective_date: gr.starts.toString(),
expiration_date: gr.ends.toString(),
renewal_date: gr.renewal_date.toString(),
execution_date: gr.sys_created_on.toString()
},
financials: {
total_value: gr.total_cost.toString(),
payment_amount: gr.payment_amount.toString(),
currency: gr.currency.getDisplayValue() || 'USD',
payment_terms: gr.payment_terms.getDisplayValue() || 'Not specified'
},
renewal: {
auto_renew: gr.auto_renew.toString() == 'true',
notice_period_days: gr.notice_period.toString() || 'Not specified',
notice_deadline: ''
},
governing_law: gr.governing_law.getDisplayValue() || 'Not specified',
contract_type: gr.contract_type.getDisplayValue(),
state: gr.state.getDisplayValue(),
obligations: [],
metadata_completeness: 0
};
// Calculate notice deadline
if (metadata.renewal.auto_renew && gr.ends.toString() && gr.notice_period.toString()) {
var endDate = new GlideDateTime(gr.ends.toString());
var noticeDays = parseInt(gr.notice_period.toString()) || 0;
endDate.addDaysUTC(-noticeDays);
metadata.renewal.notice_deadline = endDate.toString();
}
// Get vendor contact
var vendor = new GlideRecord('core_company');
if (vendor.get(gr.vendor.toString())) {
metadata.parties.vendor.contact = vendor.primary_contact.getDisplayValue();
}
// Get obligations
var obl = new GlideRecord('clm_obligation');
obl.addQuery('contract', gr.sys_id.toString());
obl.addQuery('active', true);
obl.query();
while (obl.next()) {
metadata.obligations.push({
description: obl.short_description.toString(),
type: obl.obligation_type.getDisplayValue(),
responsible: obl.responsible_party.getDisplayValue(),
due_date: obl.due_date.toString(),
status: obl.compliance_status.getDisplayValue()
});
}
// Metadata completeness score
var fields = ['total_cost', 'starts', 'ends', 'vendor', 'contract_type', 'governing_law', 'notice_period', 'payment_terms'];
var filled = 0;
for (var i = 0; i < fields.length; i++) {
if (gr.getValue(fields[i])) filled++;
}
metadata.metadata_completeness = Math.round((filled / fields.length) * 100);
gs.info('CONTRACT METADATA EXTRACTION:\n' + JSON.stringify(metadata, null, 2));
}
description: "CLM: Extract comprehensive metadata from a contract record"
Create obligation records discovered during extraction:
Tool: SN-Create-Record
Parameters:
table_name: clm_obligation
fields:
contract: [contract_sys_id]
short_description: "Annual SOC 2 Type II report delivery"
obligation_type: vendor_obligation
responsible_party: [vendor_sys_id]
due_date: 2026-06-30
frequency: annual
clause_reference: "Section 9.3 - Audit and Compliance"
state: active
compliance_status: pending
Using REST API:
POST /api/now/table/clm_obligation
Content-Type: application/json
{
"contract": "[contract_sys_id]",
"short_description": "Annual SOC 2 Type II report delivery",
"obligation_type": "vendor_obligation",
"responsible_party": "[vendor_sys_id]",
"due_date": "2026-06-30",
"frequency": "annual",
"clause_reference": "Section 9.3",
"state": "active"
}
Populate missing fields on the contract record:
Tool: SN-Update-Record
Parameters:
table_name: ast_contract
sys_id: [contract_sys_id]
data:
governing_law: "State of Delaware, United States"
payment_terms: "Net 30"
notice_period: 90
work_notes: "Metadata extraction completed. Completeness: 88%. 5 obligations cataloged. Notice deadline: 2026-09-01."
| Operation | MCP Tool | REST Endpoint | |-----------|----------|---------------| | Read Contract | SN-Read-Record | GET /api/now/table/ast_contract/{sys_id} | | Query Documents | SN-Query-Table | GET /api/now/table/clm_contract_doc | | Query Obligations | SN-Query-Table | GET /api/now/table/clm_obligation | | Query Attachments | SN-Query-Table | GET /api/now/table/sys_attachment | | Create Obligation | SN-Create-Record | POST /api/now/table/clm_obligation | | Update Contract | SN-Update-Record | PATCH /api/now/table/ast_contract/{sys_id} | | Batch Extraction | SN-Execute-Background-Script | POST /api/now/table/sys_trigger |
core_company records to avoid duplicate vendor entriesSymptom: clm_contract_doc records exist but the content field is null
Cause: Contract content may be stored as attachments rather than inline in the content field
Solution: Query sys_attachment with table_name=clm_contract_doc^table_sys_id=[doc_sys_id] to find the actual document file.
Symptom: The governing_law field does not exist on ast_contract
Cause: This field may be a custom addition or use a different name like jurisdiction or applicable_law
Solution:
Tool: SN-Discover-Table-Schema
Parameters:
table_name: ast_contract
Search for fields containing "law", "jurisdiction", or "govern" in the element name or label.
Symptom: Obligation type choices do not include expected categories
Cause: Choice values are organization-specific and may differ from defaults
Solution: Query sys_choice with name=clm_obligation^element=obligation_type to see available choices. Add custom choices if needed.
Scenario: Legal assistant uploads a new vendor agreement and needs metadata extracted
Tool: SN-Read-Record
Parameters:
table_name: ast_contract
sys_id: abc123def456
fields: sys_id,number,short_description,vendor,starts,ends,total_cost,auto_renew,notice_period,governing_law
Extracted Metadata:
Scenario: CLM admin needs to identify contracts with missing metadata
Tool: SN-Query-Table
Parameters:
table_name: ast_contract
query: active=true^governing_lawISEMPTY^ORnotice_periodISEMPTY^ORtotal_costISEMPTY
fields: number,short_description,vendor,starts,ends,governing_law,notice_period,total_cost
limit: 50
Result: 23 active contracts with incomplete metadata. Priority: 8 contracts expiring within 6 months missing notice period data.
legal/contract-analysis - Full contract risk analysislegal/contract-obligation-extraction - Deep obligation extraction and trackinglegal/contracts-query-enhancer - Enhanced contract search capabilitieslegal/legal-matter-summarization - Legal matter context for contractsdocument/document-extraction - Document content extraction from attachmentstesting
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