feat: migrate web search to support Tavily alongside DuckDuckGo#4
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces Tavily as an alternative web search provider alongside DuckDuckGo, refactoring the search logic into modular functions. Feedback was provided to ensure DuckDuckGo results are correctly validated by converting the generator to a list and to improve observability by adding error logging to the search wrapper.
| results = DDGS().text(query, max_results=5) | ||
| if not results: | ||
| return "No results found." |
There was a problem hiding this comment.
The DDGS().text() method in the duckduckgo_search library (and similar wrappers) often returns a generator. In Python, a generator object is always truthy, so the if not results check will fail to detect empty results. Converting the results to a list ensures the check works correctly and allows for safe iteration.
| results = DDGS().text(query, max_results=5) | |
| if not results: | |
| return "No results found." | |
| results = list(DDGS().text(query, max_results=5)) | |
| if not results: | |
| return "No results found." |
| except Exception as e: | ||
| return f"Error performing search: {e}" |
There was a problem hiding this comment.
This try...except block catches all exceptions and returns them as a string, which is then passed to the LLM. However, it doesn't log the error, making it difficult to debug issues (like API failures or network errors) from the server logs. Since the caller web_search also has a try...except block with logging, it would be better to either log the error here or let the exception bubble up.
| except Exception as e: | |
| return f"Error performing search: {e}" | |
| except Exception as e: | |
| logging.error(f"Web search error: {e}", exc_info=True) | |
| return f"Error performing search: {e}" |
Summary
Adds Tavily as an opt-in search backend in
tools/web_search.py. When theTAVILY_API_KEYenvironment variable is set, web searches use the Tavily API; otherwise the existing DuckDuckGo (ddgs) path is used as a fallback.This is an additive change — no existing functionality is removed.
Changes
tools/web_search.py: Refactoredperform_web_search()to dispatch to_tavily_search()or_ddgs_search()based on whetherTAVILY_API_KEYis present in the environment. Addedimport os.requirements.txt: Addedtavily-pythondependency (keptddgs).env.example: AddedTAVILY_API_KEY=so operators know the variable is available.Dependency changes
tavily-pythontorequirements.txtEnvironment variable changes
TAVILY_API_KEY(optional; activates Tavily when set)Notes for reviewers
search_depth="basic"andmax_results=5to match existing behavior.🤖 Generated with Claude Code
Automated Review