Skip to content

feat: migrate web search to support Tavily as additive engine option#350

Open
tavily-integrations wants to merge 2 commits into
bradtaylorsf:mainfrom
Tavily-FDE:feat/tavily-migration/web-search-tavily
Open

feat: migrate web search to support Tavily as additive engine option#350
tavily-integrations wants to merge 2 commits into
bradtaylorsf:mainfrom
Tavily-FDE:feat/tavily-migration/web-search-tavily

Conversation

@tavily-integrations
Copy link
Copy Markdown

Summary

Adds Tavily as a configurable search engine option in web_search.py, alongside the existing Brave Search API, DuckDuckGo, and Google Playwright scrapers. This is an additive migration — all existing providers remain fully intact.

What changed:

  • Extended Engine literal type to include 'tavily'
  • Implemented _search_tavily() using the tavily-python AsyncTavilyClient, mapping results to SearchResult with source_engine='tavily'
  • Updated 'auto' engine selection: Tavily (if TAVILY_API_KEY set) → Brave (if BRAVE_SEARCH_API_KEY set) → DDG fallback
  • Registered TAVILY_API_KEY as an optional EnvKey in config.py EXPECTED_ENV_KEYS
  • Added TAVILY_API_KEY to .env.example with signup URL
  • Documented TAVILY_API_KEY in docs/API_KEYS.md under recommended optional keys

Files changed

  • src/research_agent/tools/web_search.py — new _search_tavily(), updated Engine type and auto-resolution
  • src/research_agent/config.py — new TAVILY_API_KEY EnvKey entry
  • .env.example — new TAVILY_API_KEY= line
  • docs/API_KEYS.md — documented Tavily key in recommended table
  • pyproject.toml — added tavily-python>=0.3 dependency

Dependency changes

  • Added tavily-python>=0.3 to [project].dependencies in pyproject.toml

Environment variable changes

  • Added TAVILY_API_KEY (optional) — registered in config.py, .env.example, and docs/API_KEYS.md

Notes for reviewers

  • Auto mode now prefers Tavily over Brave when both keys are set. This can be overridden by explicitly setting engine='brave'.
  • The tavily-python import is deferred inside _search_tavily() to avoid import errors if the package is missing at runtime.
  • Tavily's content field maps to snippet in SearchResult; the relevance score is passed through in extras.

Automated Review

  • Passed after 2 attempt(s)
  • Final review: The Tavily migration is correct, complete, and consistent with the existing codebase. The implementation properly adds Tavily as a first-priority engine in auto-resolution (Tavily > Brave > DDG), guards against missing key / ImportError / network errors, logs lang-ignored at INFO level matching the DDG/Google pattern, and fixes all 6 pre-existing auto-resolution tests to be deterministic in CI when TAVILY_API_KEY is present. All required registrations (pyproject.toml, config.py EXPECTED_ENV_KEYS, .env.example, docs/API_KEYS.md) are in place. One minor code-quality issue was found in the tests but does not block approval.

Copy link
Copy Markdown
Owner

@bradtaylorsf bradtaylorsf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution. I’m requesting changes before this can merge.

Blockers:

  1. This PR adds Tavily as a new third-party credit-based search API and makes engine="auto" prefer it when TAVILY_API_KEY is set (src/research_agent/tools/web_search.py:488). I don’t see a linked/closing issue approving this policy change, and the repo rules require one issue per PR plus explicit approval for new paid/gated data APIs. Please link the approving issue in the PR body with Closes #..., or remove the Tavily provider/auto-priority/env/docs/dependency changes until that issue exists.

  2. pyproject.toml adds tavily-python>=0.3 (pyproject.toml:43), but uv.lock was not updated. In a fresh PR worktree, uv lock --check fails with “The lockfile at uv.lock needs to be updated,” and uv run --locked pytest -q tests/test_tools_web_search.py fails before tests start for the same reason. Please regenerate and commit uv.lock, then include the locked pytest result.

Review notes:

  • Tests were added for the Tavily happy path, missing key, import error, exception path, lang-ignore logging, and auto routing. That’s the right shape, but they are not currently runnable under the repo’s locked workflow.
  • I did not see hardcoded secrets, SQL/shell execution, or an obvious injection issue in the new code. The main security/project-policy concern is introducing a new external API key and credit-consuming outbound provider without an approving issue.

Verification run:

uv lock --check
uv run --locked pytest -q tests/test_tools_web_search.py

Both failed because uv.lock is stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants