Skip to content

fix(tools): make web_search resilient via multi-engine fallback (#231)#232

Merged
warren618 merged 1 commit into
mainfrom
fix/web-search-multi-backend
Jun 15, 2026
Merged

fix(tools): make web_search resilient via multi-engine fallback (#231)#232
warren618 merged 1 commit into
mainfrom
fix/web-search-multi-backend

Conversation

@warren618

Copy link
Copy Markdown
Collaborator

Summary

Makes web_search resilient to single-engine rate limiting. Fixes #231, where the tool showed a red ❌ "web search failure" while the run still completed via read_url — the symptom of DuckDuckGo (the default ddgs auto backend's lead engine) being throttled from cloud/shared IPs.

Why

ddgs is a metasearch aggregator (DuckDuckGo, Google, Bing, Brave, Mojeek, Yahoo, …), all key-free. The previous code relied on the default backend="auto", which leads with DuckDuckGo; when DDG threw, the whole tool returned an error even though the other engines were reachable. (Reproduced: the duckduckgo backend returns "No results found." intermittently while google/bing/brave/mojeek succeed for the same query.)

Changes

  • Pass an explicit ordered backend list (duckduckgo, google, bing, brave, mojeek, yahoo) so ddgs falls through a throttled engine to the next. Overridable via VIBE_TRADING_SEARCH_BACKENDS (e.g. pin to google, bing).
  • Retry transient failures with linear backoff (3 attempts).
  • Treat "No results found" as an ok + empty-results envelope, not an error.
  • On persistent failure, return an actionable message (retry / set the backend env / use read_url) instead of a bare exception string.
  • Report the backend list used in the ok envelope.
  • Preserves the legacy duckduckgo_search fallback (calls without the backend kwarg when ddgs isn't present).

Test Plan

  • New agent/tests/test_web_search_tool.py — 6 cases (mocked ddgs): multi-backend pass-through, env override, retry-then-succeed, no-results→ok-empty, persistent-failure message, max_results cap. All pass.
  • Live smoke against real ddgs returns results across the backend list.
  • Existing regression touching web_search (security scanner + MCP regression) passes; tool registry still discovers web_search (48 tools).

Checklist

  • No changes to protected areas (src/agent/, src/session/, src/providers/)
  • No hardcoded values (backend list is env-overridable)
  • Code follows CONTRIBUTING.md guidelines
web_search relied on ddgs's default 'auto' backend, which leads with
DuckDuckGo — heavily rate-limited from cloud/shared IPs. When DDG
threw, the whole tool returned ❌ (issue #231) even though Google/
Bing/Brave/Mojeek/Yahoo were reachable.

- Pass an explicit ordered backend list so ddgs falls through a
  throttled engine to the next; override via VIBE_TRADING_SEARCH_BACKENDS
- Retry transient failures with linear backoff (3 attempts)
- Treat "No results found" as an ok+empty envelope, not an error
- On persistent failure, return an actionable message (retry / set
  backend env / use read_url) instead of a bare exception string
- Report the backend list used in the ok envelope

Tests: new tests/test_web_search_tool.py (6 cases, mocked ddgs) cover
multi-backend pass-through, env override, retry-then-succeed,
no-results, persistent-failure message, and max_results cap.
@warren618 warren618 merged commit a1d84b5 into main Jun 15, 2026
1 check passed
@warren618 warren618 deleted the fix/web-search-multi-backend branch June 15, 2026 09:06
@warren618 warren618 mentioned this pull request Jun 15, 2026
@warren618 warren618 mentioned this pull request Jun 18, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant