Skip to content

Conversation

Rudra775
Copy link
Contributor

@Rudra775 Rudra775 commented Jul 13, 2025

🎯 Overview

Closes #82

📝 Description

This pull request replaces Tavily web search integration with a free and open-source alternative: DuckDuckGo, using the ddgs package. It updates the search_tool.py logic to query using DuckDuckGo and append source URLs as citations in the final LLM response.

🔧 Changes Made

Created: backend/app/agents/devrel/tools/search_tool/ddg.py

  • Implements DuckDuckGoSearchTool using ddgs

Moved: Tavily logic to backend/app/agents/devrel/tools/search_tool/tavily.py

  • No changes to Tavily logic itself

Modified: backend/app/agents/devrel/nodes/agent.py

  • Updated to use DuckDuckGoSearchTool by default

📷 Screenshots or Visual Changes (if applicable)

image image

Summary by CodeRabbit

  • New Features

    • Introduced a new web search tool powered by DuckDuckGo for enhanced search capabilities.
  • Bug Fixes

    • Updated search result formatting to improve consistency and clarity.
  • Chores

    • Added the required dependency for the new DuckDuckGo search tool.

Copy link
Contributor

coderabbitai bot commented Jul 13, 2025

Walkthrough

The changes migrate the backend web search functionality from Tavily Search to DuckDuckGo Search. This includes updating import paths, tool instantiations, and result processing logic to use the new DuckDuckGo search tool. A new dependency on the ddgs library is added, and a new class for DuckDuckGo search is implemented.

Changes

File(s) Change Summary
backend/app/agents/devrel/agent.py Replaced TavilySearchTool with DuckDuckGoSearchTool in imports and instantiation.
backend/app/agents/devrel/github/tools/search.py Updated to use DuckDuckGoSearchTool instead of TavilySearchTool; updated docstring accordingly.
backend/app/agents/devrel/nodes/handlers/web_search.py Changed source/tool names to "duckduckgo_search"; updated snippet extraction key; minor cleanup.
backend/app/agents/devrel/tools/search_tool/ddg.py Added new DuckDuckGoSearchTool class implementing async search via DDGS library.
backend/app/agents/devrel/tools/search_tool/tavilly.py Removed an extraneous newline at end of file.
pyproject.toml Added ddgs library dependency for DuckDuckGo search functionality.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DevRelAgent
    participant DuckDuckGoSearchTool
    participant DDGS Library

    User->>DevRelAgent: Initiate web search query
    DevRelAgent->>DuckDuckGoSearchTool: search(query)
    DuckDuckGoSearchTool->>DDGS Library: Perform DuckDuckGo search
    DDGS Library-->>DuckDuckGoSearchTool: Return search results
    DuckDuckGoSearchTool-->>DevRelAgent: Return processed results
    DevRelAgent-->>User: Return search results
Loading

Assessment against linked issues

