Introduction

When developing agents with dsh, web search defaults to the official deepseek-official channel. This channel is not a dedicated search endpoint: every search triggers a full Messages model call, consuming tokens for the search request itself, then backfilling the result into the conversation and billing it as conversation tokens—both are deducted from the DEEPSEEK_API_KEY balance. Moreover, it forces dependency on this key—if your dialogue model runs through a third-party channel, you likely haven’t configured it. The dsh-web-search-free introduced below replaces this channel with a pure retrieval implementation using multiple engines + automatic fallback. Retrieval itself consumes no model tokens.

What is this

dsh-web-search-free is a free Web Search / Web Scraping plugin for DeepSeek Harness (dsh), maintained by MochiNek0, current version 1.3.0. Once installed, it registers as a web capability channel for dsh, providing both searchProvider and fetchProvider (id: web-search-free), taking over default search/crawling.

It is installed as a dsh bundle layer (declared in package.json as dsh.bundle.patch): install it to take over web search/crawling; uninstall and restart dsh to automatically fall back to the default channel, with no need to manually modify the profile.

How it works: Pure retrieval, 0 model tokens

All retrieval requests are sent directly from the dsh host process (Node) to the dedicated retrieval endpoints of each engine, e.g., Tavily’s /search, Exa’s /search, Jina’s s.jina.ai. This path does not go through the official search backend or any LLM; billing is done via each engine’s own API quota, most of which have a free tier. The browser side only has the settings card; it does not initiate any network requests.

Comparison with the official channel:

Official deepseek-official Plugin web-search-free
Retrieval Method Full Messages model call Direct call to dedicated retrieval endpoints
Model Tokens Consumed on every search 0
Billing Source DEEPSEEK_API_KEY balance Each engine’s own quota
Credentials Forces dependency on DEEPSEEK_API_KEY Each engine’s respective API Key
Result Content sources sources + snippet (Tavily also gives a direct answer)

Supported Engines and Free Quotas

Supports 8 engines; the table order is the default calling order:

Engine Search Fetch Free Quota
TinyFish Free (Rate limit: Search 30 req/min, Fetch 150 url/min)
AnySearch 1,000 times/day, resets daily
Exa (Metaphor) $20 sign-up bonus + $10 top-up monthly, cumulative no reset
Tavily 1,000 credits/month
Firecrawl 1,000 credits/month
Brave Search $5 quota/month, requires card binding but no charge
SerpApi 250 times/month
Jina AI New key gives 10M tokens, one-time, no reset

Two notes:

  1. Brave Search and SerpApi are pure SERP, have no URL scraping endpoints, and won’t enter the scraping chain. If you only configured keys for these two, scraping will error with No web fetch providers configured. — please add a key for an engine that supports scraping.
  2. Result date (publishedAt) coverage varies greatly: Brave’s page_age covers the most; Tavily’s published_date only returns under topic: 'news'. Since this plugin uses general web search, it is effectively empty; Firecrawl and AnySearch search results have no date field. If you care about timeliness, move Brave to the front of the call order.

Installation and Enablement

Prerequisites: dsh installed and dsh command available; pnpm in PATH; target profile is usually web (the plugin’s client half declares platform: web, settings card only appears in Web interface).

Install from npm (Recommended):

dsh plugin --profile web add dsh-web-search-free

After execution, the plugin takes over web search/crawling as a bundle layer.

Install from local source code (for development / secondary development), build first then install:

cd /path/to/dsh-web-search-free
pnpm install
pnpm build
dsh plugin --profile web add .

You can also execute using an absolute path from any directory: dsh plugin --profile web add /absolute/path/to/dsh-web-search-free.

Configuration

First, start the dsh Web interface:

dsh web          # equivalent to dsh --profile web

Open Settings → Plugins → Free Web Search (English interface: Web Search Free) card:

  1. Fill in the API Keys for each engine one by one. The same engine supports multiple keys, one per line, rotating within the engine; return on success of any (Engine, Key).
  2. Engines with filled keys enter the call chain; drag the ⋮⋮ handle on the left of the row to adjust the call order: those at the front are called first; if the previous one fails or quota is exhausted, it automatically falls to the next.
  3. Toggle the web_fetch tool on the model side as needed: turn on to mount, turn off to remove from the model tools table (not left to error).
  4. Click “Save”. Configuration is persisted via dsh’s settings namespace (web-search-free). It takes effect immediately after saving, no restart needed. Card text switches between English and Chinese following dsh’s language settings.

Two reminders: configure keys for at least one engine; otherwise search/crawling will error with No web search providers configured. web_fetch is enabled by default (dsh official combination disables it by default). If you are concerned about going online, you can turn it off in the card, at the cost of the model being unable to read the URLs given to it or read long documents in detail.

Verification

Have the model actually use the Web capability in a dialogue, e.g., “Search for today’s news” or “Fetch the content of https://example.com”. The second one requires “Enable web_fetch” in the card to be on; otherwise, the model’s tools table won’t have this tool. Requests will execute in the engine order you arranged; if an engine fails or quota is exhausted, it automatically falls to the next.

Update and Uninstall

# npm install: upgrade to new version
dsh plugin --profile web update dsh-web-search-free

# Local source link install: just rebuild
cd /path/to/dsh-web-search-free && pnpm build

Uninstall consists of two steps. First, click “Clear All Configuration” at the bottom of the card (need to click twice to confirm) — dsh’s uninstall process does not clean the settings namespace; skipping this step leaves API Keys in $DSH_HOME/settings.yaml. Then execute:

dsh plugin --profile web remove dsh-web-search-free

After uninstalling, you need to restart dsh for search/crawling to truly fall back to the default official channel.

Use Cases and Notes

It fits these scenarios: dialogue model uses third-party channels, no DEEPSEEK_API_KEY (official channel forces dependency on it); care about search token costs (here retrieval is 0 model tokens, only spending engine free quotas); want to control call order yourself, use multi-key rotation to improve availability.

Regarding security: The plugin runs with the permissions of the current dsh process. Before installing, it is recommended to browse the repository source code and confirm license information. As of this writing (2026-09-07), no explicit license field is seen in the repository’s README or package.json. If you mind, please confirm with the author before using.

Conclusion

dsh’s philosophy is “everything is a plugin,” and dsh-web-search-free is a practical item under this concept: take over/fallback web channel without modifying profile, retrieval doesn’t burn model tokens, and engine order and keys are arranged by you in the settings card. Related links: