Files
deepseek-harness/packages/web/web-search-exa/README.md
Dudu-0223 d01f5f73b7 Add web capability seam: ctx.web, search/fetch providers, web tools
Introduce web access as a first-class capability seam so the model-facing
web tools stay stable while backends change. dsh-web owns ctx.web as a
provider registry with registration-order-independent selection and the
WebError taxonomy; dsh-web-search-exa, dsh-web-search-perplexity, and
dsh-web-fetch-local register capabilities into it; dsh-tool-web is the sole
owner of the model-facing web_search/web_fetch schemas, prompt sections, and
HTML-to-markdown presentation. Search and fetch are deliberately one seam.

Providers ship as namespace plugins that register into ctx.web (like an
LlmAdapter into ctx.llm), not key-owning services, since multiple search
providers cannot each own the key. Tool registration follows product
enablement, not backend availability, so load order/credentials never enter
the model contract; the seam resolves the provider at execution time and
surfaces a structured WebError otherwise.

Moves the RFC to implemented/ amended to match what shipped. Example/app
configs are intentionally not wired yet (RFC migration step 6).
2026-06-26 19:12:13 +08:00

1.7 KiB

@deepseek-ai/dsh-web-search-exa

An Exa-backed WebSearchProvider for the harness web capability seam (ctx.web). It calls Exa's POST /search endpoint with highlight contents and maps the flat results[] into the seam's normalized WebSearchResult.

This is an implementation package: it registers a provider into ctx.web, it does not own the ctx.web key and it does not register a model-facing tool (that is @deepseek-ai/dsh-tool-web). Like @deepseek-ai/dsh-llm-deepseek, it is a function/namespace plugin (inject: ['web']) that registers its backend, not a default-export service.

Config

Key Default Meaning
apiKey $EXA_API_KEY Exa API key. Empty/absent → provider status() reports missing-credential (the seam reports configured-unavailable/none).
baseURL https://api.exa.ai Endpoint base; /search is appended.
- id: web-search-exa
  name: '@deepseek-ai/dsh-web-search-exa'
  config:
    apiKey: !!js process.env.EXA_API_KEY

Mapping

Exa returns a flat results[] and no generated answer, so content is omitted. Each result maps to a WebSearchSource: urlurl, titletitle, snippet ← the first non-empty highlights[] entry (a result with no highlight has no portable snippet and is dropped), publishedAtpublishedDate. The provider passes maxResults through as Exa's numResults for a cost/latency optimization; the final bound is enforced by the seam. Provider failures (HTTP errors, network failure, unparseable bodies) surface as WebError WEB_PROVIDER_ERROR; an aborted request surfaces as WEB_ABORTED.