Several surfaces let readers and authors search the Knowledge Base. They all hit the same backend query and apply the same MySQL FULLTEXT ranking — only the UI differs.
The search entry points
Public reader — the search bar on the hub (/) and on every folder page (/f/). Results appear as you type; each hit opens /a/.
Chat-widget Help tab — the search field at the right of the widget's top bar (placeholder Search the Knowledge Base...). Hits open inside the widget without leaving the chat. See The chat-widget Help tab.
The Editor's link dialog — the KB article tab of the Insert link dialog searches the same way so you can link to an article by title. See The Editor.
Agent / API — GET /api/kb/search?q= returns a JSON array of { id, slug, title }, sorted by relevance.
All of them end up in the same searchPublished() helper, which returns at most 50 published articles ranked by a natural-language MATCH … AGAINST score.
What's indexed
The search index covers three columns of kb_article, and all three contribute to the score:
title — the article's headline. A query that matches the title scores higher than the same query matching only the body.
body_html — the rendered article body, after sanitisation. Tags themselves don't match — is invisible to the index — but the text inside them is.
keywords — the comma-separated tags set in the editor's Keywords field. Tagging an article with the label of an app screen (for example "HR Settings" or "Move Orders") makes it rank for that query even if the words never appear in the body. This is also what powers the Suggested for this page block in the chat-widget.
What's not indexed by search
Drafts and archived articles. Only status = 'PUBLISHED' rows are searchable. See Article statuses field definitions.
Folder names. The folder tree is browsed, not searched.
Image alt text inside
attributes. The FULLTEXT parser indexes word tokens between markup, not attribute values.
How natural-language ranking works
MySQL's FULLTEXT in natural-language mode ignores common stop-words (the, is, of, …), splits on word boundaries, and scores each row by how many query terms appear, weighted by inverse document frequency (rare terms count more). Two practical implications:
Single-word queries find the most general match. Searching dashboard returns every article that mentions the word — usually the article literally titled "The Dashboard" comes first because the term is in its title.
Multi-word queries narrow. dashboard attendance ranks articles that contain both terms above articles that have only one.
Very short words may be ignored entirely. The exact minimum token length and stop-word list are MySQL server settings, not part of the Knowledge Base code — if a two-letter query returns nothing, that is why.
Tips for getting good search results
Search for nouns, not verbs. "clock in" finds the right article; "how do I clock in" finds the same article plus every article that uses the word "how".
Use distinctive words. A query like "setup" or "manage" matches almost everything. "folder rename" or "dead letter" are far more selective.
Quotes are not phrase-matching. Natural-language mode treats quotes as ordinary characters.
Try synonyms. The index doesn't expand to synonyms. "login" and "sign-in" each find their own subset.
If you are the author, add the words readers actually type to the Keywords field — they are indexed.
Searching from the agent / a script
curl -s -H 'Authorization: Bearer ' 'https://mydoc24.org/api/kb/search?q=dashboard%20attendance' | jq
Returns:
[ { "id": 2, "slug": "the-dashboard", "title": "The Dashboard" }, { "id": 4, "slug": "attendance-status-field-definitions", "title": "Attendance status field definitions" }, { "id": 3, "slug": "clock-in-and-out-remotely", "title": "Clock in and out remotely" } ]
Search is a read endpoint, but it is not unconditionally open. The request must carry one of:
A signed-in session or a Bearer token (a Keycloak JWT or a personal access token) whose principal has the kb:read:pages permission.
The shared guest key in an X-Kb-Guest-Key header — this is what mywork's server-side proxy attaches for the chat-widget.
Nothing, only when the deployment has public-read mode switched on in its settings. Without it, anonymous requests get 401.
The response carries Access-Control-Allow-Origin: *, so a browser on another origin can call it once it has credentials.
Use search from a script when you want to dedupe before importing — search for an existing slug or title before calling the import endpoint, so you upsert rather than create duplicates.
Search vs related articles
Different jobs:
Search — initiated by the user with an explicit query. Returns published articles whose title, body, or keywords match the query.
Related — initiated by the system, automatically per article. Returns other published articles in the same folder cluster whose title and body match the current article's keywords and headings. Related deliberately matches title and body only — it uses the current article's keywords as the query, not as a target.
The two share infrastructure (FULLTEXT, MATCH … AGAINST) but differ in who supplies the query. Good keywords therefore help twice: they make the article findable by search, and they make it a better source for its own Related panel — see The Editor.
Related
The Knowledge Base — the three reader surfaces.
The chat-widget Help tab — the widget search.
The Editor — where keywords are set.
Article statuses field definitions — visibility rules that affect search.