Skip to content

feat(web): add xAI Web Search provider plugin#29042

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-ef12c6af
May 20, 2026
Merged

feat(web): add xAI Web Search provider plugin#29042
teknium1 merged 1 commit into
mainfrom
hermes/hermes-ef12c6af

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Salvage of #29036 by @Jaaneek onto current main.

Summary

New bundled web-search provider under plugins/web/xai/ — slots alongside Brave/Tavily/Exa/Firecrawl/SearXNG/DDGS. Opt in via web.backend: xai. Reuses existing xAI Grok OAuth / XAI_API_KEY credential plumbing; no new credential paths, no new env vars, no setup-wizard prompts.

Changes

  • plugins/web/xai/{plugin.yaml,__init__.py,provider.py} — new plugin, 560-line provider
  • tools/xai_http.py — adds cheap has_xai_credentials() probe + keyword-only force_refresh arg on resolve_xai_http_credentials() (fully BC)
  • tools/web_tools.py — 11 lines: "xai" added to configured-backend set + _is_backend_available branch
  • tests/tools/test_web_providers_xai.py — 39 tests

Design notes

  • is_available() is a cheap probe (env var OR auth.json read); never invokes the OAuth resolver — honors the ABC contract that it's called on every hermes tools repaint
  • 401-on-OAuth triggers a single force_refresh=True retry; env-var creds skip the retry (can't refresh)
  • Three-tier result parse: JSON block → url_citation annotations → top-level citations
  • HTTP 200 + {error: ...} envelopes surface as failures, not empty-results
  • Class docstring documents the LLM-in-a-trench-coat trust model

Validation

Suite Result
New tests (test_web_providers_xai.py) 39/39
Sibling web-provider suites 128/128
Cross-suite xai_http callers (tts/x_search/video_gen) 30/30

Authorship preserved via cherry-pick. Closes #29036.

Adds a new bundled web search provider plugin backed by xAI's agentic
Web Search tool (server-side `web_search` on the Responses API). Slots
in alongside the existing Firecrawl / Tavily / Exa / Brave / SearXNG /
DDGS providers; opt in via `web.backend: xai` (or auto-selected by the
registry's single-provider shortcut when it's the only available web
provider, matching every other backend's behavior).

Reuses the existing xAI HTTP credential plumbing (`tools/xai_http.py`)
so it works with both `hermes auth login xai-oauth` (SuperGrok OAuth)
and `XAI_API_KEY` — no new credential paths, no new env vars, no new
setup-wizard prompts. The existing `xai_grok` post_setup hook handles
credential collection.

Reference: https://docs.x.ai/developers/tools/web-search

Provider behavior
-----------------
- Sends a structured prompt to Grok with `tools=[{"type": "web_search"}]`
  enabled and `include=["no_inline_citations"]`, then parses results
  from a `{"results": [...]}` JSON block (primary), falling back to
  `url_citation` annotations (secondary) and the top-level `citations`
  list (last-ditch). Annotation fallback falls through to citations
  when no rows are extractable, so future annotation types xAI may
  add don't silently mask real data.
- HTTP 200 + `{"error": {...}}` envelopes (model-overload, refusal)
  are surfaced as failures rather than masked as success-with-empty-
  results.
- HTTP 401 on the OAuth path triggers a single `force_refresh=True`
  retry — closes two gaps the resolver's proactive JWT-exp shortcut
  doesn't cover: opaque (non-JWT) access tokens and mid-window
  revocation. Env-var (`XAI_API_KEY`) credentials never retry; they
  can't be refreshed and an immediate retry would just burn quota.
- `is_available()` is a cheap probe (env var OR auth.json read), never
  invokes the OAuth resolver — required by the ABC contract because
  it runs on every `hermes tools` repaint and at tool-registration time.
- Class docstring documents the LLM-in-a-trench-coat trust model so
  callers piping untrusted input into `web_search` know returned URLs
  are model-generated and should be validated before fetching.

Config (`config.yaml`):

    web:
      backend: xai
      xai:
        model: grok-4.3         # optional, defaults to grok-4.3
        allowed_domains:        # optional, max 5 — mutex with excluded_domains
          - arxiv.org
        excluded_domains:       # optional, max 5
          - example-spam.com
        timeout: 90             # optional, seconds

Files
-----
- plugins/web/xai/plugin.yaml          (new) plugin manifest
- plugins/web/xai/__init__.py          (new) register(ctx) hook
- plugins/web/xai/provider.py          (new) XAIWebSearchProvider impl
- tools/xai_http.py                    (+47) has_xai_credentials()
                                            cheap-probe helper +
                                            keyword-only force_refresh
                                            arg on resolve_xai_http_
                                            credentials() (backwards
                                            compatible; all 9 other
                                            call sites unaffected)
- tools/web_tools.py                   (+11) "xai" added to configured-
                                            backend set + branch in
                                            _is_backend_available()
- tests/tools/test_web_providers_xai.py (new, 39 tests) covers
                                        identity, cheap-probe semantics,
                                        JSON / annotation / citations
                                        parse paths, request payload
                                        shape, error envelopes, OAuth
                                        force-refresh-on-401 retry,
                                        env-var-no-retry guard, 500-not-
                                        retried guard, refresh-returns-
                                        same-token guard, OAuth runtime
                                        resolution, and backend wiring.

Tests
-----
- 39 xai-suite passes
- 79 sibling web-provider tests (brave-free, ddgs, searxng, base) pass
- 119 cross-suite tests for other xai_http callers (transcription,
  x_search, tts) pass — verifies the new keyword-only arg is BC
- scripts/check-windows-footguns.py: clean on all 5 modified files

No edits to run_agent.py, cli.py, gateway/, toolsets, config schema,
plugin core, or auth core.
@teknium1 teknium1 merged commit a0c0312 into main May 20, 2026
16 of 17 checks passed
@teknium1 teknium1 deleted the hermes/hermes-ef12c6af branch May 20, 2026 02:27
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-ef12c6af vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8974 on HEAD, 8963 on base (🆕 +11)

🆕 New issues (6):

Rule Count
unresolved-attribute 2
unresolved-import 2
invalid-argument-type 1
unsupported-operator 1
First entries
tests/tools/test_web_providers_xai.py:514: [unresolved-attribute] unresolved-attribute: Attribute `append` is not defined on `int` in union `list[Unknown] | int`
tests/tools/test_web_providers_xai.py:515: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `list[Unknown] | int`
tests/tools/test_web_providers_xai.py:521: [unsupported-operator] unsupported-operator: Operator `+=` is not supported between objects of type `list[Unknown]` and `Literal[1]`
plugins/web/xai/provider.py:189: [unresolved-attribute] unresolved-attribute: Attribute `strip` is not defined on `None` in union `Any | None | Literal["grok-4.3"]`
tests/tools/test_web_providers_xai.py:614: [unresolved-import] unresolved-import: Cannot resolve imported module `httpx`
plugins/web/xai/provider.py:233: [unresolved-import] unresolved-import: Cannot resolve imported module `httpx`

✅ Fixed issues: none

Unchanged: 4725 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins tool/web Web search and extraction provider/xai xAI (Grok) labels May 20, 2026
teknium1 added a commit that referenced this pull request May 20, 2026
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
Lillard01 pushed a commit to Lillard01/hermes-agent that referenced this pull request May 21, 2026
Follow-up to NousResearch#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
Gpapas pushed a commit to Gpapas/hermes-agent that referenced this pull request May 23, 2026
Follow-up to NousResearch#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
Mucky010 pushed a commit to Mucky010/hermes-agent that referenced this pull request May 24, 2026
Follow-up to NousResearch#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
Bryce-huang pushed a commit to wbkunlun/hermes-agent that referenced this pull request May 29, 2026
Follow-up to NousResearch#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
#AI commit#
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Follow-up to NousResearch#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have provider/xai xAI (Grok) tool/web Web search and extraction type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants