OpenRouter mode (DeepSeek)¶
The product runs fully local. For laptops without a GPU, the same stack can send model and AI-judge calls to DeepSeek V4.1 Flash on OpenRouter, zero-data-retention endpoints only: make demo-up REMOTE=1.
CPU-only Ollama runs qwen3:8b at a few tokens a second. For engineering, make remote-up
starts the stack with compose.remote.yml: the gateway sends generate and judge calls to
upstreams.llm_remote in config/policy.yaml (OpenRouter) instead of upstreams.llm. Put
OPENROUTER_API_KEY=... in .env first; it reaches the gateway container only, and the
gateway refuses to start without it (never a silent fall back to Ollama). make remote-off
returns to the local default, which is what the product ships.
- Data. Prompts and judge content leave the machine, after the pre controls:
piimasks,secretsandprompt_injectionblock, before the upstream call. Every request carries the policy'sextra_body(provider: {zdr: true, data_collection: deny}), which the agent cannot override; OpenRouter answers an error rather than route to an endpoint that retains data, and the gateway turns that into a generic 502upstream_error. Router extensions in the agent's request (models,provider,plugins, ...) are dropped. - Models. The remote upstream serves its own logical ids:
deepseek-v4.1-flash(deepseek/deepseek-v4.1-flash, ~27 zero-data-retention endpoints). Grants, pricing,model_allowlistand audit use that id;model_mapnames the provider model it is sent as.qwen3:8bstays local-only: asking for it in remote mode (or fordeepseek-v4.1-flashin local mode) is a 400model_not_mappedthat names what is served./v1/modelslists what the selected upstream serves, and the demo agent and smoke traffic pick their model from it, somake demoruns in both modes. Judges ask forupstreams.llm_remote.judge_modelwhile remote is selected; remote mode with judges refuses to start without a mapped one. Remote judge verdicts can differ between runs of the same content, because different ZDR endpoints serve different runs, so they are less reproducible than the local judge's. - Visibility.
/healthzreportsllm_upstreamand its host, every LLM audit entry carries"upstream": "remote",acl_llm_upstream_info{upstream}is 1 for the active one, and the gateway logs a warning at startup. - Budgets. Remote calls are charged tokens at
llm_remote.pricingand no GPU time; their deadline stayslimits.upstream_timeout_s.extra_bodyalso caps the endpoint price (provider.max_price) andpricingreserves at that ceiling, so a hold is never too small; the settlement charges the cost OpenRouter reports (usage.cost), never above the ceiling, and the ceiling when no usable figure comes back. - With the demo.
make demo-up REMOTE=1combines both overlays;make remote-off(ormake demo-off) returns to the default.