github →

New request

#2664: [bug] Web search/extract broken in WebUI: plugin registry empty despite discovery running

We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.

Issue
bugupstream-changesprint-candidateinvestigation

Summary

Since updating to Hermes Agent v0.14, all web_search and web_extract tool calls from the WebUI return "No web search provider configured." The CLI works correctly with the same config, .env, and SearXNG instance.

Symptom

web_search("test")
→ {"success": false, "error": "No web search provider configured. Run `hermes tools` to set one up."}

The error fires for both web_search (SearXNG) and web_extract (Firecrawl). Config and credentials are correct, and the SearXNG container is reachable (HTTP 200).

Environment

  • Hermes Agent: v0.14.x (git source mounted into WebUI container)
  • WebUI: v0.51.98
  • Config: web.search_backend: searxng, web.extract_backend: firecrawl
  • .env: SEARXNG_URL and FIRECRAWL_API_KEY both set
  • SearXNG container: alive, HTTP 200 from inside WebUI container

What I've confirmed

The registry is empty in the WebUI process

>>> from agent.web_search_registry import _providers, get_active_search_provider
>>> _providers
{}
>>> get_active_search_provider()
None

Plugin discovery does run

model_tools.py calls discover_plugins() at module import time (line 196-200), and run_agent.py imports model_tools at line 104. So plugin discovery is triggered in the WebUI process. It completes without error but only finds 1 plugin:

INFO hermes_cli.plugins: Plugin discovery complete: 1 found, 1 enabled

That single plugin is hermes-lcm, a user plugin installed at ~/.hermes/plugins/hermes-lcm/.

The web provider plugins exist but have no manifests

The bundled plugins directory in the WebUI's venv contains the web provider Python code:

/app/venv/.../site-packages/plugins/web/searxng/{__init__.py, provider.py}
/app/venv/.../site-packages/plugins/web/firecrawl/{__init__.py, provider.py}

Each has a proper register(ctx) hook. However, the plugin scanner requires plugin.yaml manifests to discover plugins, and none exist in the pip-installed package:

$ find /app/venv/.../site-packages/plugins/ -name "plugin.yaml" | wc -l
0

The git source has all 63 manifests

The Hermes Agent git source (mounted at ~/.hermes/hermes-agent/) contains all the manifests:

$ find ~/.hermes/hermes-agent/plugins/ -name "plugin.yaml" | wc -l
63

$ find ~/.hermes/hermes-agent/plugins/web/ -name "plugin.yaml"
.../plugins/web/searxng/plugin.yaml
.../plugins/web/firecrawl/plugin.yaml
.../plugins/web/tavily/plugin.yaml
... (8 total)

Why the CLI works

The CLI runs from the git source, where get_bundled_plugins_dir() resolves to ~/.hermes/hermes-agent/plugins/ - the directory with all 63 manifests. The WebUI runs from the pip-installed venv, where the same function resolves to site-packages/plugins/ - the directory with 0 manifests.

Why hermes-lcm still works

LCM is installed as a user plugin at ~/.hermes/plugins/hermes-lcm/ with its own plugin.yaml. The scanner checks user plugins separately from bundled plugins, so LCM is discovered regardless of the venv manifest issue.

Possible root cause

The pip package appears to strip plugin.yaml files during packaging. The Python source files are included, but the YAML manifests the plugin scanner needs to discover and load them are not. This means any entrypoint using the pip-installed package (rather than the git source) will have an empty plugin registry for all bundled plugins.

The WebUI hits this because it imports from the venv. The CLI avoids it because it runs from the git source where manifests are present.

Tool call path

For reference, the dispatch path in web_tools.py:

backend = _get_search_backend()           # returns "searxng" from config
provider = _wsp_get_provider(backend)      # returns None — registry empty
if provider is None:
    provider = get_active_search_provider()  # also None — registry empty
if provider is None:
    return {"success": False, "error": "No web search provider configured..."}

Related

  • RFC #1925: Make WebUI a thin observability/control client: The WebUI running its own agent in-process means it depends on the pip-installed package having full parity with the git source. Missing manifests are one example of that parity breaking. If the WebUI consumed Hermes as a service rather than importing it as a library, bundled plugin packaging would not be in the critical path.

Workaround

Pinning the git source onto the WebUI's Python path (so it imports from the git source instead of the venv) would likely fix this, but I haven't tested it. No simple env var or config workaround exists - the manifests need to be present for the scanner to find them.

Assessmentadvisory
bug●●● hard75% confidence

Plugin discovery works in CLI but registry remains empty in the WebUI process, suggesting a cross-cutting import/timing or upstream API issue requiring deep investigation.

Likely files
  • agent/web_search_registry.py
  • api/model_tools.py
  • api/run_agent.py
  • api/plugins.py
  • bootstrap.py
Create the request

This opens a fresh agent run and a draft PR for issue #2664.

Cancel