feat: migrate web search to support Tavily as additive engine option#350
feat: migrate web search to support Tavily as additive engine option#350tavily-integrations wants to merge 2 commits into
Conversation
…le engine option in web_search.py
bradtaylorsf
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I’m requesting changes before this can merge.
Blockers:
-
This PR adds Tavily as a new third-party credit-based search API and makes
engine="auto"prefer it whenTAVILY_API_KEYis 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 withCloses #..., or remove the Tavily provider/auto-priority/env/docs/dependency changes until that issue exists. -
pyproject.tomladdstavily-python>=0.3(pyproject.toml:43), butuv.lockwas not updated. In a fresh PR worktree,uv lock --checkfails with “The lockfile atuv.lockneeds to be updated,” anduv run --locked pytest -q tests/test_tools_web_search.pyfails before tests start for the same reason. Please regenerate and commituv.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.
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:
Engineliteral type to include'tavily'_search_tavily()using thetavily-pythonAsyncTavilyClient, mapping results toSearchResultwithsource_engine='tavily''auto'engine selection: Tavily (ifTAVILY_API_KEYset) → Brave (ifBRAVE_SEARCH_API_KEYset) → DDG fallbackTAVILY_API_KEYas an optionalEnvKeyinconfig.pyEXPECTED_ENV_KEYSTAVILY_API_KEYto.env.examplewith signup URLTAVILY_API_KEYindocs/API_KEYS.mdunder recommended optional keysFiles changed
src/research_agent/tools/web_search.py— new_search_tavily(), updated Engine type and auto-resolutionsrc/research_agent/config.py— newTAVILY_API_KEYEnvKey entry.env.example— newTAVILY_API_KEY=linedocs/API_KEYS.md— documented Tavily key in recommended tablepyproject.toml— addedtavily-python>=0.3dependencyDependency changes
tavily-python>=0.3to[project].dependenciesinpyproject.tomlEnvironment variable changes
TAVILY_API_KEY(optional) — registered inconfig.py,.env.example, anddocs/API_KEYS.mdNotes for reviewers
engine='brave'.tavily-pythonimport is deferred inside_search_tavily()to avoid import errors if the package is missing at runtime.contentfield maps tosnippetinSearchResult; the relevancescoreis passed through inextras.Automated Review