From 43c7a1b2621bdf7bf024f296c5d00e990c85e9de Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Tue, 19 May 2026 20:11:37 -0700 Subject: [PATCH] docs(web-search): document xAI Web Search backend (#29052) Follow-up to #29042 (xAI Web Search provider plugin). Adds xAI to the canonical user-facing and developer-facing docs, with the search-only caveat and the LLM-in-a-trench-coat trust model carried over from the class docstring. - user-guide/features/web-search.md - Backends table: new xAI row + extended search-only note - New 'xAI (Grok)' setup section with config knobs and trust-model caution admonition - Single-backend yaml comment now lists 'xai' - Auto-detection table: explicitly note that xAI is NOT auto-detected (XAI_API_KEY is shared with inference/TTS/image-gen so we don't silently take over web for users who only set it for chat) - developer-guide/web-search-provider-plugin.md - Added plugins/web/xai/ to the 'study these next' reference list - reference/environment-variables.md - XAI_API_KEY description now also mentions web search --- .../web-search-provider-plugin.md | 1 + .../docs/reference/environment-variables.md | 2 +- .../docs/user-guide/features/web-search.md | 54 ++++++++++++++++++- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/website/docs/developer-guide/web-search-provider-plugin.md b/website/docs/developer-guide/web-search-provider-plugin.md index c33d88f22d0..37c490d6f7d 100644 --- a/website/docs/developer-guide/web-search-provider-plugin.md +++ b/website/docs/developer-guide/web-search-provider-plugin.md @@ -246,6 +246,7 @@ If your provider wraps a third-party SDK (like DDGS does with the `ddgs` package - **`plugins/web/ddgs/`** — no-key provider that lazy-installs its SDK. Useful pattern for backends that wrap a Python package. - **`plugins/web/firecrawl/`** — full multi-capability provider (search + extract + crawl) with multiple format modes. - **`plugins/web/searxng/`** — self-hosted, URL-configured backend with no auth. +- **`plugins/web/xai/`** — LLM-backed search via Grok's server-side `web_search` tool. Shows how to reuse an existing OAuth/env-var credential surface (`tools/xai_http.py`) without adding new env vars, and how to write a cheap `is_available()` that honors the no-network contract. ## Distribute via pip diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index c7333ebda99..e9403337063 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -82,7 +82,7 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config | `STEPFUN_BASE_URL` | Override StepFun base URL (default: `https://api.stepfun.com/v1`) | | `OLLAMA_API_KEY` | Ollama Cloud API key — managed Ollama catalog without local GPU ([ollama.com/settings/keys](https://ollama.com/settings/keys)) | | `OLLAMA_BASE_URL` | Override Ollama Cloud base URL (default: `https://ollama.com/v1`) | -| `XAI_API_KEY` | xAI (Grok) API key for chat + TTS ([console.x.ai](https://console.x.ai/)) | +| `XAI_API_KEY` | xAI (Grok) API key for chat + TTS + web search ([console.x.ai](https://console.x.ai/)) | | `XAI_BASE_URL` | Override xAI base URL (default: `https://api.x.ai/v1`) | | `MISTRAL_API_KEY` | Mistral API key for Voxtral TTS and Voxtral STT ([console.mistral.ai](https://console.mistral.ai)) | | `AWS_REGION` | AWS region for Bedrock inference (e.g. `us-east-1`, `eu-central-1`). Read by boto3. | diff --git a/website/docs/user-guide/features/web-search.md b/website/docs/user-guide/features/web-search.md index f1da7ef706a..42877025225 100644 --- a/website/docs/user-guide/features/web-search.md +++ b/website/docs/user-guide/features/web-search.md @@ -25,8 +25,9 @@ Both are configured through a single backend selection. Providers are chosen via | **Tavily** | `TAVILY_API_KEY` | ✔ | ✔ | ✔ | 1 000 searches/mo | | **Exa** | `EXA_API_KEY` | ✔ | ✔ | — | 1 000 searches/mo | | **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ | — | Paid | +| **xAI (Grok)** | `XAI_API_KEY` or `hermes auth login xai-oauth` | ✔ | — | — | Paid (SuperGrok or per-token) | -Brave Search and DDGS are **search-only** — pair either with Firecrawl/Tavily/Exa/Parallel when you also need `web_extract`. DDGS uses the [`ddgs` Python package](https://pypi.org/project/ddgs/) under the hood; if it isn't already installed, run `pip install ddgs` (or let Hermes lazy-install it on first use). +Brave Search, DDGS, and xAI are **search-only** — pair any of them with Firecrawl/Tavily/Exa/Parallel when you also need `web_extract`. DDGS uses the [`ddgs` Python package](https://pypi.org/project/ddgs/) under the hood; if it isn't already installed, run `pip install ddgs` (or let Hermes lazy-install it on first use). xAI runs Grok's server-side `web_search` tool on the Responses API — results are LLM-generated rather than index-backed, so titles, descriptions, and URL choice are all model output (see the [trust-model caveat](#xai-grok) below). **Per-capability split:** you can use different providers for search and extract independently — for example SearXNG (free) for search and Firecrawl for extract. See [Per-capability configuration](#per-capability-configuration) below. @@ -273,6 +274,53 @@ Get access at [parallel.ai](https://parallel.ai). --- +### xAI (Grok) {#xai-grok} + +Routes `web_search` through Grok's server-side [web_search tool](https://docs.x.ai/developers/tools/web-search) on the Responses API. Grok runs the actual searching and returns the top results as structured JSON. + +Works with either credential path — no new env vars, no new setup wizard: + +```bash +# ~/.hermes/.env (env-var path) +XAI_API_KEY=sk-xai-your-key-here +``` + +or for SuperGrok subscribers: + +```bash +hermes auth login xai-oauth +``` + +Then select xAI as the search backend: + +```yaml +# ~/.hermes/config.yaml +web: + backend: "xai" +``` + +**Optional knobs:** + +```yaml +web: + backend: "xai" + xai: + model: grok-4.3 # reasoning model required by web_search (default) + allowed_domains: # optional, max 5 — mutex with excluded_domains + - arxiv.org + excluded_domains: # optional, max 5 + - example-spam.com + timeout: 90 # seconds (default) +``` + +**Search-only** — pair with Firecrawl / Tavily / Exa / Parallel if you also need `web_extract`. On 401 the provider performs a single forced OAuth-token refresh and retries (covers mid-window revocation and opaque tokens the proactive expiry check can't decode); env-var credentials skip the retry. + +:::caution Trust model +Unlike index-backed providers (Brave, Tavily, Exa) which return verbatim search-engine results, xAI is an LLM choosing which URLs to surface and writing the titles and descriptions itself. The *content* of the query influences the output, so a maliciously crafted query (e.g. injected via untrusted upstream input the agent picked up) can in principle steer Grok into emitting attacker-chosen URLs. Treat returned URLs the same way you'd treat any model-generated link — validate before fetching, especially if the query came from untrusted input. +::: + +--- + ## Configuration ### Single backend @@ -282,7 +330,7 @@ Set one provider for all web capabilities: ```yaml # ~/.hermes/config.yaml web: - backend: "searxng" # firecrawl | searxng | brave-free | ddgs | tavily | exa | parallel + backend: "searxng" # firecrawl | searxng | brave-free | ddgs | tavily | exa | parallel | xai ``` ### Per-capability configuration @@ -315,6 +363,8 @@ If no backend is explicitly configured, Hermes picks the first available one bas | `EXA_API_KEY` | exa | | `SEARXNG_URL` | searxng | +xAI Web Search is **not** in the auto-detection chain — having `XAI_API_KEY` set (or being signed in via xAI Grok OAuth) does not automatically route web traffic through xAI, since those credentials are also used for inference / TTS / image gen and the user may want a different backend for web. Opt in explicitly with `web.backend: "xai"`. + --- ## Verify your setup