1624318455 / dsh-plugin-tavily

Listed

Tavily-backed web search provider plugin for DeepSeek Harness (dsh) — registers a tavily search provider into ctx.web with a settings card in the web GUI

mainModelTool View source

Installation

npx -y @deepseek-ai/dsh plugin --profile web add github:1624318455/dsh-plugin-tavily

This installation command is an unverified starting point generated from the GitHub repository address.

README

Maintainer-authored documentation snapshot.

View on GitHub ↗
Commit 3471460Synced Aug 18, 2026

dsh-plugin-tavily

English | 中文

A Tavily-backed web search provider plugin for DeepSeek Harness (dsh). It is the professional/pro-user edition: it exposes the full Tavily request parameter set through the web GUI, while still letting developers pin values from the profile configuration file.

It registers a tavily search provider into the harness's ctx.web seam, so the built-in web_search tool searches the web through Tavily — and ships a settings card in the web GUI (设置 → 插件 → 网页搜索) where you paste your API key, tune advanced parameters, and test connectivity. One install, both halves.

Features

  • Drop-in search backend: select tavily and the built-in web_search tool (plus the agent's own search) is answered by Tavily — no model-facing changes.
  • Full professional parameter set in the GUI: API key, API Base URL, maxResults, searchDepth, topic, includeAnswer, includeRawContent, timeout, searchMode, and days are editable from the card; advanced fields are tucked into a collapsed <details> block so ordinary users are not overwhelmed.
  • Configuration-first priority: cordis.patch.yml > WebUI > code defaults. Any field explicitly set in the yaml is shown disabled on the card with a "covered by config file" badge, so a stale UI value can never shadow a developer's pinned config.
  • API connectivity test: a lightweight Test API connection button checks the currently entered key/base URL directly from the browser and reports success or the API error. Stored keys cannot be read back by the browser by design, so testing an already-configured key requires re-entering it once (it is not saved again).
  • Search mode: choose tavily-only (direct Tavily, skip DeepSeek) or deepseek-first (run DeepSeek first, then merge Tavily results) from the advanced panel.
  • Credential-first key handling: per-search resolution order is literal apiKey → credentials service (apiKeyEnv) → process.env[apiKeyEnv].

Install

dsh plugin --profile web add "github:1624318455/dsh-plugin-tavily#main"

During development, install from a local path instead:

dsh plugin --profile web add "file:/absolute/path/to/dsh-plugin-tavily"

The plugin registers the provider and its card only — it does not override your profile's chosen search provider.

Enable

  1. Select the provider. Either set the environment variable:

    export DSH_WEB_SEARCH_PROVIDER=tavily
    

    or add a row to your profile's cordis.patch.yml (~/.dsh/profiles/web/cordis.patch.yml):

    - id: web
      config:
        searchProvider: tavily
    
  2. Set the Tavily API key. Open 设置 → 插件 → 网页搜索, expand the Web search (Tavily) card, and paste the key into the API key field. The card shows whether a key is configured. Without a key the provider reports itself unavailable, so searches fail loudly with WEB_PROVIDER_CREDENTIAL_MISSING instead of silently returning nothing.

  3. Restart dsh and use web_search as usual. The model-facing tool is unchanged; only the backend answering it is now Tavily.

Verify the backend is really Tavily

The web_search tool's output schema is provider-agnostic — the model never sees a provider name, and the API key intentionally lives outside environment variables, so "check the env" is the wrong probe. To confirm the active backend:

  • Provider selection~/.dsh/profiles/web/cordis.patch.yml has the web row with searchProvider: tavily.
  • Plugin loaded~/.dsh/settings.yaml contains a web-search-tavily section (only the plugin's installSettingsSection writes it).
  • Credential in placeTAVILY_API_KEY exists in the credentials store (~/.dsh/.credentials.yaml), not in the environment.
  • Result fingerprint — a Tavily result carries a generated-answer summary in content; the built-in DeepSeek provider does not produce one.

Open 设置 → 插件 → 网页搜索 and expand the Web search (Tavily) card.

  • Basic area (always visible):
    • API key — paste your Tavily key. It is stored through the credentials service, never in a settings file.
    • API Base URL — leave blank for https://api.tavily.com, or set a proxy/endpoint base.
    • Search modetavily-only (default): direct Tavily, DeepSeek is not consulted; deepseek-first: run DeepSeek search first, then merge its results with Tavily. Both modes require the web config to select searchProvider: tavily.
    • Test API connection — verifies the key/base URL you just entered. Testing consumes one Tavily search credit. If a key is already configured but you have not typed one, the card tells you to re-enter it once; the browser intentionally cannot read stored secrets back.
  • Advanced area (🔧 Advanced Tavily request parameters):
    • Max results — how many web results per search (1–20, default 5).
    • Search depthbasic (fast/cheap) or advanced (deeper, more tokens).
    • Topicgeneral, news, or finance.
    • Include generated answer — default on; Tavily returns a direct answer summary.
    • Include raw page content — default off; enabling greatly increases context token usage.
    • Request timeout (ms) — default 30000.
    • Recency window (days) — optional recency filter for news/finance topics.

Every control has a short hint and a placeholder showing the default. Values are saved with the card's Save button and apply live; no service restart is needed.

If a field shows "Covered by config file; edit the yaml to change", it is pinned by cordis.patch.yml — the WebUI deliberately does not allow overriding it.

⚙️ Config-file usage (developer/pro users)

Configuration lives in your profile's cordis.patch.yml (~/.dsh/profiles/web/cordis.patch.yml). Add a web-search-tavily row with a config block:

- id: web-search-tavily
  name: '@dsh-external/dsh-plugin-tavily'
  config:
    searchDepth: advanced
    topic: news
    maxResults: 8
    includeRawContent: false
    timeout: 20000
    searchMode: deepseek-first

Priority

cordis.patch.yml config  >  WebUI card values  >  code defaults
  • If a key is present in the yaml config block, the card disables that field and shows the configuration-covered badge.
  • If the yaml does not set a field, the WebUI value (if any) is used.
  • If neither sets it, the code default applies.

Settings table

KeyDefaultMeaningGUI editable
apiKeyunsetliteral Tavily API key; prefer the credentials store insteadkey field (via credentials)
apiKeyEnvTAVILY_API_KEYcredential reference / environment key the provider resolves per searchconfig only
baseURLhttps://api.tavily.comendpoint base, /search appended
maxResults5default number of web results per search (1–20)
searchDepthbasicbasic (fast) or advanced (deep)
topicgeneralgeneral, news, or finance
includeAnswertruerequest Tavily's generated answer
includeRawContentfalseraw page content in results (context-heavy)
timeout30000request timeout in milliseconds
searchModetavily-onlytavily-only (direct Tavily) or deepseek-first (DeepSeek + Tavily combined)
daysunsetrecency window in days (news/finance topics)
numResults5deprecated alias for maxResultsno (use maxResults)

apiKeyEnv stays config-only deliberately: it is an advanced wiring detail. Values saved from the GUI land in ~/.dsh/settings.yaml's web-search-tavily section. Settings edits apply live — the provider re-reads the section for every operation, so no restart or re-registration is needed after changing a value from the card or the file.

Platform note (web GUI card visibility)

The web GUI serves a plugin's settings section to the browser only when its namespace is on the apiproxy allowlist (WEB_SETTINGS_NAMESPACES in @deepseek-ai/dsh-host-apiproxy). As of 0.1.0-rc.6 that list is hardcoded and the "let a plugin expose its own configuration" mechanism is deferred, so a freshly installed third-party card is filtered out even though the section is registered host-side. To make the Web search (Tavily) card render, add the namespace to the allowlist in your installed copy and restart dsh:

// ~/.dsh/profiles/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/index.js
// in the WEB_SETTINGS_NAMESPACES array:
"web-search-deepseek",
"web-search-tavily",   // ← add this line

The provider and all of its functionality work without this patch; only the GUI card is hidden. The patch is overwritten by pnpm install --force and by harness upgrades, so re-apply it after re-installing dependencies.

Mapping

Tavily's flat results[] maps to normalized WebSearchSources: urlurl, titletitle, snippet ← the non-blank content (entries without content are dropped), publishedAtpublished_date (news/finance topics). Tavily's generated answer (when includeAnswer) becomes the result content. A request's maxResults wins over the configured default and is sent as Tavily's max_results; the seam enforces the final bound. includeRawContent is sent as Tavily's include_raw_content. Failures surface as the seam's WebError (WEB_PROVIDER_ERROR / WEB_ABORTED); request timeouts are reported as WEB_PROVIDER_ERROR.

Development

pnpm install
pnpm run build          # tsdown → lib/index.mjs (host) + lib/client.cjs (browser, committed)
pnpm run typecheck      # tsc --noEmit
node tests/decode-check.mjs   # schema round-trip check (no network)
pnpm test               # real-API smoke: needs TAVILY_API_KEY

lib/ is committed so the plugin installs without a build step (no prepare script, no pnpm build-script allowlisting). The @deepseek-ai/* seam and framework packages are externalized — the harness provides them at runtime, declared as peerDependencies. The browser bundle (lib/client.cjs) is a CJS module-loader factory: it require()s only the client module table's platform packages and inlines the plugin's own card code, so it needs no extra install-time resolution. @deepseek-ai/dsh-base is a devDependency only, so the smoke test can resolve the harness runtime closure.

License

MIT

Project files and signals

Shown items are public repository signals detected in the directory snapshot.

TestsDetected

Repository information

Language
TypeScript
License
MIT
Last updated
Aug 18, 2026, 10:18 AM

Install deliberately

Review source code, permissions, lifecycle hooks, dependencies and network access. Test untrusted plugins in an isolated environment.