Security and privacy
An assistant inside a business application touches three sensitive things: the data of the user, an API key, and — once it can act — the application itself. Here is exactly what HelpChatAI does about each, so you can decide what to allow.
What leaves the application
When a question is sent to a provider, this is everything that travels:
| What | |
|---|---|
| The question | What the user typed |
| The conversation | The previous messages, up to HistoryMaxMessages |
| The screen | Four fields only: name, label, class and help keyword |
| The documentation | Excerpts of the pages your index matched (GroundingMaxPages, GroundingMaxChars) |
Nothing reads your data. Not the grids, not the fields, not the database. The component never inspects the content of your forms — only the help properties you declared.
If a screen label can contain a customer name or an order number, blank it in OnGetContext:
procedure TMainForm.HelpChatGetContext(Sender: TObject; var AContext: THelpChatContext);
begin
AContext.ScreenLabel := 'Documento'; // not 'Fattura 2026/0142 - Rossi S.p.A.'
end;With stub or docsearch, nothing leaves the machine at all: there is no network call.
The microphone
Dictation only happens if you ask for it, and only while the user keeps the microphone on. Nothing is recorded, nothing is stored, nothing is sent anywhere by the component.
Where the voice goes depends on the engine. hveSystemDictation hands the microphone to the dictation of Windows, the one Win+H starts, which types into the box like a keyboard: the component never sees the audio and never sees the text. hveRecognizer uses the speech recognition of Windows, whose free dictation goes through Microsoft's online service, so the voice does leave the machine — to Microsoft, not to us, and only under a consent the user gives in the Windows settings.
That consent is theirs alone. The component reads whether it was given, explains what is needed and opens the settings page; it never writes that setting, because accepting to send one's voice to Microsoft is not a decision an application takes on someone's behalf. Refuse it and dictation does not start. VoiceEngine := hveNone removes the microphone button altogether.
The API key
On a desktop, a key in a file is recoverable by whoever owns the machine. HelpChatAI does what it can — the key is never in your source, never in what the installer packages, and read from a per-user file outside the installation folder — but the honest statement is: a key deployed to a client machine is a key you have given away.
When that matters, run the engine on a server. The clients then hold an application key, which grants nothing but the right to ask questions and which you can change in a configuration file the day it leaks. Per-user control goes through OnAuthenticate on the server.
Model output is untrusted content
A reply is text produced by a model and rendered inside a browser that sits in your process. It is treated as hostile input:
- Markdown in safe mode: active HTML is escaped, so a reply cannot inject a
<script>or an<iframe>. - URL schemes restricted to
http(s),mailto,ftpand relative paths:javascript:,data:,vbscript:,file:are dropped. Bare URLs written as plain text are turned into links, in text nodes only, never inside code or an existing link. - A Content-Security-Policy on the page: it may talk to its own API and, when there is one, to the loopback host channel — nothing else, no external script, no remote image.
- The browser is confined to the panel origin: any other navigation is cancelled and handed to the system browser, so a link in a reply opens outside the application.
- User text and error messages never go through Markdown at all: they are HTML-encoded.
The local server
The transport that serves the page binds 127.0.0.1 only, on a free port, and every API call must carry a secret generated per process that only the page knows (it receives it in its URL). Another process on the machine cannot drive the assistant without that secret, and nothing is reachable from the network.
The same holds for the loopback host channel used with a remote engine, which additionally restricts CORS to the panel origin — never * — and answers the private-network preflight explicitly.
Actions
An assistant that can act is a different risk from one that answers. The design is deliberately narrow:
- only the actions you registered exist; there is no generic entry point;
- each one has the parameters you declared, and reading them never raises;
- anything that changes data can require an explicit confirmation before it runs;
ActionsEnabled := Falsetakes them all away at runtime — for a read-only mode or a user profile without the right to act.
Keep destructive operations (delete, post, send money) out of the registry, or behind Confirm and a handler that applies your own policy. The model decides what to ask for; your application decides what is allowed.
The conversation on disk
With PersistConversation (the default) the conversation is saved in %APPDATA%\<YourApp>\helpchatai-conversation.json and discarded after ConversationMaxAgeDays. On a shared or kiosk machine, set it to False. On a server, Sessions.Storage = memory keeps nothing after the last session ends.
A checklist before you ship
- [ ] No
helpchatai.jsonwith a key in your installer. - [ ]
OnGetContextblanks anything identifying in the screen label. - [ ] Destructive actions are not registered, or require confirmation.
- [ ]
PersistConversationmatches how the machine is used. - [ ] If the application is installed at customers: the engine is on a server, or you accept that the key lives on their machines.
- [ ] Your users know there is an assistant and what it sends — the same way you would tell them about any other cloud feature.