Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

IT Support & Help Desk Fundamentals  Module 12 – Service desk practice

Knowledge bases and self-service that work

Write knowledge-base articles users and technicians can find and reuse, design a self-service portal that cuts calls, and measure deflection honestly.

  • Intermediate
  • 20 minutes
  • Examples run with Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Write knowledge-base articles that users and technicians can find and follow
  • Maintain articles by reviewing them every time they are reused
  • Design a self-service portal and request catalogue that reduce calls
  • Measure whether self-service actually resolves issues

Before you start

What you’ll learn · Before you start

What you will learn

  • Write knowledge-base articles that users and technicians can find and follow
  • Maintain articles by reviewing them every time they are reused
  • Design a self-service portal and request catalogue that reduce calls
  • Measure whether self-service actually resolves issues

Before you start

On this page

One help desk received 118 tickets in a quarter with the same words: “Wi-Fi dropping on the floor six laptops”. The fix is a single power-save setting on a known adapter model, documented on one technician’s own laptop and nowhere searchable. Six weeks later she takes two days off, the fix lives in a note nobody else can read, and the hundred and nineteenth caller rings in.

What works is an article the next technician can find in seconds, follow without help and fix when a step goes stale, inside a self-service portal where users close the common requests themselves. You will write such an article, keep it current on every reuse, plan the portal around it, and judge it by the readers who say it solved their problem rather than by how many opened the page.

One article covers one task, in seven fixed fields

A knowledge-base article: A short written document in the knowledge base that explains one support task: what the user sees, why it happens and how to fix it, so a technician who has never met the problem can run through it and close the ticket. is a one-page answer to a question a user types, written so a technician who has never met the problem can run through it and close the ticket. The hardest part is deciding what one article covers. The rule to follow is one task per article: a title that answers one question, with one environment, one cause and one fix. “Printing and scanning on floor three” folds two problems into one page, so the search for a scanning problem returns a page half about printing, and neither search finds the right first paragraph.

Inside the article, the MySmartCoPilot KB template: The fixed set of seven named sections of the knowledge-base article template this track teaches, in order: Title, Environment, Symptoms, Cause, Resolution, Verification, and When to escalate. this track uses has seven fields in a fixed order: Title, Environment, Symptoms, Cause, Resolution, Verification, and When to escalate. Each field has a job the others cannot do. The title is a search target: it uses the user’s words, not the system’s, because a search for “wifi dropping” finds the former and misses the latter. Environment names the device, operating system version and build and the application version, because the same symptom on different builds often has different causes. Step through the seven fields below; each stop says what belongs in the field:

