The documentation index
The index is what makes the assistant answer about your application. It is a single JSON file listing the pages of your manual: their title, a summary, the text to search in, and the URL to link to. Both docsearch and claude use it — the first to find the page, the second to ground its answer in it.
HelpChatAI.Settings.DocIndexFile := TPath.Combine(
TPath.GetDirectoryName(ParamStr(0)), 'help-index.json');
HelpChatAI.Settings.DocBaseUrl := 'https://help.mycompany.com/myapp/';DocBaseUrl is prepended to the relative URLs of the pages, so the same index works for a manual published online and one shipped locally.
Building it from Markdown
If your manual is a folder of Markdown pages — which is what a modern help usually is — the included tool builds the index for you:
HelpIndexBuilder --source=D:\MyApp\Help --out=D:\MyApp\Bin\help-index.json| Option | Meaning |
|---|---|
--source=<folder> | Folder with the Markdown pages (required) |
--out=<file> | Output JSON (default: help-index.json in the source folder) |
--toc=<file> | Table of contents, relative to the source (default: index.md) |
--url-ext=<ext> | Extension of the published pages (default .html; --url-ext= keeps .md) |
--url-prefix=<text> | Prepended to every relative URL (e.g. manual/) |
--max-text=<n> | Characters of text kept per page for scoring |
--summary=<n> | Maximum summary length |
--no-recursive | Top folder only |
What it does with each page: the first heading becomes the title, the first meaningful paragraph the summary, the body (stripped of Markdown) the text, and the path to the page in the table of contents becomes its keywords — so a page nested under "Settings → Mail server" is found by both words even if the page itself never repeats them. Encoding is detected (BOM, UTF-8, ANSI), which matters for manuals written years ago.
Run it in your build so the index never drifts from the manual.
The format
A JSON array of pages (or {"pages": [...]} if you prefer an object):
[
{
"id": "Leads",
"title": "Leads",
"url": "Leads.md",
"summary": "The board where the work happens: four columns, one per status, and a lead moves from left to right as it progresses.",
"keywords": ["prospects", "pipeline"],
"text": "Leads The board where the work happens: four columns, one per status..."
}
]That one is a real entry of CRM Demo\Help\help-index.json, which the sample applications read — build it yourself and compare.
| Field | Required | Used for |
|---|---|---|
title | yes | Shown to the user; weighs ×6 in the ranking |
url | yes | The link in the reply (relative to DocBaseUrl) |
summary | recommended | What docsearch shows; the fallback grounding for claude |
text | recommended | Searched, and its matching passages are handed to the model |
keywords | optional | Aliases and breadcrumb; weighs ×3 |
id | optional | Your own identifier |
You can of course generate the same JSON from whatever your documentation really is: a CMS, a database of help topics, an old CHM you exported.
Making the assistant find the right page
The retriever is deterministic, so you can reason about it:
- The title is what matters most. Write titles the way a user would name the thing ("Setting up and managing e-mail", not "Module MAIL-02").
HelpKeywordshould match a title. That is how a screen is tied to its page: see F1 and the screen context.- Use keywords for synonyms. The word your users say, the word your manual uses, the name of the old menu it used to be under.
- A page about everything is found for nothing. Idf weighting means a term present in every page does not select anything.
Checking what it finds
A console program is the fastest way to try questions against an index without any UI: point Settings.DocIndexFile at the file, set Settings.Provider to docsearch, and ask. The engine from a command line is such a program, complete, in about sixty lines — the engine is RTL only, so it needs no form and no window.
Reading the pages inside the panel
An answer that ends with a link is only half useful if the link throws the user into a browser. When the manual is a folder of Markdown pages, point Settings.DocFolder at it (absolute, or relative to the executable) and keep the index URLs relative — HelpIndexBuilder --url-ext= leaves page.md. From then on a link to a page opens in the panel: in a reply, in a "read more" of docsearch, or inside another page. The ← button goes back to the chat, and so does Esc.
The page is rendered by the same safe Markdown pipeline as the replies, images of the folder are inlined, and a link that starts with DocBaseUrl counts as a page too. Page names are relative paths that must stay inside the folder and end in .md; anything else answers 404.
| What | Where |
|---|---|
Settings.DocFolder | The folder of Markdown pages; empty disables the whole thing |
OpenDocPage('110') | Opens a page from code, so an action can do it for the assistant |
Engine.DocPageFilter | Adjusts the Markdown before rendering (placeholders, variables) |
OnOpenLink(Sender, Url, var Handled) | A link that leaves the panel: handle it yourself, or let the system browser open it |
Nothing is served without the token, and the panel's content policy is unchanged: the pages travel through the same API as everything else.
Without an index
Nothing breaks: docsearch says plainly that no documentation index is available, and claude answers as a competent assistant that does not know your application — which is exactly the reason to build the index.