💡 Why toService ManagementIntermediate✨ AI-assisted

Why CMDB Data Quality Decides Whether Service Desk AI Works

WittyTech Daily··4 min read
#cmdb#service-desk#data-quality#itsm

Your service desk assistant reads the CMDB (the configuration management database: your inventory of servers, apps and services, plus who owns them) the way a new hire reads an org chart. It believes every line. That makes CMDB data quality the first thing to check, before you touch a prompt or swap a model.

How bad CMDB data becomes confident wrong triage

Picture a ticket that says "Payroll export is failing." The assistant looks up the service and finds two records, payroll-app-prod and Payroll App (PROD). One names a team that was reorganized last year. The other has no owner at all. The model picks one, writes a tidy summary, and routes the ticket to a queue nobody watches.

Nothing looks broken. The answer is fluent and the ticket is lost. This is an illustration, but if you run a service desk you have seen its cousin.

Three kinds of bad record cause most of it:

  • Duplicates. Two records for one thing. The assistant picks one, and neither is verifiably right.
  • Stale records. The server was retired or the owner left, but the record still reads as plausible. ServiceNow's health model calls a configuration item (CI) stale when it hasn't been updated within the window set for its class, 60 days by default.
  • Ownerless or orphaned records. No owner means no routing target. No relationships means no idea what else breaks. ServiceNow flags orphans by checking for missing required attributes and missing relationships.

Those buckets come from ServiceNow's CMDB Health KPIs and metrics, which score correctness, completeness and compliance. The same checks make sense in any ITSM tool.

A human agent who sees two payroll records squints and pings a colleague. The model doesn't squint. Poor configuration item accuracy used to be an annoyance a person absorbed. Now it feeds automated routing at ticket volume.

Run a CMDB data quality audit before anything else

Export your CIs to CSV and run the script below. Rename the columns to match your tool, because owner, support group and last-updated fields are named differently across CMDBs and releases.

import pandas as pd

cis = pd.read_csv("cmdb_export.csv", parse_dates=["last_verified"])
today = pd.Timestamp.today().normalize()

# 1. Ownerless: no named owner and no support group to route to
ownerless = cis[
    cis["owner"].fillna("").str.strip().eq("")
    & cis["support_group"].fillna("").str.strip().eq("")
]

# 2. Stale: never verified, or not verified within your window
stale = cis[
    cis["last_verified"].isna()
    | (cis["last_verified"] < today - pd.Timedelta(days=90))
]

# 3. Likely duplicates: same normalized name, class and environment
cis["key"] = cis["ci_name"].str.lower().str.replace(r"[^a-z0-9]+", "", regex=True)
dupes = cis[cis.duplicated(["key", "ci_class", "environment"], keep=False)]

for label, df in [("ownerless", ownerless), ("stale", stale), ("duplicate", dupes)]:
    print(f"{label:<10}{len(df):>6}  {len(df) / len(cis):.1%}")

The script counts a CI that was never verified as stale, and it treats names as duplicates when they match once case and punctuation are stripped. That catches payroll-app-prod and Payroll App (PROD), but only the easy cases, so treat the output as a worklist, not a verdict. Start with the CIs that appear in the last few months of tickets rather than the whole table, since those are the ones the assistant will actually touch.

Can't the model work around messy data?

Partly, and it's the best objection. Models are good at fuzzy matching, and a typo in a hostname won't stop one. What they can't do is invent information the data doesn't hold. Nothing in the text of a stale record says it's stale, and nothing tells the model which of two duplicates is the real one. The records that hurt are plausible and wrong, not obviously messy.

Where the model does help is the cleanup. Ask it to cluster likely duplicates or draft owner-confirmation emails, then have a person approve each merge. Use it on the data, not as a substitute for fixing it.

Tell the assistant which records to distrust

Once the audit runs, pass its findings to the model next to each CI it retrieves.

issues = {}
for label, df in [("no_owner", ownerless), ("stale", stale), ("possible_duplicate", dupes)]:
    for name in df["ci_name"]:
        issues.setdefault(name, []).append(label)  # use a unique CI id if names repeat

def ci_for_prompt(row: dict) -> dict:
    found = issues.get(row["ci_name"], [])
    return {**row, "record_health": "needs_review" if found else "ok", "issues": found}

Then add one rule to the system prompt:

If a configuration item has record_health "needs_review", name the issue, do not choose an owner from that record, and route the ticket to the triage queue.

The failure changes from confident wrong routing to an honest "this record needs review". A human can settle that in a minute, and each flag tells you which record to clean next.

Your first step this week

Pull the CIs referenced by last month's tickets, run the audit, and report three numbers: ownerless, stale, duplicate. Assign owners to the worst offenders before you tune anything else. Then rerun it weekly, because CMDB data decays on its own.

An assistant is only as accurate as the records it reads, so a CMDB audit is the cheapest evaluation you can run before putting AI in front of a production service desk.

← More in Service Management