43 lines
2.0 KiB
Markdown
43 lines
2.0 KiB
Markdown
# SPEC-015 — Web search (Exa)
|
|
|
|
A `web_search` function tool for general "look it up on the internet"
|
|
questions the other tools do not cover: IGDB is games, the Codex is
|
|
Adeptus Mechanicus lore, the news store is the configured feeds, and
|
|
`fetch_url` needs a URL the user already has. Web search fills the gap
|
|
and pairs with `fetch_url` (search → pick a link → read it). Results are
|
|
external text and are sanitized (SAF-03); the Exa key is a host secret,
|
|
never in the repo. Active only when `enable-web-search = true` and a key
|
|
is present.
|
|
|
|
### WEB-01 — web_search is offered as a tool (coverage: test)
|
|
|
|
When `enable-web-search` is true **and** an Exa key is available
|
|
(`exa-api-key` in config, else `EXA_API_KEY` env), the chat call's
|
|
`tools` list includes a `web_search` function (`query` string, optional
|
|
`num_results`). With the flag off or no key it is absent.
|
|
|
|
### WEB-02 — Results are reduced and sanitized (coverage: test)
|
|
|
|
Each Exa result becomes `{title, url, snippet, published}`; `title` and
|
|
`snippet` pass through `sanitize_external_text` (snippet capped at
|
|
`web-snippet-chars`, default 400) so a web page can neither inject an
|
|
`@everyone` nor smuggle control characters into the prompt.
|
|
|
|
### WEB-03 — Result count is bounded (coverage: test)
|
|
|
|
`num_results` is clamped to 1..`MAX_RESULTS` (10) before the request, so
|
|
neither a huge fan-out nor a zero/negative count reaches the API.
|
|
|
|
### WEB-04 — Missing key and API failure are reported, not raised (coverage: test)
|
|
|
|
With no key the tool returns an `{error: ...}` result without a network
|
|
call. A request that raises (network, non-2xx, bad JSON) is logged and
|
|
returns an `{error: ...}` dict — `search` never raises into the loop.
|
|
|
|
### WEB-05 — Searches are metered per user (coverage: test)
|
|
|
|
Each `web_search` increments a per-user daily counter; over
|
|
`web-daily-per-user` (default 30) the tool refuses with an error result
|
|
without calling the API. The budget gate (SAF-04) still applies to the
|
|
surrounding model calls.
|