feat: add DuckDuckGoSearchTool (keyless web search)#6498
Conversation
Add a DuckDuckGoSearchTool that lets agents search the web via DuckDuckGo using the `ddgs` package. Unlike the existing search tools (Brave, SerpApi, Serper, Serply, Exa, Tavily, Linkup), it requires no API key, providing a zero-configuration default for web search. - New tool under lib/crewai-tools/src/crewai_tools/tools/duckduckgo_search_tool/ - Configurable n_results, region and safesearch - Lazy import of ddgs with a clear, actionable install message - Graceful error handling; returns compact title/link/snippet text - Unit tests under lib/crewai-tools/tests/tools/ (mocked, no network) - Register `ddgs` as an optional extra in pyproject.toml
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a new ChangesDuckDuckGo Search Tool
Sequence Diagram(s)sequenceDiagram
participant Caller
participant DuckDuckGoSearchTool
participant DDGS
Caller->>DuckDuckGoSearchTool: _run(search_query)
DuckDuckGoSearchTool->>DuckDuckGoSearchTool: validate search_query
DuckDuckGoSearchTool->>DDGS: text(query, n_results, region, safesearch)
DDGS-->>DuckDuckGoSearchTool: results or exception
DuckDuckGoSearchTool-->>Caller: formatted results, no-results message, or error string
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
lib/crewai-tools/tests/tools/duckduckgo_search_tool_test.py (1)
30-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winVerify that
region,safesearch, andmax_resultsare passed correctly toDDGS().text().
test_ddg_tool_searchassertsinstance.text.assert_called_once()but doesn't verify the arguments. Addingassert_called_once_withwould catch regressions if the parameter-passing logic in_runchanges.♻️ Proposed improvement
- instance.text.assert_called_once() + instance.text.assert_called_once_with( + "test", + region="wt-wt", + safesearch="moderate", + max_results=2, + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/crewai-tools/tests/tools/duckduckgo_search_tool_test.py` around lines 30 - 47, The DuckDuckGo search test only checks that DDGS().text() is called, not that _run passes the expected parameters. Update test_ddg_tool_search in DuckDuckGoSearchTool to assert the exact call arguments with assert_called_once_with, including region, safesearch, and max_results, so regressions in parameter wiring are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@lib/crewai-tools/tests/tools/duckduckgo_search_tool_test.py`:
- Around line 30-47: The DuckDuckGo search test only checks that DDGS().text()
is called, not that _run passes the expected parameters. Update
test_ddg_tool_search in DuckDuckGoSearchTool to assert the exact call arguments
with assert_called_once_with, including region, safesearch, and max_results, so
regressions in parameter wiring are caught.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 760d7e53-0351-4f7b-855b-6fbec7bb5b32
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
lib/crewai-tools/pyproject.tomllib/crewai-tools/src/crewai_tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/duckduckgo_search_tool/README.mdlib/crewai-tools/src/crewai_tools/tools/duckduckgo_search_tool/__init__.pylib/crewai-tools/src/crewai_tools/tools/duckduckgo_search_tool/duckduckgo_search_tool.pylib/crewai-tools/tests/tools/duckduckgo_search_tool_test.py
Address review feedback: - test_ddg_tool_search now asserts the exact ddgs.text() call arguments (region, safesearch, max_results) via assert_called_once_with, so a parameter-wiring regression is caught. - Add docstrings to DuckDuckGoSearchTool.__init__ and _run.
What
Adds a new
DuckDuckGoSearchTooltocrewai-tools, providing web search via DuckDuckGo powered by theddgspackage.Why
Every existing web-search tool in
crewai-toolsrequires an API key —BraveSearchTool,SerpApiGoogleSearchTool,SerperDevTool,SerplyWebSearchTool,EXASearchTool,TavilySearchTool,LinkupSearchTool. There is currently no keyless web-search option.DuckDuckGo requires no API key, which makes it a convenient, zero-configuration default for giving an agent internet-search capability — ideal for quick prototypes, examples, and first-time users. It's a common default across other agent frameworks, so it fills a real gap here.
Implementation
Mirrors the existing search tools (e.g.
TavilySearchTool,BraveSearchTool) and follows the repo conventions:lib/crewai-tools/src/crewai_tools/tools/duckduckgo_search_tool/(duckduckgo_search_tool.py,__init__.py,README.md)args_schema(DuckDuckGoSearchToolSchema) with a described, requiredsearch_queryn_results,region, andsafesearchddgswith a clear, actionable install messagepackage_dependenciesviaField(default_factory=...)Title / Link / Snippetoutput, ready for an agent transcriptcrewai_toolsandcrewai_tools.tools(import +__all__)ddgsregistered as an optional extra inlib/crewai-tools/pyproject.toml, withuv.lockupdated accordinglyUsage
Install the optional dependency:
uv add crewai-tools --extra ddgs # or: pip install ddgsTesting
lib/crewai-tools/tests/tools/duckduckgo_search_tool_test.py— 5 tests covering initialization, missing-query handling, the happy path, no-results, and error handling. All mocked; no network calls in CI.ruff checkandruff format --checkpass,mypypasses,pytestpasses, and a real live search returns correctly-formatted results.