Skip to content

feat: add Tavily search option to legacy web search skill#5

Open
tavily-integrations wants to merge 1 commit into
tysonchamp:mainfrom
Tavily-FDE:feat/tavily-migration/legacy-web-search-ddgs
Open

feat: add Tavily search option to legacy web search skill#5
tavily-integrations wants to merge 1 commit into
tysonchamp:mainfrom
Tavily-FDE:feat/tavily-migration/legacy-web-search-ddgs

Conversation

@tavily-integrations
Copy link
Copy Markdown

Summary

  • Added Tavily as a configurable search provider in _legacy/skills/web_search.py
  • When TAVILY_API_KEY environment variable is set, perform_web_search() uses TavilyClient.search() with max_results=5 and search_depth="basic"
  • When TAVILY_API_KEY is not set, the existing DuckDuckGo (DDGS) search path is used unchanged
  • This is an additive/parallel migration — no existing functionality is removed

Files changed

  • _legacy/skills/web_search.py — Added os import and Tavily-gated branch in perform_web_search()
  • requirements.txt — Added tavily-python dependency

Dependency changes

  • Added tavily-python to requirements.txt

Environment variable changes

  • TAVILY_API_KEY — When set, enables Tavily search in the legacy skill layer (optional; DuckDuckGo remains the default)

Notes for reviewers

  • The Tavily branch mirrors the same pattern used in the active tools layer for consistency
  • Lower priority change — only needed if _legacy/ is still actively deployed

Automated Review

  • Passed after 1 attempt(s)
  • Final review: The migration correctly adds Tavily as a configurable search provider to _legacy/skills/web_search.py using an additive/fallback pattern. Tavily SDK usage is valid (TavilyClient, client.search(), and response field names title/url/content are all correct). The DDGS fallback is fully preserved. tavily-python is added to requirements.txt. TAVILY_API_KEY documentation in env.example is handled by the prerequisite unit active-web-search-ddgs and is not required here. No regressions, no unintended changes, no dead code.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request integrates the Tavily search API into the web search skill, providing it as a primary option when an API key is available while maintaining DuckDuckGo as a fallback. The requirements.txt file was updated to include the tavily-python package. Feedback was provided to refactor the perform_web_search function to eliminate code duplication between the two search provider paths by normalizing the result format before generating the final summary string.

Comment on lines 10 to +40
def perform_web_search(query):
from ddgs import DDGS
try:
results = DDGS().text(query, max_results=5)
if not results:
return "No results found."

summary = ""
for r in results:
summary += f"- [{r['title']}]({r['href']}): {r['body']}\n"
return summary
except Exception as e:
return f"Error performing search: {e}"
tavily_api_key = os.environ.get("TAVILY_API_KEY")
if tavily_api_key:
try:
from tavily import TavilyClient
client = TavilyClient(api_key=tavily_api_key)
response = client.search(query=query, max_results=5, search_depth="basic")
results = response.get("results", [])
if not results:
return "No results found."
summary = ""
for r in results:
title = r.get("title", "No title")
url = r.get("url", "")
content = r.get("content", "")
summary += f"- [{title}]({url}): {content}\n"
return summary
except Exception as e:
return f"Error performing search with Tavily: {e}"
else:
from ddgs import DDGS
try:
results = DDGS().text(query, max_results=5)
if not results:
return "No results found."
summary = ""
for r in results:
summary += f"- [{r['title']}]({r['href']}): {r['body']}\n"
return summary
except Exception as e:
return f"Error performing search: {e}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The perform_web_search function contains significant code duplication between the Tavily and DuckDuckGo search paths. Both branches implement nearly identical logic for checking results and formatting the markdown summary. Refactoring this to normalize the results into a common format before generating the summary would improve maintainability and reduce the risk of logic drift between providers.

def perform_web_search(query):
    tavily_api_key = os.environ.get("TAVILY_API_KEY")
    provider = "Tavily" if tavily_api_key else "DuckDuckGo"
    try:
        if tavily_api_key:
            from tavily import TavilyClient
            client = TavilyClient(api_key=tavily_api_key)
            response = client.search(query=query, max_results=5, search_depth="basic")
            results = [
                {"title": r.get("title", "No title"), "url": r.get("url", ""), "body": r.get("content", "")}
                for r in response.get("results", [])
            ]
        else:
            from ddgs import DDGS
            ddgs_results = DDGS().text(query, max_results=5)
            results = [
                {"title": r.get("title", "No title"), "url": r.get("href", ""), "body": r.get("body", "")}
                for r in (ddgs_results or [])
            ]

        if not results:
            return "No results found."

        summary = ""
        for r in results:
            summary += f"- [{r['title']}]({r['url']}): {r['body']}\n"
        return summary
    except Exception as e:
        return f"Error performing search with {provider}: {e}"

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.

1 participant