feat(skills): integrate web-search, db-yaml, agent-cost, diataxis-docs, kb-search; retire searxng

This commit is contained in:
Andriy Oblivantsev
2026-08-10 20:50:25 +01:00
parent 390784d406
commit d4a88eead7
8 changed files with 294 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
---
name: web-search
description: >-
Search the public web through the self-hosted SearXNG at search.ops.io
using bin/web/search. Use for German care law, SGB paragraphs, vendor
documentation and any fact that is not in our own repos - and as the second
independent source the detective method requires.
---
# web-search
```bash
bin/web/search "Pflegegrad SGB XI Einstufung"
bin/web/search "Toureffizienz" --site ticket.detective.de
bin/web/search "sqlite-vec" --category it -n 3 --json | jq -r '.results[].url'
bin/web/search "Pflegereform" --lang de --fresh year
```
## Web or knowledge base
`bin/kb/search` holds our own facts: product docs, detective business logic, the
lexicon. Go there first. Reach for `bin/web/search` when the answer is outside
our repos: legislation, vendor documentation, upstream library behaviour.
Keep the two apart. A finding is stronger when the reader can see that one
source was ours and one was not.
## PII: this query leaves the host
The search goes to external engines. Never put a client or staff identifier in
it. The tool refuses long digit runs, `Personalnummer`, `KV-Nr`, dates of birth
and street-with-number, and exits 2. Rephrase rather than reaching for `--force`.
## Read the status, not just the results
The instance answers HTTP 200 with an empty list when it throttles, so an empty
answer is ambiguous by construction. The tool resolves that for you:
| status | exit | meaning |
|--------|------|---------|
| `ok` | 0 | engines answered |
| `throttled` | 3 | nobody answered; say nothing about what exists |
Never turn a `throttled` result into "there is no information about X".
## Etiquette
Calls are serialised host-wide and kept ten seconds apart, and answers are
cached for seven days. Do not loop over queries, and do not use `--refresh`
unless the cached answer is genuinely stale: a burst suspends the engines for
several minutes for everyone.
@@ -0,0 +1,67 @@
---
type: howto
status: current
---
# Tuning the SearXNG instance
The client works around a fragile instance. These changes fix the cause, and
they need shell access to the host behind `search.ops.io`
(`90.169.228.16` / `ops.mywire.org`), which is a different machine from
the one the agents run on.
## Why it is needed
Measured on 2026-08-10 from this host:
- The default engine set for the `general` category is only `duckduckgo`,
`brave` and `startpage`. `brave` and `startpage` sit in
`Suspended: too many requests` or `Suspended: CAPTCHA` almost permanently, so
in practice a single engine carries every query.
- About 25 probe requests over a few minutes pushed `duckduckgo` into `CAPTCHA`
as well. The instance then answered HTTP 200 with `results: []` and an empty
`unresponsive_engines` - indistinguishable from "nothing found" without the
client-side handling we added.
- Recovery took roughly six minutes.
## Changes
1. **Allow our egress IP through the limiter.** In `limiter.toml`:
```toml
[botdetection.ip_lists]
pass_ip = ["77.7.46.234"]
```
2. **Shorten the suspensions.** In `settings.yml` the defaults are 24 hours for
a CAPTCHA and one hour for too-many-requests, which is far longer than the
condition lasts:
```yaml
search:
suspended_times:
SearxEngineCaptcha: 300
SearxEngineTooManyRequests: 120
SearxEngineAccessDenied: 300
```
3. **Give `general` more than one working engine.** `google` and `wikipedia`
report `enabled: true` in `/config` yet never appear in a `general` response,
so they are not in the default set. Put them in it; one live engine per
category is a single point of failure.
4. **Keep the JSON API on.** `formats: [html, json]` must stay, otherwise every
client here breaks.
## Verifying
Ten requests in a row used to suspend the instance for minutes. After the
change they should all answer:
```bash
for i in $(seq 10); do
bin/web/search "test $i" -n 1 --refresh --json | jq -r .status
done
```
Ten lines of `ok` means it is fixed.