Skip to content

Network traffic ​

What the router contacts, when, and how to turn it off. The router has no telemetry, crash reporting or analytics, and it turns off the telemetry of the ONNX Runtime library it uses for in-process embeddings (below). Every outbound connection is one of the destinations below, and most of them only exist because you configured them.

Destinations ​

WhatDestinationWhenHow to turn it off
ConnectorsThe BaseAddress of each HTTP connector (api.anthropic.com, api.openai.com, a local model server, …)A request is routed to one of its models, the dashboard checks or discovers models, or doctor runsDisable or remove the connector, or its models
EmbeddingsEmbeddings:Endpoint when the provider is OpenAICompatibleEvery classified prompt, and route warm-upUse Onnx, or a server on this machine
ONNX model downloadhuggingface.co, which redirects the model file to its CDN (*.hf.co; the host is regional, e.g. us.aws.cdn.hf.co or cas-bridge.xethub.hf.co)Once, on the first start with Embeddings:Provider: Onnx and no model in models/{name}Copy a models/{name} directory into the configuration directory (or set ModelPath); the download is then skipped. The files are pinned to a revision and checked by SHA-256
The answer judgeOne of your connectors (Middleware:Judge:Model)A sampled share of cheap answers, when Judge:Enabled is on (off by default)Leave Judge:Enabled off
WebhooksEach Notifications:Webhooks URLA notice appears or clears, and the weekly digestRemove the webhook
Subscription CLIs (claude, codex, copilot) and the Copilot SDK connectorTheir vendor's API, from the vendor's own processA request is routed to one of their models, or doctor runsDisable the connector. The router starts Claude Code with DISABLE_AUTOUPDATER=1 and CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 and Copilot with --no-auto-update, so a run makes no update, telemetry or error-reporting requests. Codex is started with -c check_for_update_on_startup=false -c analytics.enabled=false -c otel.metrics_exporter="none" (and --ignore-user-config), so it checks for no update and sends OpenAI no analytics or metrics
Desktop app updatesapi.github.com, github.com and the release download hosts it redirects to (release-assets.githubusercontent.com, objects.githubusercontent.com)A minute after the app starts, then every 12 hours, when installed with the installerUntick Check for updates automatically in the tray menu; for a whole machine, Updates:Mode Off or an internal feed in the machine policy
initlocalhost:1234 (LM Studio), localhost:11434 (Ollama)When you run semantic-router initNothing leaves this machine

Nothing else is contacted:

  • The dashboard loads its scripts, styles and fonts from the router itself and sends Content-Security-Policy: default-src 'self'; …, so the browser refuses requests to any other host. The link to the project on GitHub is only followed when you click it.
  • The desktop app shows the dashboard from the router it runs, and reads the weekly digest from it for the tray.
  • Building from source sends no Avalonia build telemetry: Directory.Build.targets replaces its telemetry target. The .NET SDK has its own; set DOTNET_CLI_TELEMETRY_OPTOUT=1 to turn it off (see Contributing).

ONNX Runtime telemetry ​

The in-process embeddings (Embeddings:Provider: Onnx, which init picks when it finds no embedding server) run on Microsoft's ONNX Runtime. Its Linux and macOS builds send usage data to mobile.events.data.microsoft.com about ten seconds after a model is loaded, and keep a device id and an event queue in ~/.cache/Microsoft/DeveloperTools/.onnxruntime/, unless the environment variable ORT_DISABLE_TELEMETRY is 1 when ONNX Runtime loads. Its Windows build writes its events to Event Tracing for Windows (ETW) on the machine instead.

The router turns this off:

  • Every way it runs (the tool, the desktop app, a service, the container): before it first loads ONNX Runtime, it sets ORT_DISABLE_TELEMETRY=1 in the process's own environment, where ONNX Runtime reads it (setenv on Linux and macOS). On every platform it also turns off ONNX Runtime's telemetry events, which covers the Windows ETW events. Your own value is kept when you set ORT_DISABLE_TELEMETRY before starting the router.
  • The container image and the systemd and launchd services that semantic-router service install writes also set ORT_DISABLE_TELEMETRY=1 in the environment they start the router with.
  • Your own app with the SemanticRouter.Embeddings.Onnx package: AddOnnxEmbeddings and UseOnnxEmbeddings set it. If your app uses ONNX Runtime itself before that, call OnnxRuntimeEnvironment.DisableTelemetry() first, or set the variable before the process starts. Environment.SetEnvironmentVariable alone does not work on Linux and macOS: it changes only .NET's copy of the environment, which ONNX Runtime does not read.

semantic-router doctor says whether it is off, on an egress line, when the embeddings are Onnx.

Proxies and certificates ​

HTTP connectors, embeddings, webhooks and the ONNX download use .NET's HttpClient. It honours HTTPS_PROXY, HTTP_PROXY and NO_PROXY (and the system proxy on Windows and macOS), and trusts the operating system's certificate store.

A corporate root certificate. A proxy that inspects TLS signs every site with its own root. When that root is not in the operating system's store (common in containers), point SemanticRouter:Network:CaBundle at a PEM file with it:

