Source code for orka.tools.search_tools
# OrKa: Orchestrator Kit Agents
# Copyright © 2025 Marco Somma
#
# This file is part of OrKa – https://github.com/marcosomma/orka-resoning
#
# Licensed under the Apache License, Version 2.0 (Apache 2.0).
# You may not use this file for commercial purposes without explicit permission.
#
# Full license: https://www.apache.org/licenses/LICENSE-2.0
# For commercial use, contact: marcosomma.work@gmail.com
#
# Required attribution: OrKa by Marco Somma – https://github.com/marcosomma/orka-resoning
"""
Search Tools Module
=================
This module implements web search tools for the OrKa framework.
These tools provide capabilities to search the web using various search engines.
The search tools in this module include:
- GoogleSearchTool: Searches the web using Google Custom Search API
- DuckDuckGoTool: Searches the web using DuckDuckGo search engine
These tools can be used within workflows to retrieve real-time information
from the web, enabling agents to access up-to-date knowledge that might not
be present in their training data.
"""
import logging
# Optional import for DuckDuckGo search
try:
from duckduckgo_search import DDGS
HAS_DUCKDUCKGO = True
except ImportError:
DDGS = None
HAS_DUCKDUCKGO = False
from .base_tool import BaseTool
logger = logging.getLogger(__name__)
[docs]
class DuckDuckGoTool(BaseTool):
"""
A tool that performs web searches using the DuckDuckGo search engine.
Returns search result snippets from the top results.
"""
[docs]
def run(self, input_data):
"""
Perform a DuckDuckGo search and return result snippets.
Args:
input_data (dict): Input containing search query.
Returns:
list: List of search result snippets.
"""
# Check if DuckDuckGo is available
if not HAS_DUCKDUCKGO:
return [
"DuckDuckGo search not available - duckduckgo_search package not installed"
]
# Get query - prioritize formatted_prompt from orchestrator, then fallback to other sources
query = ""
if isinstance(input_data, dict):
# First check if orchestrator has provided a formatted_prompt via payload
if "formatted_prompt" in input_data:
query = input_data["formatted_prompt"]
# Then check if we have a prompt that was rendered by orchestrator
elif hasattr(self, "formatted_prompt"):
query = self.formatted_prompt
# Fall back to the raw prompt (which should be rendered by orchestrator)
elif hasattr(self, "prompt") and self.prompt:
query = self.prompt
# Finally, try to get from input data
else:
query = input_data.get("input") or input_data.get("query") or ""
else:
query = input_data
if not query:
return ["No query provided"]
# Convert to string if needed
query = str(query)
try:
# Execute search and get top 5 results
with DDGS() as ddgs:
results = [r["body"] for r in ddgs.text(query, max_results=5)]
return results
except Exception as e:
logger.error(f"DuckDuckGo search failed: {str(e)}")
return [f"DuckDuckGo search failed: {str(e)}"]