Interactive · step by step One article, seven template fields Step through the seven fields of a knowledge-base article in order. Each stop names what goes in the field, so a reader learns the template by walking it.
One article, seven template fields, step 7 of 7. Showing Title (the user's words), Environment (device, OS, version), Symptoms (what the user sees), Cause (why it happens), Resolution (numbered steps), Verification (prove the fix held), When to escalate (who to call next). In focus: When to escalate.Titlethe user's wordsEnvironmentdevice, OS, versionSymptomswhat the user seesCausewhy it happensResolutionnumbered stepsVerificationprove the fix heldWhen to escalatewho to call next

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. Title, in the user's words. The title repeats what the user types or says, not a system name: a search for "Wi-Fi drops on floor six" finds this title, and nobody searches for "wireless adapter power management anomaly". One task per article: two problems get two titles.
  2. Environment, exact. Which devices, which operating system version and build, which app version. The same symptom on Windows 11 24H2 and macOS 15 often has different causes, so narrow the article to the environment the fix works on.
  3. Symptoms, in plain words. What the user sees, with the exact error text where there is one. A symptom written the way the screen shows it, such as "No internet", is useful; "connectivity issue" is not, because nobody searches that way.
  4. Cause, as far as you know. The condition that makes the symptom happen, written honestly: "The adapter saves power by turning the radio off" is a cause; "something to do with the network" is a guess the next technician cannot act on.
  5. Resolution, numbered steps. The fix, as numbered steps a less experienced reader can follow without ringing the author. One instruction per step, the control named the way the screen names it, and a short sentence per step on what it did.
  6. Verification that it held. How to prove the fix held, before the ticket closes. Watch the Wi-Fi icon stay on through a two-minute test call, print a one-page test page, open the file the user could not open: name the check so the next reader runs the same one.
  7. When to escalate. The one sentence that says when the article has run out: "if the icon still drops after the fix, raise a ticket for the floor router team with the time and the floor number." A reader must never have to guess who to call next.

The two fields that get skipped most are Verification and When to escalate. Without Verification, a reader runs the Resolution steps but has no agreed way to prove the fix held, so the ticket closes on hope. Without When to escalate, the article runs out of road and the next reader guesses who to call. Writing both takes two sentences and saves the next technician a root cause: The condition that makes a fault happen. Fixing it stops the fault from coming back, while fixing only a symptom, or working around it, leaves the cause in place. More in “A troubleshooting method that holds under pressure” hunt they have no time for. “One task per article” is the rule that keeps the template honest; a tempting second task becomes its own article and links to this one.

A title that reads for the system, not the user

Wrong: “Wireless adapter power-management anomaly on Model X laptops.” Right: “Wi-Fi drops every few minutes on the floor six laptops.” The first title names a cause the user does not know, so their search returns nothing. The second quotes the user, so the words they type are the words it matches.

Write while you solve the ticket

Articles that get written on Thursdays, in a separate “documentation hour”, are expensive and quickly stale. The habit to build is capture while you solve the ticket: open a draft inside the ticket as you work, using the seven template fields, and finish it before the ticket closes. The Consortium for Service Innovation’s Knowledge-Centred Service: The Consortium for Service Innovation's method, KCS, in which support teams reuse, improve and capture knowledge-base articles as part of solving every ticket; its newest practices guide renames it Knowledge-Centered Success. method runs a similar loop: reuse what the team already knows, improve it as you use it, and capture what is missing while the context is fresh. Its newest practices guide renames the method Knowledge-Centered Success and keeps the abbreviation KCS®, a service mark of the Consortium; both guides are in the references.

The habit has four stages, and the first ticket that reuses the article is where it earns its place. Every stage is a small action a technician can take without leaving the ticket:

Interactive · stage by stage Reuse, flag and improve, every time Walk the cycle a service desk turns on every ticket. Each stage names a short action, and the branch at the end sends the loop back to the first stage for the next ticket.
Reuse, flag and improve, every time, step 5 of 5. Showing Find it or write it (the user's own words), Use the article (quoted, not retyped), Flag what is wrong, Improve the article (minutes, not days). In focus: Find it or write it.next ticketFind it or write itthe user's own wordsUse the articlequoted, not retypedFlag what is wrongstale step, missing factImprove the articleminutes, not daysnext ticket

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. Find it, or write a draft now. As soon as a ticket opens, search the knowledge base for the user's own words. If an article answers the question, work from it. If no article exists, start a short draft in the ticket itself with the seven template fields, so the record of the work is also the article.
  2. Use it, do not retype it. Follow its steps on the device, and send the user the same words you are reading. A reply that quotes the article is faster to write, correct the first time, and easy for a colleague to continue if the call drops.
  3. Flag what the article got wrong. Every reuse is a review. A step named a menu that was renamed, a screen the user never sees, a version the fix no longer applies to: mark it on the article as you work, in one sentence, so the next reader sees it before they trust the step.
  4. Improve the article, now. Fix the step while the ticket is fresh. Bump the version string in the title, update the date, name the setting the way the current screen names it. Small changes, in minutes, are what keep articles alive.
  5. The next ticket arrives. The loop turns. The next similar ticket starts at the first stage with the improved article, so a few minutes of improvement pay back on every later read.

The cycle turns because every article reuse: When a technician uses an existing knowledge-base article to solve a new ticket. Each reuse is logged on the ticket, which is also the moment to flag any step that is wrong or stale. is a review. On the second similar ticket, the technician reads the article as a reader for the first time and sees the step that names a menu that has since been renamed; they flag the step and change it in the same breath. Articles improved in minutes stay alive; articles saved for a documentation hour that never happens die quietly. Keep improvement in the same tool as the ticket, so a technician who already has the fix open does not need a second sign-in and a context switch.

The four stages together are the KB review cycle: The four-stage habit a service desk runs on every ticket to keep its knowledge base alive: find or write an article, use it in the fix, flag any step that is wrong, and improve the article before the ticket closes. a service desk turns on every ticket. Three things keep it working. First, the author of a draft is anyone who solved the ticket, not a special writer: handing drafts to “the writer” delays every article by days. Second, every reuse of an article is logged on the ticket by its reference, so the article’s reuse count rises and the team can see which pages are earning their keep. Third, articles have an owner, named on the page itself, who is the person a flag ends up with when the next reader does not have the authority to change it on the spot.

Checkpoint

Check: Template and one task per article · Capture, reuse, flag, improve

  1. Question 1 of 2 A reader sends you a draft titled "Printing and scanning on floor three". What is the first thing to do with it?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Split it into two articles, one for printing and one for scanning

    One task per article means one title that answers one search, one environment, one cause and one fix. Two problems become two articles that can link to each other.

  2. Question 2 of 2 You reuse an article on a ticket and spot that step three names a menu that was renamed last month. The ticket is open and the user is waiting. What do you do?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Flag the step on the article and fix the name while the ticket is fresh

    The cycle is find or write, use, flag, improve. Flag the step and fix it on the article while the ticket is open; the next reuse starts from the improved version.

A knowledge-base article is useful only when the person with the problem can find it. That is a writing problem, not a software one: a search engine returns what it is given, and a page that uses private jargon returns to no one. Three rules sort most of it. Write the title and the symptoms in the words the user types, including the exact error text and code where there is one, because 0x000006ba is a signature that cannot be guessed and “spooler” is what people search. Avoid internal shorthand: “the Pune-3 box” means nothing to a new starter, so “the shared printer on the Pune third floor” wins. Date and version every article, so a stale article is a visibly stale one.

The last of these is the trap. A knowledge base without visible dates and versions collects pages that were right for the operating system of three years ago and are wrong for every reader today, and the search still returns them. Put a version string in the title and the date of the last change where a search result shows it, in the title or the article’s details. For the words themselves, Microsoft’s style guide gives plain language: Writing and speaking for the person who has to act: what the user can see rather than what the system does, one instruction at a time, short sentences, and the exact words from the screen. More in “Support conversations: listen, ask, explain” advice that suits every article a desk writes: write like you speak, and avoid jargon and overly technical language.

A readability score keeps that habit measurable. The Flesch-Kincaid grade: A readability number from the formula 0.39 * (words / sentences) + 11.8 * (syllables / words) - 15.59, read as the US school grade a reader at that level would be in. About grade 8 suits text meant for the general public. comes from a study for the US Navy in which J. Peter Kincaid and colleagues recalculated Rudolf Flesch’s reading-ease formula against the reading tests of 531 enlisted Navy personnel. It weighs the average words per sentence and syllables per word, and gives the result as a US school grade. Readable’s guide to the score suggests about grade 8 for text meant for the general public; the linter below flags an article above grade 10, which leaves room for the product names a help-desk article cannot avoid. It runs the formula on two in-memory articles, a weak one and a strong one, and prints every problem it finds:

Linting two in-memory KB articles Python · kb/kb_lint.py
"""Lint two in-memory knowledge-base articles against the MySmartCoPilot template.

Checks every template section (Title, Environment, Symptoms, Cause, Resolution,
Verification and Escalation, the code's short name for When to escalate), a
version string, an ISO 8601 date and the Flesch-Kincaid reading grade,
computed with the standard formula and a stdlib-only syllable counter. Both
articles below are invented in-memory: one weak article (missing Verification,
no version, no date, dense wording), and one strong article (every section, a
version, an ISO 8601 date, a grade near a general audience).
"""

import re


TEMPLATE_SECTIONS = (
    "Title",
    "Environment",
    "Symptoms",
    "Cause",
    "Resolution",
    "Verification",
    "Escalation",
)
VERSION = re.compile(r"\bv\d+(?:\.\d+){0,2}\b")
ISO_DATE = re.compile(r"\b\d{4}-\d{2}-\d{2}\b")
WORD = re.compile(r"[A-Za-z]+")
SENTENCE_END = re.compile(r"[.!?]+")
VOWELS = "aeiouy"


def count_syllables(word):
    """Count vowel groups in one word, with two common rules.

    Stdlib only. A vowel group is a run of a, e, i, o, u or y. A trailing
    silent "e" is subtracted when a consonant comes just before it, unless
    the word ends in a consonant then "le" (as in "simple"). The count is
    never below 1.
    """
    word = word.lower()
    if not word:
        return 0
    groups = re.findall(r"[aeiouy]+", word)
    count = len(groups)
    if count > 1 and word.endswith("e") and word[-2] not in VOWELS:
        is_consonant_le = (
            len(word) >= 3
            and word[-2] == "l"
            and word[-3] not in VOWELS
        )
        if not is_consonant_le:
            count -= 1
    return max(count, 1)


def flesch_kincaid_grade(text):
    """Return the Flesch-Kincaid grade of a text, or None when it is too short.

    Standard formula (Kincaid et al., 1975):
        0.39 * (words / sentences) + 11.8 * (syllables / words) - 15.59
    rounded to one decimal.
    """
    words = WORD.findall(text)
    sentences = [s for s in SENTENCE_END.split(text) if s.strip()]
    if not words or not sentences:
        return None
    syllables = sum(count_syllables(w) for w in words)
    w = len(words)
    s = len(sentences)
    return round(0.39 * w / s + 11.8 * syllables / w - 15.59, 1)


def lint(article):
    """Return the sorted problems in one article against the KB template."""
    problems = []
    sections = dict(article.get("sections", {}))
    for name in TEMPLATE_SECTIONS:
        if name not in sections or not sections[name].strip():
            problems.append(f"missing section: {name}")
    text = "\n".join(sections.values())
    if not VERSION.search(text):
        problems.append("no version string")
    if not ISO_DATE.search(text):
        problems.append("no ISO 8601 date")
    grade = flesch_kincaid_grade(text)
    if grade is None:
        problems.append("too short to grade for reading")
    elif grade > 10:
        problems.append(f"reading grade {grade} is above 10")
    return sorted(set(problems))


# A weak article: Verification is missing, there is no version, and the prose
# is dense enough to push the reading grade well above 10.
WEAK = {
    "sections": {
        "Title": "Wifi issues",
        "Environment": "Various laptops.",
        "Symptoms": (
            "The networking subsystem experiences intermittent disconnection "
            "events, particularly in dense enterprise wireless environments "
            "where interference considerations dominate operational behaviour."
        ),
        "Cause": (
            "A heuristic power-management policy enacts an aggressive "
            "suppression of the wireless radio subsystem during idle intervals."
        ),
        "Resolution": (
            "Reconfiguration of the power-management parameters associated "
            "with the wireless network adapter is required."
        ),
        "Escalation": "Escalate to networking.",
    },
}

# A strong article: every section is present, a version string sits in the
# title, the date is an ISO 8601 date, and the prose reads at a general level.
STRONG = {
    "sections": {
        "Title": (
            "Wi-Fi drops every few minutes on the floor six laptops "
            "(v2, dated 2026-10-04)"
        ),
        "Environment": (
            "Model X laptops on floor six, running Windows 11 version 26H2 "
            "(OS build 26300) with the standard adapter driver that the "
            "imaging team ships."
        ),
        "Symptoms": (
            "The Wi-Fi icon turns off, then comes back after about a minute "
            "with the message 'No internet'. The pattern shows up during "
            "video calls and whenever a user downloads something large."
        ),
        "Cause": (
            "The wireless adapter saves power by turning the radio off during "
            "quiet moments. The dense Wi-Fi mesh on this floor cannot hand "
            "the laptop back in time, so the system shows the link as lost."
        ),
        "Resolution": (
            "Open Device Manager, pick the wireless adapter and open its "
            "Power Management tab. Clear 'Allow the computer to turn off "
            "this device to save power', apply the change and restart the "
            "laptop once."
        ),
        "Verification": (
            "Ask the user to run a short test call for about two minutes "
            "and watch the Wi-Fi icon stay on for the whole call. Close "
            "the ticket when the call runs without a dropout."
        ),
        "Escalation": (
            "If the connection still drops after the fix, raise a ticket "
            "for the floor router team with the time, the floor number "
            "and the identifier of this article attached."
        ),
    },
}


def main():
    for name, article in [("weak article", WEAK), ("strong article", STRONG)]:
        print(name)
        problems = lint(article)
        if not problems:
            print("    clean: nothing to fix")
        for problem in problems:
            print(f"    - {problem}")
        grade = flesch_kincaid_grade("\n".join(article["sections"].values()))
        print(f"    reading grade: {grade}")
        print()
    clean = sum(1 for a in [WEAK, STRONG] if not lint(a))
    print(f"{clean} of 2 articles pass the KB template check.")


if __name__ == "__main__":
    main()

Output

weak article
    - missing section: Verification
    - no ISO 8601 date
    - no version string
    - reading grade 19.7 is above 10
    reading grade: 19.7

strong article
    clean: nothing to fix
    reading grade: 9.3

1 of 2 articles pass the KB template check.

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 kb_lint.py

The weak article fails four checks: Verification is missing, it carries no version string and no ISO date, and it reads at grade 19.7. The strong one has every field, a version and an ISO date in its title, and reads at grade 9.3. The exercise at the end checks the rules this linter leaves out: the exact error code in the title, internal shorthand, and a version and a date where a search result shows them.

Run the linter in the browser

Press Edit on the example above, replace the first sentence of the strong article’s Cause with the weak article’s long Symptoms sentence, and press Run. The strong article’s grade climbs from 9.3 to 11.1, and the linter adds reading grade 11.1 is above 10 to its findings.

Self-service works when every request has an owner and a path

Even a well-written knowledge base closes only the tickets a user searches first. A self-service portal: A website where users raise requests, read knowledge base articles and finish common tasks such as a password reset themselves, at any hour: tier 0 of the tier model this track uses. More in “IT support roles, tiers and channels” raises that number by placing the knowledge base, the request forms and a few finished actions on one page the user already has a reason to open. The portal is tier zero of the desk: a reset the user runs themselves, a form the user raises instead of a ticket, a page that answers “is it just me?” without a call. A first catalogue often starts with four kinds of entry, and each entry is a row in the request catalogue: The published list of self-service items a user can raise or do themselves on the portal, each row named with the user's own words and carrying an owner, a fulfilment path and a target time. with the same four columns: what the user picks, who owns it, how it is delivered, and how fast.

Catalogue item Owner Fulfilment path Target time
Password or MFA reset identity team portal, with identity verification 2 minutes
New software from the standard list application team portal, delivered through the device management tool 1 business day
Access to a shared folder or inbox the folder’s owner, then identity team portal, with the owner’s decision recorded 1 business day
Service status (what is broken right now) the service’s team a status page the portal links to live

A row without an owner is a row the request gets stuck on, and a row without a fulfilment path is a row that becomes a phone call anyway, so a catalogue item is finished only when both are named. The portal lists them with the user’s own words on each row, links the knowledge-base article that explains it where one exists, and shows the current state of the user’s own requests. A new catalogue item lives in draft until the owner says what the fulfilment path is and the desk has an article that answers the common questions about it; adding items before both of those exist drops them into the desk’s queue instead.

Two patterns are worth building in early. First, every portal action logs a ticket of its own, so the desk still sees what the self-service did and can measure the effect; second, every catalogue item has an “ask for help” link that raises a ticket with the context attached, so a user who gets stuck does not have to start again on the phone. The goal is not to turn the user away from the desk; it is to let them close the easy requests themselves and keep the desk’s attention for the ones nobody has yet solved.

Checkpoint

Check: Writing for search · Portal and request catalogue

  1. Question 1 of 2 Which title is most likely to be found by the next user with the same fault?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Printer stops with error 0x000006ba, spooler offline on the Pune third floor

    Writing for search means the exact error text and the words users type, plus the environment, in the title and the symptoms. Internal names belong under Cause, not in the title.

  2. Question 2 of 2 Which of these must every item of the request catalogue have? Choose every one.

    Choose every answer that is right.

    Show the answer: Question 2 of 2

    Answer:

    • A fulfilment path
    • A target time
    • A named owner

    Every catalogue item is finished when its owner, its fulfilment path and its target time are named, with a knowledge-base article that answers the common questions about it. Anything less lands back in the desk's queue.

Measure deflection honestly

The last habit of a working knowledge base is to measure what it does, the way it works rather than the way that is easy to count. The common mistake is to compute the deflection rate: The share of support interactions a self-service article or portal removes from the technicians' queue; measured honestly, it counts only views where the user confirmed the fix, not every view. from every article view that no ticket follows, because views are easy to count and a missing ticket looks like a fix. A view is a visit, not a fix: a reader who tried the first step and gave up still counts, and so does one who closed the tab and asked a colleague at the next desk. The Consortium’s guide to measuring self-service says as much: not every failed attempt turns into a case. The number looks good, and the backlog does not move.

A better rate counts only views where the user confirmed the fix. One honest signal is a “did this solve it?” button at the bottom of each article, answered on the spot; another is the number of tickets opened by the same user within the next day that match the article’s keywords. The program below builds one thousand invented views, records for each whether a ticket followed and whether the reader pressed Yes, and prints both rates side by side:

A view is not a resolution: naive vs. honest deflection Python · deflection/deflection.py
"""A view is not a resolution.

Simulates 1,000 invented views of one knowledge-base article. Each view has
two signals: whether the user opened a ticket afterwards (a weak but easy
signal), and whether the user answered 'yes' to 'did this solve it?' at the
bottom of the article (a slower but honest signal).

The naive deflection rate counts every view that did not raise a ticket as a
resolution; the resolution-confirmed rate counts only the 'yes' answers. The
chances below are set so that about 80 % of views raise no ticket and about
42 % end in a 'yes'; with seed 42 the program prints 82.0 % and 41.6 %, a gap
of 40.4 points. The data is built in-memory from one seed; no file is read.
"""

import random


TOTAL = 1000
SEED = 42


def build_views(total, seed):
    """Return a list of invented view records.

    Each record carries two independent facts about one invented reader:
      - raised_ticket: True when the reader opened a ticket after the view.
      - answered_yes:  True when the reader answered 'yes' to the 'did this
                       solve it?' prompt (only readers who did not raise a
                       ticket are asked, and most of them never answer).
    """
    rng = random.Random(seed)
    views = []
    for _ in range(total):
        raised_ticket = rng.random() < 0.20
        # Of the ~80 % who do not raise a ticket, roughly 52.5 % answer 'yes',
        # which lands the honest rate near 42 % of all views.
        answered_yes = (not raised_ticket) and (rng.random() < 0.525)
        views.append({"raised_ticket": raised_ticket, "answered_yes": answered_yes})
    return views


def main():
    views = build_views(TOTAL, SEED)
    no_ticket = sum(1 for v in views if not v["raised_ticket"])
    confirmed = sum(1 for v in views if v["answered_yes"])
    naive = no_ticket / TOTAL
    honest = confirmed / TOTAL
    gap = naive - honest

    print(f"views total                                            {TOTAL}")
    print(f"views that did not raise a ticket afterwards           {no_ticket}")
    print(f"views where the user answered 'yes, it solved it'      {confirmed}")
    print()
    print(f"naive deflection rate (view = resolution)              {naive:.1%}")
    print(f"resolution-confirmed deflection rate ('yes' answers)   {honest:.1%}")
    print(f"gap between the two rates                              {gap:.1%}")
    print()
    print("A view is a visit, not a fix: the honest rate asks the reader.")


if __name__ == "__main__":
    main()

Output

views total                                            1000
views that did not raise a ticket afterwards           820
views where the user answered 'yes, it solved it'      416

naive deflection rate (view = resolution)              82.0%
resolution-confirmed deflection rate ('yes' answers)   41.6%
gap between the two rates                              40.4%

A view is a visit, not a fix: the honest rate asks the reader.

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 deflection.py

The naive rate reads 82.0 % on this data, the resolution-confirmed rate 41.6 %, and the gap is 40.4 percentage points. The honest number is less flattering and more useful: 416 of the 1,000 readers said the article solved their problem, and the rest said no, raised a ticket or never answered. Even this generous invented case, where about half of the readers who raised no ticket pressed Yes, halves the naive number. Real readers answer far less often: the same Consortium guide puts participation in article feedback at about 1.5 %, so a Yes count is a floor under the true rate, read beside the tickets that follow a view. A desk that steers on the honest numbers knows which articles need rewriting; a desk that steers on the naive one adds more articles the users never finish.

Key idea

A view is not a resolution. Count the users who said the article solved their problem, and the users who opened a ticket afterwards, before you call a page a deflection.

Checkpoint

Check: Deflection, measured honestly

  1. One question In one month an article has 2,000 views. A ticket from the same reader followed 300 of them, and 34 readers pressed Yes under "did this solve it?". Which reading is right?

    Choose one answer.

    Show the answer: One question

    Answer: At least 34 readers confirmed a fix, and likely far more were helped; read it beside the 300 views a ticket followed

    The 1,700 views that no ticket followed give the naive 85 %, which counts quiet failures as fixes. Only 34 readers confirmed a fix, and because so few readers answer the button, that is a lower bound rather than the rate. Read the confirmed count and the tickets after a view together, month after month, before you call the page a deflection.

Practise: lint a knowledge-base article

The exercise turns the rules of writing for search into checks: an error code from the symptoms that the title lacks, internal shorthand anywhere in the article, and a title without a version or a date of last change. The sample tests check a findable article, a missing code, one code written twice in two cases, two pieces of shorthand, an undated title and a date kept in the article’s details.

Exercise · Medium · Python

Lint an article for the words people search

The linter in the lesson checks the template fields and the reading grade. This exercise checks the rules of writing for search that it leaves out: the exact error code in the title, no internal shorthand, and a version and a date where a search result shows them. Write lint_article(article, shorthand) and return its problems as a list of strings, in the order of the four checks below, or an empty list for an article that search will find.

  • article["sections"] is a dict of section name to text. The "Title" and "Symptoms" sections matter most here, and any section may be absent.
  • article["updated"], when present, is the date of the article's last change, as text.
  • shorthand is the desk's list of internal names that users never type, such as "Pune-3 box".

The checks:

  1. Error codes. An error code is 0x (or 0X) followed by exactly eight hexadecimal digits. For every code in the Symptoms that the Title does not contain (ignoring case), once each and in order of first appearance, add "title lacks error code <code>" with the code in lower case.
  2. Shorthand. For every term of shorthand, in its order, that appears in any section, the Title included, ignoring case, add "internal shorthand: <term>" with the term as given.
  3. Version. When the Title has no version token (a lowercase v, then one to three dot-separated groups of digits, as in v2 or v2.4), add "no version in title".
  4. Date. When the Title holds no real YYYY-MM-DD date and article["updated"] is not one either, add "no date of last change". A real date is one the calendar has: 2026-02-30 is not.

The article itself must not change.

Starter code · lint_article.py

"""Starter for lint_article(article, shorthand): the four search checks of the task, in their order."""

import re
from datetime import date

ERROR_CODE = re.compile(r"\b0[xX][0-9A-Fa-f]{8}\b")
VERSION = re.compile(r"\bv\d+(?:\.\d+){0,2}\b")
ISO_DATE = re.compile(r"\b\d{4}-\d{2}-\d{2}\b")


def is_real_date(text):
    """True when text is one YYYY-MM-DD date that the calendar has."""
    # TODO: the whole text must match ISO_DATE, and date.fromisoformat must accept it.
    return False


def lint_article(article, shorthand):
    """Return the search problems of one article, in the order of the four checks."""
    problems = []
    # TODO 1: every error code of the Symptoms, once each, that the Title lacks.
    # TODO 2: every shorthand term found in any section, the Title included.
    # TODO 3: no version token in the Title.
    # TODO 4: no real date in the Title, and none in article["updated"].
    return problems
The sample tests · test_lint.py
"""Sample tests for lint_article(article, shorthand)."""

from lint_article import lint_article

SHORTHAND = ["Pune-3 box", "the cage"]


def article(title, symptoms, **extra):
    sections = {"Title": title, "Symptoms": symptoms, "Resolution": "Restart the print spooler service."}
    return {"sections": sections, **extra}


def test_a_findable_article_has_no_problems():
    a = article("Printing fails with 0x000006ba on Windows 11 (v2, 2026-10-04)", "Every print job stops with error 0x000006ba.")
    assert lint_article(a, SHORTHAND) == []


def test_the_title_must_carry_the_error_code():
    a = article("Printing fails (v2, 2026-10-04)", "Every print job stops with error 0x000006ba.")
    assert lint_article(a, SHORTHAND) == ["title lacks error code 0x000006ba"]


def test_each_missing_code_is_named_once_in_lower_case():
    a = article("Network share fails (v1, 2026-10-04)", "Error 0x80070035 appears, then 0X80070035 again, then 0x000006BA.")
    assert lint_article(a, SHORTHAND) == ["title lacks error code 0x80070035", "title lacks error code 0x000006ba"]


def test_internal_shorthand_is_flagged_in_any_section():
    a = article("Scanner on the Pune-3 box is offline (v1, 2026-10-04)", "Nothing scans from the cage either.")
    assert lint_article(a, SHORTHAND) == ["internal shorthand: Pune-3 box", "internal shorthand: the cage"]


def test_an_undated_unversioned_title_gets_two_problems():
    a = article("Printing fails", "Jobs stay in the queue.")
    assert lint_article(a, SHORTHAND) == ["no version in title", "no date of last change"]


def test_the_date_may_sit_in_the_details():
    a = article("Printing fails (v3)", "Jobs stay in the queue.", updated="2026-09-30")
    assert lint_article(a, SHORTHAND) == []
A hint

Compare lower-case text with lower-case text: the code from the Symptoms, the Title, and the joined text of every section. A list of the codes you have already handled keeps each code to one problem. For the date, write is_real_date first: ISO_DATE.fullmatch(text) checks the shape, and date.fromisoformat raises ValueError for a day the calendar does not have.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Then check all five ideas, from the seven template fields to the honest deflection rate; each question you get depends on how you answered the one before:

Practice that adapts to you

Practise this lesson

10 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 10 Which of these are the fields of MySmartCoPilot's knowledge-base article template? Choose every one.

    Choose every answer that is right.

    Show the answer: Question 1 of 10

    Answer:

    • Resolution
    • Title
    • Environment
    • Cause
    • Verification
    • Symptoms
    • When to escalate

    The template is Title, Environment, Symptoms, Cause, Resolution, Verification and When to escalate, in that order. One task per article keeps all seven fields honest.

  2. Question 2 of 10 A technician proposes an article "VPN and Wi-Fi on travel laptops: a complete guide". Why is this a problem?

    Choose one answer.

    Show the answer: Question 2 of 10

    Answer: It folds two different tasks into one page, so neither search finds the right first paragraph

    A knowledge-base article covers one task so that the search for one problem returns a page about that problem. Split the guide into two articles that link to each other.

  3. Question 3 of 10 When should the first draft of a knowledge-base article be written?

    Choose one answer.

    Show the answer: Question 3 of 10

    Answer: Inside the ticket, while you solve it

    Capture while you solve, so the record of the work is also the article. The habit survives because it is in the same tool as the ticket, with no extra sign-in.

  4. Question 4 of 10 Why is "every reuse is a review" the engine of the cycle?

    Choose one answer.

    Show the answer: Question 4 of 10

    Answer: The reader sees the article as a new reader does, and spots stale words the author no longer sees

    Every reuse puts a new reader on the article; the new reader sees what the author no longer sees. Fixing a bad step in minutes is what keeps articles alive over years.

  5. Question 5 of 10 In kb_lint.py, what Flesch-Kincaid grade does the lesson's strong article receive?

    Type a number.

    A hint

    Look at the second block of the example's output, under "strong article".

    Show the answer: Question 5 of 10

    Answer: 9.3 grade

    The example prints reading grade 9.3 for the strong article, below the linter's ceiling of 10, so the linter raises no reading finding for it.

  6. Question 6 of 10 Where should the exact error text or code sit in a knowledge-base article?

    Choose one answer.

    Show the answer: Question 6 of 10

    Answer: In the title and the symptoms, so a search for that text finds the article

    Put the exact error text and code in the title and the symptoms, in plain language, and leave the system's own names for the Cause section.

  7. Question 7 of 10 What is a request catalogue?

    Choose one answer.

    Show the answer: Question 7 of 10

    Answer: A published list of self-service items, each with an owner, a fulfilment path and a target time

    The catalogue is the published list a user picks from on the portal: password reset, software requests, access requests, and so on. Each row names the owner, the path and the target time.

  8. Question 8 of 10 A portal item lets users request access to a shared folder, but about a tenth of users still ring the desk. The desk is annoyed. What is the better next move?

    Choose one answer.

    Show the answer: Question 8 of 10

    Answer: Add an "ask for help" link beside the item that raises a ticket with the context attached

    Self-service is a path for easy requests, not a wall against the desk. An "ask for help" link beside each item sends the user forward with their context, so the desk starts from a filled ticket rather than a cold call.

  9. Question 9 of 10 What does "a view is not a resolution" mean when measuring deflection?

    Choose one answer.

    Show the answer: Question 9 of 10

    Answer: A page view counts a visit, not whether the article solved the user's problem

    Count only views where the user confirmed the fix, and watch the tickets opened in the next day after a view. Both signals exclude "read a step, then rang the desk".

  10. Question 10 of 10 In deflection.py, how many of the 1,000 views are counted by the resolution-confirmed rate?

    Type a number.

    A hint

    Look at the line "views where the user answered 'yes, it solved it'" in the output.

    Show the answer: Question 10 of 10

    Answer: 416 views

    The program prints 416 confirmed views out of 1,000, a resolution-confirmed rate of 41.6 %. The naive rate on the same data is 82.0 %, a gap of 40.4 percentage points.

Interview questions

Warm-up (fresher): a technician writes “spool woes” as a title and resolves the ticket. A week later the next user searches for 0x000006ba. Why does the search miss, and what title would the technician write today?

The search misses because the article’s words and the user’s words do not overlap: “spool woes” is private shorthand for the author, while 0x000006ba is the exact error code the user sees and “spooler” is the word everyone types. A search engine indexes the words in the article; it does not know that “spool woes” is about the spooler, and it does not translate between shorthand and plain language. A title written today would quote both the symptom in the user’s words and the code: “Printer stops with error 0x000006ba, spooler offline on the Pune third floor”. That title names the user’s words, the exact code (so a code search returns the article), and the environment (so a reader on another floor knows whether this is their fix). The habit to build is to write the title the way the user types the problem into the search box; the system’s internal name belongs in the Cause section, not the title.

Two harder cases follow: a new starter who finds three kinds of ticket that only one colleague knows how to fix, and a portal launch that a project lead credits with 18 % fewer tickets. Sketch what you would do first in each case, then open it:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    In your first week on a new desk, three kinds of ticket keep coming back, and each has a fix that only one colleague knows. How do you capture an article for each, find its owner and publish it, from your call with the user to the next reader finding it?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    Your desk launched a self-service password-reset form on its portal, and the next month's tickets fell from 2,400 to 1,970. The project lead reports 18 % deflection. What else could explain the fall, and how would you estimate how many tickets the form really removed?

    Model answer, Pro. First step and follow-ups

Flashcards · 6 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. Which seven fields does a knowledge-base article in this track have?

    Title, Environment, Symptoms, Cause, Resolution, Verification and When to escalate, for one task, with a named owner who takes a flag when a reader cannot change the article.

  2. When is a knowledge-base article written, and when is it improved?

    It is captured while the ticket is being solved and improved every time it is reused, so a stale step flagged and fixed in minutes stays fixed for every later reader.

  3. An article is titled "spool woes", and the next user searches for 0x000006ba. Why does the search miss?

    The article's words and the user's words do not overlap. Put the exact error code and text, and the words users type, such as spooler, in the title and the symptoms.

  4. How readable should a knowledge-base article be?

    At or below Flesch-Kincaid grade 10, with no internal jargon, and with a version on every article.

  5. When do a self-service portal and a request catalogue really cut calls?

    When every catalogue item has an owner, a fulfilment path and a target time, and an article answers the common questions about it.

  6. How do you measure deflection honestly?

    A view is not a resolution. Count the readers who said the article solved their problem, treat those few answers as a floor, and watch for tickets opened right after a view.

Key takeaways

  • A useful knowledge-base article covers one task, in seven fixed fields (Title, Environment, Symptoms, Cause, Resolution, Verification, When to escalate), and names the owner who takes a flag when a reader cannot change it.
  • Capture while you solve the ticket, and improve the article every time it is reused: a stale step flagged and fixed in minutes stays fixed for every reader who comes after.
  • Write for search, so a reader finds the page from the words they already type: the exact error text and code in the title and the symptoms, no internal jargon, a version and a date on every article, and prose at or below Flesch-Kincaid grade 10.
  • A self-service portal and a request catalogue cut calls only when every catalogue item has an owner, a fulfilment path and a target time, and a knowledge-base article that answers the common questions about it.
  • Measure deflection honestly: a view is not a resolution, so ask the reader whether the article solved it, treat the few answers as a floor, and watch the tickets opened right after a view before you call a page a deflection.

Terms in this lesson

article reuse
When a technician uses an existing knowledge-base article to solve a new ticket. Each reuse is logged on the ticket, which is also the moment to flag any step that is wrong or stale.
deflection rate
The share of support interactions a self-service article or portal removes from the technicians' queue; measured honestly, it counts only views where the user confirmed the fix, not every view.
Flesch-Kincaid grade
A readability number from the formula 0.39 * (words / sentences) + 11.8 * (syllables / words) - 15.59, read as the US school grade a reader at that level would be in. About grade 8 suits text meant for the general public.
KB review cycle
The four-stage habit a service desk runs on every ticket to keep its knowledge base alive: find or write an article, use it in the fix, flag any step that is wrong, and improve the article before the ticket closes.
KB template
The fixed set of seven named sections of the knowledge-base article template this track teaches, in order: Title, Environment, Symptoms, Cause, Resolution, Verification, and When to escalate.
knowledge-base article
A short written document in the knowledge base that explains one support task: what the user sees, why it happens and how to fix it, so a technician who has never met the problem can run through it and close the ticket.
Knowledge-Centred Service
The Consortium for Service Innovation's method, KCS, in which support teams reuse, improve and capture knowledge-base articles as part of solving every ticket; its newest practices guide renames it Knowledge-Centered Success.
request catalogue
The published list of self-service items a user can raise or do themselves on the portal, each row named with the user's own words and carrying an owner, a fulfilment path and a target time.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.