Skip to content

Web Providers Reference

This document describes web_search's currently supported search providers, provider selection behavior, configuration, and error boundaries. For Web tools parameters and return structures, see web-tools.md; for complete configuration, see configuration.md.

Provider overview

Providers are the search backend adapters for web_search. The current provider registry is at src/modules/web/providers/registry.ts, and provider selection is at src/modules/web/providers/select-provider.ts.

Current providers:

text
ddgs, brave, tavily, serper, openserp, searxng

Providers are only used for web_search. fetch_content's Jina Reader fallback is not a regular search provider; see Jina fallback below.

Provider implementations follow the architecture consistency policy: each search provider should use the shared provider adapter interface, provider registry, selection flow, configuration naming pattern, and provider-focused tests unless a documented exception exists.

Provider matrix

ProviderAPI keyConfig keyEnvironment variableSelection availabilityPrimary useLimitations
ddgsNot neededNo provider sub-configNoneAlways enabled; adapter isAvailable() always returns trueZero-config DuckDuckGo Lite fallbackMax 5 results per request; depends on DuckDuckGo Lite HTML structure
braveRequiredweb.brave.*Default BRAVE_SEARCH_API_KEY, customizable via web.brave.apiKeyEnvRequires web.brave.enabled=true, valid baseUrl, and keyBrave Search APIThird-party rate limit/API behavior may change
tavilyRequiredweb.tavily.*Default TAVILY_API_KEY, customizable via web.tavily.apiKeyEnvRequires web.tavily.enabled=true, valid baseUrl, and keyTavily Search APIThird-party rate limit/API behavior may change
serperRequiredweb.serper.*Default SERPER_API_KEY, customizable via web.serper.apiKeyEnvRequires web.serper.enabled=true, valid baseUrl, and keySerper Google Search APIThird-party rate limit/API behavior may change
openserpRequiredweb.openserp.*Default OPENSERP_API_KEY, customizable via web.openserp.apiKeyEnvRequires web.openserp.enabled=true, valid baseUrl, and keyOpenSERP-compatible APIResponse fields support organic_results or results
searxngNot neededweb.searxng.*NoneRequires web.searxng.enabled=true and valid HTTP/HTTPS baseUrlSelf-hosted SearXNG JSON searchRequires accessible SearXNG instance; requests use fixed format=json

Provider configuration summary

ddgs

Zero-config provider. Default web.provider is ddgs.

json
{
  "web": {
    "provider": "ddgs"
  }
}

Implementation limit: src/modules/web/providers/ddgs.ts limits results to a maximum of 5.

brave

json
{
  "web": {
    "provider": "brave",
    "brave": {
      "enabled": true,
      "baseUrl": "https://api.search.brave.com/res/v1/web/search",
      "apiKeyEnv": "BRAVE_SEARCH_API_KEY"
    }
  }
}

When explicitly selecting brave, web.brave.enabled must be true; missing key will be classified as PROVIDER_AUTH_FAILED during the provider request phase.

tavily

json
{
  "web": {
    "provider": "tavily",
    "tavily": {
      "enabled": true,
      "baseUrl": "https://api.tavily.com/search",
      "apiKeyEnv": "TAVILY_API_KEY"
    }
  }
}

When explicitly selecting tavily, web.tavily.enabled must be true; missing key will be classified as PROVIDER_AUTH_FAILED during the provider request phase.

serper

json
{
  "web": {
    "provider": "serper",
    "serper": {
      "enabled": true,
      "baseUrl": "https://google.serper.dev/search",
      "apiKeyEnv": "SERPER_API_KEY"
    }
  }
}

When explicitly selecting serper, web.serper.enabled must be true; missing key will be classified as PROVIDER_AUTH_FAILED during the provider request phase.

openserp

json
{
  "web": {
    "provider": "openserp",
    "openserp": {
      "enabled": true,
      "baseUrl": "https://api.openserp.com/search",
      "apiKeyEnv": "OPENSERP_API_KEY"
    }
  }
}

When explicitly selecting openserp, web.openserp.enabled must be true. The provider reads the key from the environment variable specified by web.openserp.apiKeyEnv.

searxng

json
{
  "web": {
    "provider": "searxng",
    "searxng": {
      "enabled": true,
      "baseUrl": "https://searx.example.com",
      "defaultEngine": "google"
    }
  }
}

