Skip to content

feat: add Tavily as parallel search provider in web_search tool#2

Open
mani2001 wants to merge 2 commits intotysonchamp:mainfrom
mani2001:feat/tavily-migration/tools-web-search-duckduckgo
Open

feat: add Tavily as parallel search provider in web_search tool#2
mani2001 wants to merge 2 commits intotysonchamp:mainfrom
mani2001:feat/tavily-migration/tools-web-search-duckduckgo

Conversation

@mani2001
Copy link

Summary

  • Added Tavily as a configurable search backend alongside existing DuckDuckGo in tools/web_search.py
  • Search provider is selectable via SEARCH_PROVIDER env var (duckduckgo or tavily, defaults to duckduckgo)
  • Existing DuckDuckGo functionality is fully preserved and remains the default

Files changed

  • tools/web_search.py — Extracted DuckDuckGo logic into perform_duckduckgo_search(), added perform_tavily_search() using TavilyClient, added provider dispatcher in perform_web_search()
  • requirements.txt — Added tavily-python dependency
  • env.example — Added SEARCH_PROVIDER and TAVILY_API_KEY env vars
  • config/config.yaml.example — Added search.provider and search.tavily_api_key config fields

Dependency changes

  • Added tavily-python to requirements.txt

Environment variable changes

  • Added SEARCH_PROVIDER (optional, values: duckduckgo|tavily, default: duckduckgo)
  • Added TAVILY_API_KEY (required when SEARCH_PROVIDER=tavily)

Notes for reviewers

  • This is an additive change — DuckDuckGo remains the default provider and all existing behavior is unchanged
  • To use Tavily, set SEARCH_PROVIDER=tavily and provide a valid TAVILY_API_KEY
  • The Tavily response format (title, url, content) is mapped to match the existing DuckDuckGo output shape

🤖 Generated with Claude Code

Automated Review

  • Passed after 2 attempt(s)
  • Final review: The Tavily migration is correct, complete, and additive. All necessary files were updated: requirements.txt adds tavily-python, config/__init__.py wires up SEARCH_PROVIDER/TAVILY_API_KEY env-var overrides into the config object, config/config.yaml.example documents the new search: block, env.example adds both env vars with a trailing newline, and tools/web_search.py correctly renames the old function to perform_duckduckgo_search, adds perform_tavily_search, and introduces a dispatcher perform_web_search with provider routing, fallback warning, and graceful error handling. Existing DuckDuckGo behavior is fully preserved. Three minor issues were found but none are blocking.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the web search tool by integrating Tavily as an additional, configurable search provider alongside the existing DuckDuckGo service. This provides users with greater flexibility in choosing their preferred search backend via environment variables or configuration, thereby expanding web data retrieval options without altering the default behavior or requiring changes to existing implementations.

Highlights

  • New Search Provider: Tavily has been integrated as an alternative web search provider for the web_search tool.
  • Configurable Search: Users can now select between DuckDuckGo (default) and Tavily using the SEARCH_PROVIDER environment variable or configuration.
  • Backward Compatibility: Existing DuckDuckGo functionality is fully preserved, ensuring no breaking changes to current implementations.
  • API Key Management: The TAVILY_API_KEY environment variable is introduced for authenticating with the Tavily service when selected.
  • Output Consistency: Tavily search results are mapped to match the existing output format of DuckDuckGo for seamless integration.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@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 adds Tavily as a configurable search provider, which is a great enhancement. The changes across the configuration files and requirements.txt are correct. However, in tools/web_search.py, the new dispatcher logic for selecting the search provider is overly complex, difficult to read, and contains a bug related to handling the TAVILY_API_KEY when the configuration file is not present. I've provided a single, comprehensive suggestion to refactor the perform_web_search function to improve its clarity, fix the bug, and make it more robust by adding a fallback mechanism.

Comment on lines +45 to +57
def perform_web_search(query):
"""Dispatches search to the configured provider (duckduckgo or tavily)."""
conf = app_config.load_config()
provider = (conf.get("search", {}).get("provider", "duckduckgo") if conf else os.environ.get("SEARCH_PROVIDER", "duckduckgo")).lower()
if provider not in ("duckduckgo", "tavily"):
logging.warning(f'Unknown SEARCH_PROVIDER "{provider}", falling back to duckduckgo')
provider = "duckduckgo"
if provider == "tavily":
tavily_key = conf.get("search", {}).get("tavily_api_key", "") if conf else ""
if tavily_key:
os.environ.setdefault("TAVILY_API_KEY", tavily_key)
return perform_tavily_search(query)
return perform_duckduckgo_search(query)

Choose a reason for hiding this comment

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

high

The current implementation for selecting the search provider and handling the API key in perform_web_search is complex and contains a bug.

  1. The logic is packed into dense one-liners, which harms readability.
  2. There's a bug where if the config file is missing, the code doesn't fall back to using the TAVILY_API_KEY environment variable.
  3. If Tavily is the selected provider but the API key is missing, the search will fail instead of gracefully falling back to another provider.

I suggest refactoring the entire function to be more explicit and robust. This change improves readability, fixes the bug, and adds a safe fallback to DuckDuckGo if the Tavily key is missing.

def perform_web_search(query):
    """Dispatches search to the configured provider (duckduckgo or tavily)."""
    conf = app_config.load_config()

    if conf:
        search_conf = conf.get("search", {})
        provider = search_conf.get("provider", "duckduckgo")
        tavily_key = search_conf.get("tavily_api_key")
    else:
        provider = os.getenv("SEARCH_PROVIDER", "duckduckgo")
        tavily_key = os.getenv("TAVILY_API_KEY")

    provider = provider.lower()
    if provider not in ("duckduckgo", "tavily"):
        logging.warning(f'Unknown SEARCH_PROVIDER "{provider}", falling back to duckduckgo')
        provider = "duckduckgo"

    if provider == "tavily":
        if tavily_key:
            os.environ.setdefault("TAVILY_API_KEY", tavily_key)
            return perform_tavily_search(query)
        logging.warning("SEARCH_PROVIDER is 'tavily' but TAVILY_API_KEY is not set. Falling back to duckduckgo.")
    
    return perform_duckduckgo_search(query)

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