Building an Intelligent Search Agent with Brave Search API and uAgents Framework

Introduction: When AI Agents Meet Powerful Search Capabilities

In today’s information-rich world, efficiently retrieving accurate data is paramount. This guide explores how to combine Brave Search API‘s robust capabilities with the uAgents framework to create an AI-powered search agent. This solution delivers real-time web and local business search functionality through Python, ideal for applications requiring dynamic information retrieval.

Core Value: This implementation enables developers to build intelligent agents for real-time web content discovery and local business searches, suitable for chatbots, research tools, and location-based services.


1. Technology Ecosystem Breakdown

1.1 Fetch.ai Platform Overview

Fetch.ai provides a decentralized AI ecosystem with core components:

  • uAgents Framework: Lightweight framework for agent development with built-in identity management
  • Agentverse: Open marketplace for agent discovery and deployment
  • ASI:One LLM: Web3-native language model for agentic workflows
  • Chat Protocol: Standardized communication protocol for agent conversations

1.2 Brave Search API Advantages

Brave Search offers unique benefits:

  • Independent search index
  • Privacy-focused design (no user tracking)
  • Dual web/local search capabilities
  • Custom filters (time, safety level, content type)

2. System Architecture & Design Goals

System Architecture

2.1 Core Functionality

Search Type Capabilities Use Cases
Web Search Web pages, news, videos with filters Research, trend monitoring
Local Search Business details, addresses, ratings Restaurant discovery, services

Intelligent Fallback: Automatically switches to web search when local results are unavailable.


3. Implementation Walkthrough

3.1 Environment Setup

Prerequisites:

  1. Brave Search API Key (Get here)
  2. ASI:One API Key (Get here)
  3. Python 3.8+

Install dependencies:

pip install uagents uagents-adapter requests python-dotenv  

3.2 Agent Configuration & MCP Connection

Create agent_setup.py:

from uagents_adapter import MCPServerAdapter  
from server import mcp  
from uagents import Agent  

# Initialize adapter  
mcp_adapter = MCPServerAdapter(  
    mcp_server=mcp,  
    asi1_api_key="YOUR_ASI1_KEY",  # Replace with actual key  
    model="asi1-mini"  
)  

# Configure agent  
agent = Agent()  
for protocol in mcp_adapter.protocols:  
    agent.include(protocol, publish_manifest=True)  

if __name__ == "__main__":  
    mcp_adapter.run(agent)  

Key functions:

  • Creates agent instance
  • Connects to MCP server
  • Integrates ASI:One for tool selection
  • Publishes to Agentverse

3.3 MCP Server Implementation

Create server.py:

import os  
import time  
import requests  
from mcp.server.fastmcp import FastMCP  
from dotenv import load_dotenv  

# Load environment variables  
load_dotenv()  
BRAVE_API_KEY = os.getenv("BRAVE_API_KEY")  

# Rate limiting configuration  
RATE_LIMIT = {"per_second": 1, "per_month": 15000}  
request_count = {"second": 0, "month": 0, "last_reset": time.time()}  

def check_rate_limit():  
    current_time = time.time()  
    if current_time - request_count["last_reset"] > 1:  
        request_count["second"] = 0  
        request_count["last_reset"] = current_time  
    if (request_count["second"] >= RATE_LIMIT["per_second"] or  
        request_count["month"] >= RATE_LIMIT["per_month"]):  
        raise ValueError("Rate limit exceeded")  
    request_count["second"] += 1  
    request_count["month"] += 1  

mcp = FastMCP("BraveSearch")  
3.3.1 Web Search Implementation
@mcp.tool()  
def brave_web_search(  
    query: str,  
    count: int = 10,  
    offset: int = 0,  
    result_type: str = "all",  
    safety_level: str = "moderate",  
    freshness: str = "all"  
) -> str:  
    check_rate_limit()  
    # Validate parameters  
    if len(query) > 400 or not 1 <= count <= 20 or offset not in range(10):  
        raise ValueError("Invalid parameters")  

    # Configure API request  
    url = "https://api.search.brave.com/res/v1/web/search"  
    params = {"q": query, "count": count, "offset": offset, "safesearch": safety_level}  
    if result_type != "all": params["result_filter"] = result_type  
    if freshness != "all": params["freshness"] = freshness  

    headers = {"Accept": "application/json", "X-Subscription-Token": BRAVE_API_KEY}  
    response = requests.get(url, params=params, headers=headers)  
    
    # Process results  
    data = response.json()  
    results = []  
    for rtype in ["web", "news", "videos"]:  
        if result_type in ["all", rtype] and data.get(rtype, {}).get("results"):  
            for item in data[rtype]["results"]:  
                result_entry = f"Title: {item['title']}\nDescription: {item['description']}\nURL: {item['url']}"  
                if item.get('published'):  
                    result_entry += f"\nPublished: {item['published']}"  
                results.append(result_entry)  
    return "\n\n".join(results) or "No results found"  

Key Parameters:

  • result_type: web/news/videos/all
  • safety_level: strict/moderate/off
  • freshness: day/week/month/year/all
