import requests from smolagents import Tool import os import json class ScaleSerpSearchTool(Tool): """ A reliable web search tool using the Scale SERP API. This tool is chosen for its high reliability and accessible free tier when other search providers fail due to quota or instability. """ name = "scaleserp_search" description = "Use the reliable Scale SERP API to fetch current and general knowledge from Google Search results. Requires an API key." inputs = { "query": {"type": "string", "description": "The search term to look up."} } output_type = "string" def __init__(self, **kwargs): super().__init__(**kwargs) # Retrieve API key from environment variables self.api_key = os.getenv("SCALESERP_API_KEY") self.endpoint = "https://api.scaleserp.com/search" if not self.api_key: raise ValueError("SCALESERP_API_KEY secret not found. You need a key from the Scale SERP free tier.") def forward(self, query: str) -> str: """ Executes a Scale SERP search query and formats the top results (up to 3). Args: query: The search term provided by the agent. Returns: A formatted string of search results, or an error message. """ print(f"Executing Scale SERP Search for: '{query}'") params = { "api_key": self.api_key, "q": query, "num": 3, # Request up to 3 results "gl": "us" # Limit results to US region for consistency } try: # Make the API request response = requests.get(self.endpoint, params=params, timeout=10) response.raise_for_status() data = response.json() # Extract the organic results organic_results = data.get('organic_results', []) if not organic_results: # Check for a knowledge panel or featured snippet as a fallback featured_snippet = data.get('knowledge_graph', {}).get('description') if featured_snippet: return f"RESULT 1 (Featured Snippet): '{query}'\nCONTENT: {featured_snippet}\nSOURCE: Knowledge Panel" # If nothing useful is found: return "XX record info: No results found." search_results = [] # Process the top 3 organic results for i, item in enumerate(organic_results[:3]): search_results.append( f"RESULT {i+1}: '{item.get('title', 'N/A')}'\n" f"CONTENT: {item.get('snippet', 'No snippet available.')}\n" f"SOURCE: {item.get('url', 'N/A')}" ) # Join the results with a clear separator return "\n\n---SEPARATOR---\n\n".join(search_results) except requests.exceptions.RequestException as e: return f"Error during Scale SERP API Request: {e}" except Exception as e: return f"Error processing Scale SERP results: {e}"