Objective Addressed Explanation
Migrate web search from Tavily Search to DuckDuckGo Search (#82)
Update handle_web_search_node and search tool to use DuckDuckGo (#82)
Add DuckDuckGo search library dependency, remove Tavily dependencies (#82)
Remove Tavily API key setting and update config if needed (#82) No evidence of config file changes; config.py not mentioned in the provided change summary.

Poem

In burrows deep, I search anew,
DuckDuckGo now hops into view!
Tavily’s gone, the code is neat,
DDGS makes results complete.
With whiskers twitching, queries fly—
A rabbit’s search will never die!
🐇🔍


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36a61c9 and 6724f33.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • backend/app/agents/devrel/github/tools/search.py (1 hunks)
  • backend/app/agents/devrel/nodes/handlers/web_search.py (2 hunks)
  • backend/app/agents/devrel/tools/search_tool/ddg.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/app/agents/devrel/nodes/handlers/web_search.py
  • backend/app/agents/devrel/github/tools/search.py
  • backend/app/agents/devrel/tools/search_tool/ddg.py
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/app/agents/devrel/tools/search_tool/ddg.py (1)

15-17: Consider enhancing the helper method for better error isolation.

While the current implementation works, consider adding error handling directly in the helper method to better isolate DDGS-specific exceptions.

     def _perform_search(self, query: str, max_results: int):
-        with DDGS() as ddg:
-            return ddg.text(query, max_results=max_results)
+        try:
+            with DDGS() as ddg:
+                return ddg.text(query, max_results=max_results)
+        except Exception as e:
+            logger.debug("DDGS library error: %s", str(e))
+            raise
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7dc98 and 737031a.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • backend/app/agents/devrel/agent.py (2 hunks)
  • backend/app/agents/devrel/github/tools/search.py (1 hunks)
  • backend/app/agents/devrel/nodes/handlers/web_search.py (2 hunks)
  • backend/app/agents/devrel/tools/search_tool/ddg.py (1 hunks)
  • backend/app/agents/devrel/tools/search_tool/tavilly.py (1 hunks)
  • pyproject.toml (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
backend/app/agents/devrel/nodes/handlers/web_search.py (2)
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
backend/app/agents/devrel/tools/search_tool/tavilly.py (2)
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
backend/app/agents/devrel/agent.py (3)
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#75
File: backend/app/agents/devrel/agent.py:34-35
Timestamp: 2025-06-13T21:56:19.183Z
Learning: In the Devr.AI backend, the DevRelAgent follows a singleton pattern where only one instance exists for the entire application lifetime, using InMemorySaver with thread-based conversation management to persist user conversations across sessions.
backend/app/agents/devrel/github/tools/search.py (2)
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
backend/app/agents/devrel/tools/search_tool/ddg.py (2)
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method has partial error handling for missing API key, AttributeError, ConnectionError, and TimeoutError, but lacks a comprehensive Exception catch-all block, so calling functions may still need additional error handling for other potential exceptions.
Learnt from: smokeyScraper
PR: AOSSIE-Org/Devr.AI#72
File: backend/app/agents/devrel/nodes/handle_web_search_node.py:31-42
Timestamp: 2025-06-08T13:31:11.572Z
Learning: In backend/app/agents/devrel/tools/search_tool.py, the TavilySearchTool.search() method already includes comprehensive error handling that catches all exceptions and returns an empty list instead of raising them, so calling functions don't need additional try-catch blocks.
🧬 Code Graph Analysis (3)
backend/app/agents/devrel/agent.py (1)
backend/app/agents/devrel/tools/search_tool/ddg.py (1)
  • DuckDuckGoSearchTool (9-42)
backend/app/agents/devrel/github/tools/search.py (1)
backend/app/agents/devrel/tools/search_tool/ddg.py (1)
  • DuckDuckGoSearchTool (9-42)
backend/app/agents/devrel/tools/search_tool/ddg.py (1)
backend/app/agents/devrel/tools/search_tool/tavilly.py (1)
  • search (17-52)
🔇 Additional comments (10)
pyproject.toml (1)

27-27: LGTM! Dependency addition is appropriate.

The version constraint for the ddgs package follows best practices, allowing patch and minor updates while preventing potentially breaking changes in major version 10.

backend/app/agents/devrel/tools/search_tool/tavilly.py (1)

52-52: LGTM! Minor formatting cleanup.

Removing the trailing newline improves code consistency.

backend/app/agents/devrel/nodes/handlers/web_search.py (2)

44-46: LGTM! Source identifier updates are consistent.

The changes correctly update the source identifiers from "tavily_search" to "duckduckgo_search" to reflect the new search tool being used.


60-62: LGTM! Field mapping updated correctly.

The change from 'snippet' to 'content' aligns with the DuckDuckGoSearchTool's result format, which returns content in the 'content' field rather than 'snippet'.

backend/app/agents/devrel/agent.py (2)

30-30: LGTM! Search tool instantiation updated correctly.

The instantiation is updated to use DuckDuckGoSearchTool, maintaining the same interface as the previous TavilySearchTool.


8-8: Import Verified: DuckDuckGoSearchTool Implementation Exists

Confirmed that backend/app/agents/devrel/tools/search_tool/ddg.py defines class DuckDuckGoSearchTool on line 9. The import and instantiation changes are correct.

backend/app/agents/devrel/github/tools/search.py (3)

3-3: LGTM! Import updated correctly.

The import correctly references the new DuckDuckGoSearchTool from the updated module path.


8-8: LGTM! Docstring updated appropriately.

The docstring correctly reflects the change to using the DuckDuckGo search tool.


12-12: LGTM! Search tool instantiation updated correctly.

The instantiation correctly uses DuckDuckGoSearchTool, which based on the retrieved learnings should have improved error handling compared to the previous TavilySearchTool.

backend/app/agents/devrel/tools/search_tool/ddg.py (1)

19-42: The DDG search’s error‐handling branch for network issues never returns a value (falls through to None), and we can’t confirm “body”/“href”/“title” without docs or a quick test. To be safe:

• In the except (ConnectionError, TimeoutError) block add return [] so it always returns a list
• Run a brief smoke test against DDGS or check its docs to confirm the result dict has “results” → list of { title, body, href }.

Please update accordingly or verify with a test call to DDGS.

@smokeyScraper
Copy link
Contributor

very well aligned and clean work @Rudra775!
could you please resolve the remaining issue as raised by coderabbit?
also please run poetry lock once (the dependencies aren't updated)

Also, how were you initializing the app? I'm facing a few import path errors, which are preventing the app from starting. Could you please check once again, or lmk how you were using it. The current app is set to run under backend/ directory

PS: In order to have a clean commit history, please undo your last commit and make changes within that, then make a commit with a force push. This keeps the commit history clean. I'm preferring "'n' commits for edits" + "1 commit for coderabbit fix" (Easiest is to use editor's (VS Code/Cursor) GitHub section for this)

@smokeyScraper smokeyScraper merged commit ed85a5e into AOSSIE-Org:main Jul 15, 2025
1 check passed
@smokeyScraper
Copy link
Contributor

merged!
cheers! @Rudra775

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.

FEATURE REQUEST: Migrate from Tavily Search to DuckDuckGo Search

2 participants