前言¶
在 DeepSeek Harness(DSH)里做联网智能体时,web_search 和 web_fetch 往往要对接 Tavily、Exa、Firecrawl 等不同厂商:各家 API 形状、密钥管理和降级策略都不一致,换一家后端就要改配置或改代码。社区插件 dsh-web-tool-provider(维护者 nhhc-lxr,分类:联网工具)在 Harness 的 ctx.web 契约与三家厂商之间做归一化中间层:搜索和抓取可以分别选后端,密钥走设置页与凭据库,必要时还能在无密钥或厂商失败时降级到本地 HTTP 抓取。
这是什么¶
dsh-web-tool-provider 是 DeepSeek Harness 的 web_search / web_fetch 与 Tavily / Exa / Firecrawl 之间的归一化中间层。Harness 侧只面对统一的 ctx.web 契约;具体请求参数转换、输出形状对齐、错误码映射由本插件完成。
web_search ─┐ ┌─ tavily
├─ ctx.web 统一契约 ───────┤
web_fetch ─┘ (本插件负责转换) └─ exa / firecrawl
仓库:https://github.com/nhhc-lxr/dsh-web-tool-provider
目录页:https://www.skillhub.cn/plugins/nhhc-lxr/dsh-web-tool-provider
许可证:MIT(见仓库 README)。
核心功能¶
输入与输出归一¶
- 输入归一:通用层只暴露域名白名单 / 黑名单;每次搜索固定 5 条结果;深度、主题、格式、地区等厂商参数由插件内部默认值决定,设置页不逐项暴露。
- 输出归一:统一的
source结构、统一的日期格式(publishedAt为YYYY-MM-DD)、统一的错误码;厂商侧的author、warnings、failed_results等折进同一套字段。 - 不向厂商索要「现成答案」:Tavily 的
include_answer与 Exa 的contents.highlights均关闭;content字段只承载降级说明,正文一律通过web_fetch获取。
输出契约(TypeScript 形状,见 README):
SearchResult = { content?: string; sources: { url; title?; snippet?; publishedAt? }[]; truncated: boolean }
FetchResult = { url: string; statusCode: number; body: { kind: 'text' | 'html'; content: string }; truncated: boolean }
snippet 单行且不超过 400 字;Exa 在不请求 contents 时只有链接、标题和日期,没有 snippet。
设置页:后端可独立切换¶
路径:Settings → Plugins → 网页工具后端。一页三块:web_search 与 web_fetch 各有一个后端下拉(可分别选 Tavily / Exa / Firecrawl),以及三家 API 密钥区。
两个下拉改动即存,没有单独的保存按钮。密钥需显式保存(避免输一半写入凭据库):已配置的行隐藏输入框,点铅笔才展开;输入框左侧会显示剩余额度(直连厂商接口查询,不经 ctx.web)。Exa 无余额接口,页面显示「无额度接口」。
密钥解析顺序:插件配置里的字面量 → 凭据库 → 环境变量(TAVILY_API_KEY / EXA_API_KEY / FIRECRAWL_API_KEY),每次调用重新解析;字面量密钥不会写入状态文件。
可选 YAML 与状态文件¶
界面主要改后端与通用选项;更细的默认值可从 profile 的 cordis.patch.yml 读取,包括 search / fetch 的 backend、域名列表、fallbackToHttp,以及 providers.tavily / providers.exa / providers.firecrawl 下的 baseURL、timeoutMs、maxChars 与各厂商专有字段等(完整字段表见 GitHub README)。
后端与通用选项还保存在插件自管状态文件 <profile>/.web-tool-provider/state.json(回退 $DSH_HOME、~/.dsh);状态文件优先于 Config。
运行行为要点¶
web_search多 query = 多次厂商调用(工具层并发后合并)。- 抓取结果一律标为
text(三家返回 markdown/文本)。 - 抓取降级:厂商报错、额度、无密钥、空正文、超时等 → 可本地 HTTP 抓取并附带 notice;目标页 4xx 不降级;abort 不降级。本地抓取仅有协议白名单、内网/回环拦截、重定向校验与字节上限,没有官方
dsh-web-fetch-http的 DNS 公网校验与连接钉扎;需要那层保护时可关闭fallbackToHttp。 - 搜索不降级:选中后端未配密钥则报
WEB_PROVIDER_CREDENTIAL_MISSING。
各后端默认请求参数(可在 YAML 覆盖)见 README 表格,例如 Tavily 搜索 max_results=5,Firecrawl 抓取 /v2/scrape(markdown、onlyMainContent、48h 缓存)等。
安装与启用¶
在已配置 web profile 的 DSH 环境中,使用 README 给出的命令安装:
dsh plugin --profile web add github:nhhc-lxr/dsh-web-tool-provider
安装后打开 Settings → Plugins → 网页工具后端,为将要使用的厂商配置 API 密钥,并按需分别选择 web_search 与 web_fetch 的后端。
插件以当前 DSH 进程权限运行;安装前请自行审阅仓库源码与 MIT 许可证。改插件代码后需重启一次 Harness 才会加载新的 host 实现;设置页刷新即可。
典型用法¶
本插件不新增独立 CLI,而是接管 Harness 已有的 web_search 与 web_fetch 工具:在 Agent 或工作流里照常调用这两项能力即可,实际请求会路由到你设置页所选的后端。
典型流程:
- 用上述命令把插件装进
webprofile。 - 在设置页为 Tavily / Exa / Firecrawl 配置密钥(或依赖环境变量)。
- 将
web_search指向搜索后端(如 Tavily),web_fetch指向抓取后端(如 Firecrawl);需要纯厂商链路时可关闭 YAML 或状态中的fallbackToHttp。 - 在 Harness 对话或自动化中触发联网搜索与页面抓取;多关键词搜索会对应多次厂商调用并合并结果。
错误码包括 WEB_PROVIDER_UNAUTHORIZED、WEB_PROVIDER_QUOTA_EXCEEDED、WEB_PROVIDER_CREDENTIAL_MISSING、WEB_INVALID_URL、WEB_BLOCKED_URL 等,便于在上层做重试或提示(完整列表见 README)。
适用场景与注意¶
适合:希望在 DSH 里用同一套 web_search / web_fetch 契约,按任务或成本在 Tavily、Exa、Firecrawl 之间切换;或搜索与抓取想拆到不同厂商的用户。
注意:
- 插件依赖 Node
^22.19.0 || >=24.0.0(见package.json)。 - 社区目录 SkillHub 与 DeepSeek / 幻方无官方从属关系;DSH 生态遵循「一切皆插件」,选用前请核对版本与自身合规要求。
- 本地抓取降级安全模型弱于专用 HTTP 抓取插件;高安全场景请评估
fallbackToHttp与密钥存放方式。
结尾¶
dsh-web-tool-provider 把 Tavily、Exa、Firecrawl 收成可互换的 ctx.web 后端,设置页分离搜索与抓取引擎,密钥与额度一目了然,并在抓取侧提供可配置的本地降级。进一步了解实现细节与 YAML 字段,见 GitHub README:https://github.com/nhhc-lxr/dsh-web-tool-provider;插件索引:https://www.skillhub.cn/plugins/nhhc-lxr/dsh-web-tool-provider。