ByteNoteByteNote

字节笔记本

2026年6月21日

hermes教程-Web 搜索提供者插件

API中转
¥120

构建 Web 搜索提供者插件

Web 搜索提供者插件注册一个后端,用于服务 web_searchweb_extract 以及(可选)深度爬取工具调用。内置提供者——Firecrawl、SearXNG、Tavily、Exa、Parallel、Brave Search(免费层)、xAI 和 DDGS——均作为插件位于 plugins/web/<name>/ 下。您可以通过在旁边放置一个目录来添加新插件或覆盖捆绑的插件。

提示

Web 搜索是 Hermes 支持的几种后端插件之一。其他插件(具有各自的 ABC)包括图像生成提供者插件视频生成提供者插件内存提供者插件上下文引擎插件模型提供者插件。通用工具/钩子/CLI 插件位于构建 Hermes 插件中。

发现机制

Hermes 在三个位置扫描 Web 搜索后端:

  1. 捆绑<repo>/plugins/web/<name>/(自动加载,kind: backend,始终可用)
  2. 用户~/.hermes/plugins/web/<name>/(通过 plugins.enabledhermes plugins enable <name> 选择加入)
  3. Pip — 声明 hermes_agent.plugins 入口点的包

每个插件的 register(ctx) 函数调用 ctx.register_web_search_provider(...)——这将实例放入 agent/web_search_registry.py 的注册表中。每个能力的活动提供者由配置选择:

能力配置键回退到
web_searchweb.search_backendweb.backend
web_extractweb.extract_backendweb.backend
web_extract 内部的深度爬取模式web.extract_backendweb.backend

当两个键都未设置时,Hermes 根据环境中存在的 API 密钥/URL 自动检测后端。hermes tools 引导用户进行选择。

目录结构

text
plugins/web/my-backend/
├── __init__.py     # register() 入口点
├── provider.py     # WebSearchProvider 子类
└── plugin.yaml     # 清单,包含 kind: backend 和 provides_web_providers

brave_free/ddgs/ 是树内最小的参考——brave_free 是一个需要 API 密钥的仅搜索提供者,ddgs 是一个无需密钥的提供者,它惰性安装其 SDK。

WebSearchProvider ABC

子类化 agent.web_search_provider.WebSearchProvider。唯一必需的成员是 nameis_available() 以及您实现的 search() / extract() 中的任何一个。(深度爬取不是单独的方法——它是 extract() 的一种模式。)

python
## plugins/web/my-backend/provider.py
from __future__ import annotations

import os
from typing import Any, Dict, List

from agent.web_search_provider import WebSearchProvider

class MyBackendWebSearchProvider(WebSearchProvider):
    """针对 My Backend HTTP API 的最小化仅搜索提供者。"""

    @property
    def name(self) -> str:
## 用于 web.search_backend / web.extract_backend / web.backend
## 配置键的稳定 ID。小写,无空格;允许连字符。
        return "my-backend"

    @property
    def display_name(self) -> str:
## 在 `hermes tools` 中显示的人类可读标签。默认为 `name`。
        return "My Backend"

    def is_available(self) -> bool:
## 廉价检查——环境变量存在,可选依赖可导入等。
## 不得进行网络调用(每次 `hermes tools` 渲染时运行)。
        return bool(os.getenv("MY_BACKEND_API_KEY", "").strip())

    def supports_search(self) -> bool:
        return True

    def supports_extract(self) -> bool:
        return False

    def search(self, query: str, limit: int = 5) -> Dict[str, Any]:
        import httpx

        api_key = os.environ["MY_BACKEND_API_KEY"]
        try:
            resp = httpx.get(
                "https://api.example.com/search",
                params={"q": query, "count": max(1, min(int(limit), 20))},
                headers={"Authorization": f"Bearer {api_key}"},
                timeout=15,
            )
            resp.raise_for_status()
            data = resp.json()
        except httpx.HTTPError as exc:
            return {"success": False, "error": str(exc)}
## 响应形状是固定的——请参阅下面的“响应形状”。
        return {
            "success": True,
            "data": {
                "web": [
                    {
                        "title": item.get("title", ""),
                        "url": item.get("url", ""),
                        "description": item.get("snippet", ""),
                        "position": idx + 1,
                    }
                    for idx, item in enumerate(data.get("results", []))
                ],
            },
        }
python
## plugins/web/my-backend/__init__.py
from plugins.web.my_backend.provider import MyBackendWebSearchProvider

def register(ctx) -> None:
    """插件入口点——在加载时调用一次。"""
    ctx.register_web_search_provider(MyBackendWebSearchProvider())

plugin.yaml

yaml
name: web-my-backend
version: 1.0.0
description: "My Backend 网络搜索——Bearer 认证 REST API"
author: Your Name
kind: backend
provides_web_providers:
  - my-backend
requires_env:
  - MY_BACKEND_API_KEY