When explicitly selecting searxng, web.searxng.enabled must be true, and web.searxng.baseUrl must be a valid HTTP/HTTPS URL. If the base URL pathname is /, source code will request /search; otherwise the original pathname is preserved.

Provider selection

Explicit mode

When web.provider is a specific provider name, selection enters explicit mode:

  • Only that provider is used.
  • Provider failure does not fall back to other providers.
  • Unsupported provider name returns INVALID_INPUT.
  • brave, openserp, searxng, tavily, serper must be enabled in their corresponding config before explicit use.
  • All explicit providers run the same technical availability check during selection.
  • Missing API keys for keyed providers return PROVIDER_AUTH_FAILED; invalid endpoints return INVALID_INPUT.

Auto mode

When web.provider="auto", selection constructs a candidate list from providers that are enabled and technically available. Source code divides providers into three tiers:

  1. commercial: tavily, serper, brave
  2. self-host-or-open: openserp, searxng
  3. zero-config: ddgs

Within each tier, providers are sorted by web.providerPriority, then concatenated. Default priority:

text
tavily → serper → brave → openserp → searxng → ddgs

Selection availability combines a config enabled gate with each provider adapter's technical isAvailable() check:

  • ddgs: always enabled and technically available.
  • brave / tavily / serper / openserp: requires enabled=true, valid baseUrl, and API key.
  • searxng: requires enabled=true and valid HTTP/HTTPS baseUrl.

Provider adapter isAvailable() implementations intentionally do not check enabled; selectSearchProvider owns the enabled gate.

In auto mode, when one provider fails, web_search will try the next candidate provider; when all candidates fail, it returns the last error or WEB_SEARCH_FAILED.

Default behavior

Default configuration is:

json
{
  "web": {
    "provider": "ddgs"
  }
}

Therefore default is not auto, but explicitly using ddgs.

Provider error behavior

Provider errors are ultimately classified by src/modules/web/search.ts into WebToolError.

ScenarioCurrent error behavior
Explicit unsupported providerINVALID_INPUT
Explicit provider not enabled or endpoint config invalidINVALID_INPUT
API key missing or HTTP 401/403PROVIDER_AUTH_FAILED
HTTP 429PROVIDER_RATE_LIMITED
HTTP 5xxPROVIDER_UNAVAILABLE
fetch failed / DNS ENOTFOUND / ECONN*NETWORK_ERROR
timeout / abortWEB_SEARCH_TIMEOUT
Provider request failed or uncategorized exceptionWEB_SEARCH_FAILED
Provider JSON parse / response shape anomalyCurrently continues to be classified as WEB_SEARCH_FAILED; does not directly return reserved code PARSE_ERROR
Provider returns empty resultsSuccess response, results = []; does not return WEB_SEARCH_NO_RESULTS

For complete error code status, see web-tools-error-codes.md.

Jina fallback

Jina Reader fallback is an internal content extraction recovery mechanism within fetch_content, not a web_search provider:

  • Does not participate in web.provider / web.providerPriority.
  • Not registered in src/modules/web/providers/registry.ts.
  • May only trigger when fetch_content processes HTML and web.enableJinaFallback=true.
  • preferReader=true is a single fetch_content tool parameter, not provider selection.
  • Private network URLs are not sent to Jina.
  • Jina failure currently does not introduce new JINA_* error codes; timeout/abort may return CONTENT_FETCH_TIMEOUT, other exceptions may be classified as CONTENT_FETCH_FAILED, and non-2xx or empty content falls back to original HTML extraction result.

Related configuration: configuration.md#jina-reader-configuration.

Source map

Document topicSource
Provider registrysrc/modules/web/providers/registry.ts
Provider adapter interfacesrc/modules/web/providers/types.ts
Provider selectionsrc/modules/web/providers/select-provider.ts
ddgssrc/modules/web/providers/ddgs.ts
bravesrc/modules/web/providers/brave.ts
tavilysrc/modules/web/providers/tavily.ts
serpersrc/modules/web/providers/serper.ts
openserpsrc/modules/web/providers/openserp.ts
searxngsrc/modules/web/providers/searxng.ts
Search error classificationsrc/modules/web/search.ts
Provider config typessrc/shared/types.ts
Provider config defaults/normalizesrc/config/load-config.ts