json
{ "SemanticRouter": { "Network": { "CaBundle": "/etc/semantic-router/corporate-root.pem" } } }
  • The certificates in the file are trusted in addition to the system store, for the router's own connections only: connectors, the embeddings endpoint, webhooks and the ONNX download. A certificate must still match the host name and chain to a trusted root; nothing turns validation off.
  • It is a host setting, read at start-up: put it in appsettings.json in the configuration directory, the environment (SemanticRouter__Network__CaBundle) or the command line (--SemanticRouter:Network:CaBundle=…). A relative path is resolved against the configuration directory.
  • A file that is missing or holds no certificate stops the router at start-up, and doctor names it. doctor also prints how many certificates it added.
  • The desktop app's updater does not use it; it trusts the system store.

The container image is Ubuntu chiseled, with no shell or package manager, so update-ca-certificates cannot run in it. Mount the PEM file and set the option:

bash
docker run -v ./corporate-root.pem:/etc/semantic-router/corporate-root.pem:ro \
  -e SemanticRouter__Network__CaBundle=/etc/semantic-router/corporate-root.pem … semantic-router

On Linux, .NET also reads SSL_CERT_FILE (a bundle) and SSL_CERT_DIR, but these replace the system store instead of adding to it: a file with only the corporate root then fails every site the proxy does not inspect. Use CaBundle, or give SSL_CERT_FILE a file with both the system's roots and yours.

The CLIs are separate programs: CaBundle does not reach them. They inherit the router's environment (minus the variables the preset removes), so the same proxy variables reach them, and so do their own certificate settings: NODE_EXTRA_CA_CERTS for Claude Code and the Copilot CLI (Node.js programs; it adds to their built-in roots) and CODEX_CA_CERTIFICATE for Codex. Set them in the router's environment, or per connector in EnvironmentVariables, e.g. "EnvironmentVariables": { "NODE_EXTRA_CA_CERTS": "/etc/semantic-router/corporate-root.pem" }.

Offline mode ​

For an air-gapped or locked-down network, SemanticRouter:Network:Offline makes sure nothing leaves except the model traffic you allow:

json
{ "SemanticRouter": { "Network": { "Offline": true, "AllowedHosts": ["llm-gateway.corp.example"] } } }
  • Connectors, the embeddings endpoint and webhooks reach only this machine (loopback) and AllowedHosts (host names, *.domain or IP addresses, each with an optional :port). Models on any other connector are turned off at start-up and listed with the warnings on the dashboard; turning one back on, on the dashboard or through the admin API, is refused. Remote embeddings fall back to the in-process hashing provider; a webhook elsewhere is not used.
  • CLI and Copilot connectors are off. They always reach their vendor over the internet, whatever the router does.
  • Prices are not looked up (the dashboard's Look up prices, and the prices Discover models fills in from OpenRouter's list), unless openrouter.ai is in AllowedHosts.
  • ONNX Runtime's telemetry is off, as it is outside offline mode (see above).
  • The ONNX embedding model is never downloaded. If it is not on disk, classification fails with a message naming the file, where to put it and its SHA-256: download it on another machine (semantic-router doctor prints the URLs' host and the folder) or set Embeddings:ModelPath to a folder with model.onnx and vocab.txt.
  • semantic-router doctor shows what is still contacted, and what is never contacted and why.

It is a host setting, like CaBundle: appsettings.json in the configuration directory, the environment (SemanticRouter__Network__Offline=true) or the command line. An administrator can force it for the whole machine with "Offline": true in the machine-wide policy; then the policy's AllowedEndpoints are the hosts it allows, the user's AllowedHosts cannot add more, and the desktop app does not update. The user's own Network:Offline does not change the desktop app's updates: untick Check for updates automatically in its tray menu.

Allowing it through a firewall ​

For an egress allowlist, list:

  1. the hosts of the connectors you enabled;
  2. huggingface.co and *.hf.co (its CDN, which serves the model file through a redirect) for the first start with ONNX embeddings, or pre-seed models/ and leave them out;
  3. your webhook hosts;
  4. for subscription CLIs, the hosts their vendors document;
  5. for desktop updates, api.github.com, github.com, release-assets.githubusercontent.com and objects.githubusercontent.com;
  6. for the dashboard's price lookup, openrouter.ai (optional: without it, prices are entered by hand).

semantic-router doctor prints this list for the current configuration, one egress line per destination:

[ OK ] egress: connector lmstudio: localhost:1234 (this machine).
[ OK ] egress: connector openai: api.openai.com.
[ OK ] egress: connector claude: CLI: claude, which contacts Anthropic.
[ OK ] egress: embeddings: huggingface.co and its CDN (*.hf.co), once, to download ONNX model all-MiniLM-L6-v2 into /data/models/all-MiniLM-L6-v2 (copy it there to skip the download).
[ OK ] egress: ONNX Runtime telemetry: off (ORT_DISABLE_TELEMETRY=1, set before ONNX Runtime loads): mobile.events.data.microsoft.com is never contacted and no device id is written.
[ OK ] egress: webhook ops: hooks.slack.com.
[ OK ] egress: price list: openrouter.ai, only when the dashboard looks up cloud models' prices (Look up prices, Discover models); nothing but the request for the list is sent.
[ OK ] egress: desktop app updates: api.github.com, github.com, release-assets.githubusercontent.com and objects.githubusercontent.com (only the installed desktop app; untick Check for updates automatically in its tray menu to turn this off).

Connectors and webhooks show their host and port only: a webhook URL usually carries its token, so its path and query are never printed. The embeddings line names the download host only while the model is not in the models directory yet. Then doctor checks each enabled connector and the embeddings, so it fails on any host the allowlist is missing.

Released under the MIT License.