用途
kind: backend将插件路由到后端加载路径
provides_web_providers此插件注册的提供者 name 列表——加载器使用它在 register() 运行之前就在 hermes tools 中宣传该插件
requires_envhermes plugins install 期间交互式凭据提示(有关丰富格式,请参阅构建 Hermes 插件

ABC 参考

完整契约在 agent/web_search_provider.py 中。您可以覆盖的方法:

成员必需默认值用途
name用于 web.*_backend 配置的稳定 ID
display_namenamehermes tools 中显示的标签
is_available()廉价可用性门控——环境变量、可选依赖
supports_search()True用于 web_search 路由的能力标志
supports_extract()False用于 web_extract 路由的能力标志
search(query, limit)条件引发异常supports_search() 返回 True 时必需
extract(urls, **kwargs)条件引发异常supports_extract() 返回 True 时必需

提供者可以从单个类中宣传多种能力——Firecrawl、Tavily、Exa 和 Parallel 都实现了搜索和提取。Brave Search 和 DDGS 仅搜索;SearXNG 仅搜索,并具有记录在案的“将我配对提取提供者”工作流。

响应形状

工具包装器期望一个固定的信封,这样它就不必在后端之间进行转换。

搜索成功:

python
{
    "success": True,
    "data": {
        "web": [
            {"title": str, "url": str, "description": str, "position": int},
            ...
        ],
    },
}

提取成功:

python
{
    "success": True,
    "data": [
        {
            "url": str,
            "title": str,
            "content": str,
            "raw_content": str,
            "metadata": dict,    # 可选
            "error": str,        # 可选,仅在单个 URL 失败时出现
        },
        ...
    ],
}

任一能力,失败时:

python
{"success": False, "error": "人类可读的消息"}

search()extract() 都可以是 async def——调度器通过 inspect.iscoroutinefunction 检测协程函数并相应地等待。对于小型后端,执行阻塞 I/O(HTTP、SDK 调用)的同步实现是可以的;调度器处理线程。

能力标志

Hermes 根据 supports_* 标志将调用路由到正确的提供者。一个常见的多提供者设置:

yaml
## ~/.hermes/config.yaml
web:
  search_backend: "brave-free"     # 仅搜索,快速,免费 2k/月
  extract_backend: "firecrawl"     # 提取 + 爬取,付费配额

web.search_backendweb.extract_backend 未设置时,两者都回退到 web.backend。当该值也未设置时,Hermes 根据环境变量存在性选择第一个支持所请求能力的可用提供者。

如果您的提供者只支持一种能力,请将其他标志保留为默认值(False),注册表将跳过该工具——当用户仅使用 X 进行搜索并要求代理提取时,他们不会看到误导性的“提供者 X 失败”错误。

Hermes 如何将其接入工具

web_searchweb_extract 工具位于 tools/web_tools.py 中。在调用时,它们:

  1. 读取相关配置键(web.search_backend 用于 web_searchweb.extract_backend 用于 web_extract
  2. 向注册表请求具有该 name 的提供者
  3. 检查 is_available() 和匹配的 supports_*() 标志
  4. 分派到 search() / extract()(深度爬取作为 extract() 内部的一种模式运行),如果方法是协程则等待
  5. JSON 序列化响应信封并将其返回给 LLM

错误作为工具结果呈现;LLM 决定如何解释它们。如果没有注册提供者(或者每个可用的提供者都未通过能力门控),工具会返回一个有用的错误,指向 hermes tools

惰性安装可选依赖

如果您的提供者包装了第三方 SDK(如 DDGS 使用 ddgs 包),请不要在模块顶层 import 它。在 is_available()search() 内部使用 tools.lazy_deps.ensure(...)——Hermes 将在首次使用时安装该包,受 security.allow_lazy_installs 门控。有关安全模型,请参阅构建 Hermes 插件 → 惰性安装

参考实现

  • plugins/web/brave_free/ — 小型、需要 API 密钥、仅搜索的 HTTP 提供者。良好的起始模板。
  • plugins/web/ddgs/ — 无需密钥的提供者,惰性安装其 SDK。对于包装 Python 包的后端有用的模式。
  • plugins/web/firecrawl/ — 完整的多能力提供者(搜索 + 提取 + 爬取),具有多种格式模式。
  • plugins/web/searxng/ — 自托管、URL 配置的后端,无需认证。
  • plugins/web/xai/ — 通过 Grok 服务器端 web_search 工具进行 LLM 支持的搜索。展示了如何重用现有的 OAuth/环境变量凭据表面(tools/xai_http.py)而无需添加新的环境变量,以及如何编写一个遵守无网络契约的廉价 is_available()

通过 pip 分发

toml
## pyproject.toml
[project.entry-points."hermes_agent.plugins"]
my-backend-web = "my_backend_web_package"

my_backend_web_package 必须公开一个顶层的 register 函数。有关完整设置,请参阅通用插件指南中的通过 pip 分发

相关页面


分享: