Is your ServiceNow data ready for AI? A 30-minute check
Five read-only background scripts, what each number means, and the thresholds I use to decide whether a workflow is ready for AI or needs fixing first.
By Nicole Montederamos · ServiceNow CSA · SlickLab.Digital, Cebu City
Part of the guide: ServiceNow AI integration
Most AI projects in ServiceNow that disappoint don’t fail on the model. They fail on what the model is given to read. A summary of a case whose description says “issue” is still “issue”. A router trained on records that bounced between three groups learns to bounce. A knowledge answer drawn from an article that expired in 2023 is confidently wrong. You can find out how much of this you have in about thirty minutes, before anyone writes a prompt or signs a contract.
This post gives you five read-only background scripts, what each number means, and the thresholds I use to decide whether a workflow is ready. It sits under my guide to ServiceNow AI integration. Field names were checked against ServiceNow’s documentation in October 2026; confirm them for your release and your customisations.
Before you start
- Where to run. A recent clone or sub-production instance, in System Definition › Scripts - Background. The scripts only read, but a background script runs with full rights and a big query can slow a busy instance. If production is all you have, run them out of hours.
- What they look at. The last 90 days of incidents. For Customer Service Management, change the table to
sn_customerservice_caseand check the field names: cases use different fields for some of these (resolution notes, for example), and your instance may have its own. - Limits. The scripts that loop over records stop at 2,000. That is enough to see the pattern without loading the instance. The GlideRecord query builder will rewrite any of them for another table or date range.
Check 1: are the descriptions worth reading?
Every AI feature in this area reads the short description first: summaries, routing, similar-record matching, knowledge search. If it is empty, a single word, or the same phrase on hundreds of records, the AI has nothing to work with.
// Short descriptions in the last 90 days: how many are too short, and which repeat most.
var gr = new GlideRecord('incident');
gr.addQuery('opened_at', '>=', gs.daysAgoStart(90));
gr.orderByDesc('opened_at');
gr.setLimit(2000);
gr.query();
var total = 0, tooShort = 0, seen = {};
while (gr.next()) {
total++;
var sd = (gr.getValue('short_description') || '').trim().toLowerCase();
if (sd.length < 15) tooShort++;
seen[sd] = (seen[sd] || 0) + 1;
}
var repeats = Object.keys(seen).sort(function (a, b) { return seen[b] - seen[a]; }).slice(0, 10);
gs.info('Records: ' + total + ', under 15 characters: ' + tooShort + ' (' + Math.round(tooShort * 100 / Math.max(total, 1)) + '%)');
repeats.forEach(function (k) { gs.info(seen[k] + ' x "' + k + '"'); });
Look at the top ten repeats as well as the percentage. Some repeats are fine: monitoring alerts and record producers often fill the short description automatically, and the detail is in the description field. Repeats typed by people (“help”, “not working”, “please assist”) are the problem.
Check 2: does the first route stick?
If records are often reassigned, two things are true. Your routing history is noisy, so a classifier will learn some wrong answers. And people disagree about who owns what, which no model fixes. The incident table keeps a reassignment count, which makes this one quick.
// Closed incidents in the last 90 days: how many were reassigned at least once.
function countClosed(extra) {
var ga = new GlideAggregate('incident');
ga.addQuery('active', false);
ga.addQuery('closed_at', '>=', gs.daysAgoStart(90));
if (extra) ga.addEncodedQuery(extra);
ga.addAggregate('COUNT');
ga.query();
return ga.next() ? parseInt(ga.getAggregate('COUNT'), 10) : 0;
}
var all = countClosed('');
var moved = countClosed('reassignment_count>0');
var bounced = countClosed('reassignment_count>2');
gs.info('Closed: ' + all + ', reassigned: ' + moved + ', reassigned 3+ times: ' + bounced);
For cases, check whether your instance tracks a reassignment count on sn_customerservice_case; if not, the assignment group’s history in the audit log answers the same question, but querying sys_audit is heavy, so filter it tightly and run it in sub-production only. My article on Predictive Intelligence vs an LLM for routing shows the next script to run: volume by group.
Check 3: do closed records say what fixed them?
Close notes are where the answer lives. They feed resolution summaries, similar-case suggestions and any knowledge you want to draft from past work. Empty or one-word close notes mean the AI can see the question but never the answer.
// Closed incidents in the last 90 days: close notes that are missing or too short to help.
var gr = new GlideRecord('incident');
gr.addQuery('active', false);
gr.addQuery('closed_at', '>=', gs.daysAgoStart(90));
gr.orderByDesc('closed_at');
gr.setLimit(2000);
gr.query();
var total = 0, thin = 0, codes = {};
while (gr.next()) {
total++;
if ((gr.getValue('close_notes') || '').trim().length < 30) thin++;
var code = gr.getValue('close_code') || '(empty)';
codes[code] = (codes[code] || 0) + 1;
}
gs.info('Closed: ' + total + ', close notes under 30 characters: ' + thin + ' (' + Math.round(thin * 100 / Math.max(total, 1)) + '%)');
for (var c in codes) gs.info('Close code ' + c + ': ' + codes[c]);
The close code spread is a bonus. If one code (often a generic “solved” option) covers nearly everything, it tells you nothing, and neither the team nor a model can use it to spot patterns.
Check 4: are categories chosen or defaulted?
Categories drive reports, routing rules and assignment. When the form opens with a default category and most people leave it, the field looks filled but says nothing.
// Incidents opened in the last 90 days, by category.
var ga = new GlideAggregate('incident');
ga.addQuery('opened_at', '>=', gs.daysAgoStart(90));
ga.addAggregate('COUNT');
ga.groupBy('category');
ga.query();
while (ga.next()) {
gs.info((ga.category.getDisplayValue() || '(empty)') + ': ' + ga.getAggregate('COUNT'));
}
Find the biggest category in the output. If it is your form’s default value (on many instances it is “Inquiry / Help”) and it holds a large share, people aren’t choosing. That is fine for an AI that reads text, and a problem for anything that relies on the category being right.
Check 5: is the knowledge base current?
If you want AI answers grounded in your own articles (the approach I explain in RAG explained for business owners), the knowledge base is the source of truth. Expired, stale and never-read articles are where wrong answers come from.
// Published knowledge articles: expired, not updated in two years, never viewed.
function countKb(extra) {
var ga = new GlideAggregate('kb_knowledge');
ga.addQuery('workflow_state', 'published');
if (extra) extra(ga);
ga.addAggregate('COUNT');
ga.query();
return ga.next() ? parseInt(ga.getAggregate('COUNT'), 10) : 0;
}
gs.info('Published: ' + countKb());
gs.info('Valid-to date passed: ' + countKb(function (g) { g.addQuery('valid_to', '<', gs.beginningOfToday()); }));
gs.info('Not updated in 2 years: ' + countKb(function (g) { g.addQuery('sys_updated_on', '<', gs.daysAgoStart(730)); }));
gs.info('Never viewed: ' + countKb(function (g) { g.addQuery('sys_view_count', 0); }));
An article not updated in two years may still be right; a password-reset guide can last. Use the number to decide how many articles someone needs to read, not how many to delete.
Reading the results
These are my working thresholds, not ServiceNow’s. They are the points where, in my experience, an AI feature on that data starts to cost more in corrections than it saves.
| Check | Ready | Fix first |
|---|---|---|
| Short descriptions under 15 characters | Under 10% | Over 25% |
| Closed incidents reassigned at least once | Under 20% | Over 40% |
| Close notes under 30 characters | Under 15% | Over 35% |
| Biggest category is the form default | Under 30% of records | Over 50% |
| Published articles expired or never viewed | Under 15% | Over 30% |
Between the two columns, start in suggest mode and watch the accept rate. Each check maps to a workflow, so one bad number doesn’t block everything. Poor close notes hurt resolution summaries and similar-case suggestions, but case summaries of open work can still go ahead. A noisy reassignment rate hurts routing, not summaries. Pick the first workflow from the checks that passed; my list of five CSM workflows shows which data each one needs.
Next steps
Write your five numbers down; they are the baseline that tells you later whether the AI helped. Before anything is switched on, work through the guardrails checklist, because good data still needs a narrow account and a person before every write. If you want a quick, non-technical view of the rest of your readiness, the free AI readiness checker takes five minutes. And if you want me to run this check with you and turn the numbers into a scoped first project, that is the AI Readiness Audit. Tell me what you’re working with.
Questions people ask
How do I know if my ServiceNow data is ready for AI?
Measure it. Run read-only queries on your last 90 days of records: how many short descriptions are too short to mean anything, how often records are reassigned, how many closures have no useful notes, how many categories are left on the default, and how much of your knowledge base is expired or never viewed. The answers tell you what an AI will have to work with.
Is it safe to run these scripts in production?
They only read, but a background script runs with full rights and a heavy query can slow a busy instance. Run them in a recent clone or sub-production instance if you have one. If you must use production, run them out of hours and keep the limits in the scripts.
What if my data fails the check?
Fix the process, not the data. Make the short description mandatory and meaningful, agree the routing rules, require close notes and a close code, and retire stale knowledge. Then measure again in a month. Cleaning old records by hand rarely pays back; better new records do.
Do I need clean data for Now Assist as well as for a custom integration?
Yes. Summaries, routing suggestions and knowledge answers all read the same fields. A native skill does not make a vague short description any clearer than a custom one does.
Start a project