# Operating it ## Logs **Every component writes its own file into [`../logs/`](../logs/README.md)** — one place to look rather than working out which compose invocation you wanted: ```sh tail -f logs/api.log # tool calls and errors tail -f logs/egress.access.log # every outbound request, with allow/deny tail -f logs/searxng.log # which search engines are refusing ``` Nothing is hidden from Docker by this — it all still goes to stdout, so `docker compose logs -f api` works exactly as before. `logs/egress.access.log` is the audit trail of everything the assistant fetched and on whose behalf. `TCP_DENIED/403` lines are the guard working, not a fault. The VM daemon is the exception: it is a systemd service rather than part of this stack, so it logs to the journal — `sudo journalctl -u owuivmd -f`. For a VM session, the logs to read are the session transcripts — see [vm-agent/troubleshooting.md](vm-agent/troubleshooting.md). ## Rate limits `dns_lookup`, `inspect_tls`, `http_headers` and `lookup_ip_or_asn` each cost one unit of a per-user hourly budget: `OWUITOOLS_PROBE_RATE_PER_HOUR`, default 30, keyed on the `X-OpenWebUI-User-Id` header Open WebUI forwards. Set it to `0` to disable the limiter. squid is what makes these tools *safe*; the budget only keeps them polite. Bounding how much scanning one account can drive is the point, not preventing abuse — the private-range block does that. ## Caching is load-bearing It is not an optimisation. Stack Exchange allows 300 calls/day/IP without a key and GitHub 60/hour, and those budgets are shared by **every user of the assistant at once**. Without the cache, one enthusiastic conversation exhausts the day for everyone. Clear it after changing a tool that shapes its output: ```sh docker exec owuitools-valkey valkey-cli --scan --pattern 'owuitools:*' | \ xargs -r docker exec -i owuitools-valkey valkey-cli del ``` If valkey is down the tools still work — the cache fails open, with a warning in the log. ## Restarting things ```sh docker compose restart api # after editing configs/tools.toml docker compose restart vmagent # after editing anything in configs/agent/ docker compose up -d --build # after changing code ``` **Restarting `netguard` or `vmguard` strands the containers that share their network namespace.** `api` and `searxng` live in netguard's; `vmagent` lives in vmguard's. Docker does not re-attach them, so they keep running, keep passing their own healthchecks — which are loopback calls — and have no route to anything at all. ```sh docker compose up -d --force-recreate netguard api searxng docker compose up -d --force-recreate vmguard vmagent ``` ## After changing the tool list `docker compose restart api`, **then re-save the connection in Open WebUI.** It caches the spec from when the connection was saved, so without the second step you keep the old list. ## Known constraints Two of these are about one machine's egress IP and may simply not be true for yours — they are recorded because the reasoning behind a configuration choice is worth more than the choice. - **arXiv's API rate-limits some datacentre IPs** to a hard 429, verified through three separate paths, so it is the address rather than the request. `search_papers` uses OpenAlex, which indexes arXiv anyway and allows 100k requests/day keyless. - **Some search engines serve datacentre IPs a CAPTCHA.** The engine list in `configs/services/searxng.settings.yml` reflects what was observed from one address; if results are thin, that list is the first thing to change. General searches deliberately fan out across several engines so no single one is a point of failure. - **No keyless datasheet API exists.** Octopart, Nexar, DigiKey and Mouser all require credentials. `find_datasheet` tries manufacturer URL patterns first, then a PDF-scoped search. - **PyMuPDF is deliberately not used**, despite being faster. It is AGPL-3.0, and section 13's network clause is a live concern for a tool server other people reach over a network. `pypdf` (BSD) and `pdfminer.six` (MIT) cover it. - **Scanned datasheets** — older parts, mostly — have no text layer and cannot be read without OCR. `fetch_page` says so rather than returning garbage. ## Troubleshooting | Symptom | Cause | |---|---| | "Connection failed" when adding the server | Added under **personal** Settings → Integrations rather than **Admin Panel** → Settings → Integrations. A personal tool server is fetched by your browser, which cannot resolve `owuitools-gw`. | | The model never calls tools | System prompt not pasted, connection not enabled on the model, or Function Calling set to Legacy instead of Default. | | Tools vanish after a rebuild | The spec is cached — re-save the connection. | | The model answers from memory | `num_ctx` still at Ollama's 4096 default, silently truncating the tool definitions out of the prompt. | | `FAILED: ... refused by the egress proxy` | Working as intended: a private address was requested. Check `docker compose logs egress`. | | Thin search results | Rate-limited or blocked engines — `docker compose logs searxng`. `web_search` also reports them to the model. | | `wikipedia_lookup` returns 403 | `OWUITOOLS_CONTACT` is unset. See [setup/contact.md](setup/contact.md). | | Everything is "Up" and nothing is reachable | A namespace owner was recreated without its dependents — see above. |