3.3.2 Local Search Implementation
@mcp.tool()  
def brave_local_search(query: str, count: int = 5, safety_level: str = "moderate") -> str:  
    check_rate_limit()  
    # Step 1: Get location IDs  
    search_url = "https://api.search.brave.com/res/v1/web/search"  
    params = {  
        "q": query,  
        "result_filter": "locations",  
        "count": count,  
        "safesearch": safety_level  
    }  
    headers = {"Accept": "application/json", "X-Subscription-Token": BRAVE_API_KEY}  
    response = requests.get(search_url, params=params, headers=headers)  
    
    # Handle no results  
    data = response.json()  
    location_ids = [item["id"] for item in data.get("locations", {}).get("results", [])]  
    if not location_ids:  
        return brave_web_search(query, count, 0, "all", safety_level, "all")  

    # Step 2: Fetch POI details  
    poi_url = "https://api.search.brave.com/res/v1/local/pois"  
    poi_response = requests.get(poi_url, params={"ids": location_ids}, headers=headers)  

    # Step 3: Get descriptions  
    desc_url = "https://api.search.brave.com/res/v1/local/descriptions"  
    desc_response = requests.get(desc_url, params={"ids": location_ids}, headers=headers)  
    desc_data = desc_response.json().get("descriptions", {}) if desc_response.ok else {}  

    # Format results  
    results = []  
    for location in poi_response.json().get("results", []):  
        address_components = [  
            location.get("address", {}).get("streetAddress", ""),  
            location.get("address", {}).get("addressLocality", ""),  
            location.get("address", {}).get("addressRegion", ""),  
            location.get("address", {}).get("postalCode", "")  
        ]  
        address = ", ".join(filter(None, address_components))  
        rating_value = location.get('rating', {}).get('ratingValue', 'Not rated')  
        rating_count = location.get('rating', {}).get('ratingCount', 0)  
        
        result_entry = (  
            f"Name: {location.get('name', 'Unknown')}\n"  
            f"Address: {address or 'Unavailable'}\n"  
            f"Phone: {location.get('phone', 'Unavailable')}\n"  
            f"Rating: {rating_value} ({rating_count} reviews)\n"  
            f"Description: {desc_data.get(location.get('id'), 'No description')}"  
        )  
        results.append(result_entry)  
    return "\n---\n".join(results) or "No local results"  

3.4 Launching the MCP Server

if __name__ == "__main__":  
    mcp.run(transport="stdio")  

4. Deployment & Practical Usage

4.1 Agent Deployment

  1. Register agent on Agentverse:
    https://agentverse.ai/agents/details/agent1qgfnnx5nwxspd55e3zjwtra2gegdt77edf254k47tkcl0nc9dv2zvj6jjhj/profile

  2. Access via Agentverse Chat:
    Chat Interface

4.2 Search Examples

Web Search:

brave_web_search(  
    query="AI breakthroughs 2025",  
    count=5,  
    result_type="news",  
    freshness="pm",  # Past month  
    safety_level="strict"  
)  

Sample Output:

Title: Top 5 AI Predictions for 2025  
Description: Experts forecast transformative AI applications in healthcare...  
URL: https://example.com/ai-predictions  
Published: 2025-03-15T08:30:00Z  

Local Search:

brave_local_search("sushi restaurants San Francisco", count=3)  

Sample Output:

Name: Sushi Paradise  
Address: 123 Main St, San Francisco, CA 94105  
Phone: (555) 123-4567  
Rating: 4.5 (128 reviews)  
Description: Authentic Edo-style sushi with daily fresh catches...  
---  
Name: Tokyo Sushi Bar  
Address: 456 Elm St, San Francisco, CA 94110  
Phone: (555) 987-6543  
Rating: 4.2 (95 reviews)  
Description: Modern twist on traditional sushi...  

4.3 System Workflow

Workflow Diagram
  1. User submits query
  2. uAgent routes request to MCP server
  3. MCP invokes appropriate Brave API tool
  4. Results formatted and returned

5. Practical Applications

5.1 Conversational AI Enhancement

Chatbot Integration
  • Real-time Q&A about current events
  • Location-based recommendations
  • Research assistance

5.2 Location-Based Services

  • Travel concierge tools
  • Accessibility-focused business discovery
  • Emergency service locators

5.3 Research & Analysis

  • Academic trend monitoring
  • Competitive intelligence gathering
  • Multi-source data aggregation

6. Optimization Strategies

6.1 Rate Limit Management

Brave API constraints:

  • 1 request/second
  • 15,000 requests/month

Optimization Tips:

  • Implement query caching
  • Distribute requests evenly
  • Set usage alerts at 80% capacity

6.2 Error Handling Enhancements

Add:

  • API response validation
  • Network timeout retries
  • Fallback search sources
  • Detailed error logging

6.3 Search Refinements

Filter sponsored content:

if r.get('extra', {}).get('sponsored', False):  
    continue  # Skip paid results  

7. Conclusion & Next Steps

Key Achievements:

  • Modular MCP-based architecture
  • Dual-mode search with automatic fallback
  • Lightweight Python implementation

Future Enhancements:

  • Multilingual search support
  • Personalized recommendation engine
  • Browser extension development
  • User preference profiles

Resources & Community

Start by experimenting with search parameters, then extend functionality with custom filters. Join the Fetch.ai Developer Community to collaborate on agent development.