Two roads to local
There are two ways to reach a local model, and they are not equivalent for the sovereignty readout.
The native local provider, lockable with a single setting, carrying the zero-egress label by construction.
The OpenAI-compatible plug pointed at your own server - the bytes stay with you if your address really is yours, which the engine cannot verify from an arbitrary address: the label therefore stays prudent, unless you declare it yourself.
Both are documented below.
Ollama and the single setting
Models first, on your Ollama server:
The server address, shared by chat and search, is declared in your deployment’s .env. Mind the point that makes most first attempts fail: your Kastel runs in a container, so this address is the one the container sees, not the one your browser sees. If Ollama runs as a service of the stack, use its service name; if it runs elsewhere, use an address reachable from the container.
Then the lock, one line in kastel.config.yaml:
That is the whole setting. max implies local chat and local search: there is nothing else to write. And it is a lock, not a preference: combining max with the BYOK plug, for chat as for search, is a configuration error refused at load. One reservation to know rather than discover: that refusal targets the BYOK plug; if you explicitly name a cloud provider from another family in your configuration, loading does not stop you today. On a sovereign profile, check that your chat provider really is local.
Finally, build the index on the local model:
vLLM or LM Studio
These servers expose an OpenAI-compatible API: the BYOK plug connects to them like to any address, pointed at your own machine:
The key must be non-empty even when your server checks none: set a placeholder. For search, keep the local Ollama model - nothing forces chat and search onto the same server.
On this road, sovereignty_profile: max is refused: the engine cannot verify that an arbitrary address is truly local, so it will not stamp the zero-egress label on it. It is the same variable that reaches a remote provider: on this road, you are the one who knows where your address points, the engine does not infer it. If you want the sovereignty readout to reflect your reality, declare it yourself in the configuration, under inference.provider_postures: you assert it, on the record, rather than the engine guessing.
The zero-egress guarantee, in two layers
Telemetry is opt-in and off by default: under the default configuration, no network client is even constructed. Zero outbound bytes to our servers, verified by dedicated tests, not declared.
With a local chat and a local search, model calls go to your local server. What a test proves, stated precisely: a real, full indexation runs under the max profile, and the test asserts that not a single request left the machine. That is the search path; the chat path rides the same local plug, without an equivalent egress test.
One architect’s honesty to close: “local” is a property of where your addresses point. The guarantee holds as long as KASTEL_LOCAL_BASE_URL names infrastructure that is really yours.
Telemetry deserves its own sentence: off by default, and if you ever turn it on, it carries only anonymised engineering signals with a documented schema - never your content. On a fully local profile, leave it off: that is the default.
What works, what degrades
Running local is a real capability, not a footnote - but it has a price, stated plainly:
Complete. No model call in the direct read path; the rest is deterministic.
bge-m3)Strong. A very good multilingual model: the least compromised part of the local path.
Degrades. It tracks the local chat model you run, weaker than a large hosted model.
Said plainly: the local path is tested for plumbing and for zero egress, not benchmarked to parity with a large hosted model. A company that cannot send data to any external API gets a real, complete system, cut off from the world for inference. A company chasing the best synthesis without that constraint is better served by a BYOK key to a large model - where you decide what each AI is allowed to see.