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

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:
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
-
Register agent on Agentverse:
https://agentverse.ai/agents/details/agent1qgfnnx5nwxspd55e3zjwtra2gegdt77edf254k47tkcl0nc9dv2zvj6jjhj/profile -
Access via Agentverse Chat:
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

-
User submits query -
uAgent routes request to MCP server -
MCP invokes appropriate Brave API tool -
Results formatted and returned
5. Practical Applications
5.1 Conversational AI Enhancement

-
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
-
ASI:One Models: https://asi1.ai/ -
Agentverse Platform: https://agentverse.ai/ -
uAgents Documentation: https://uagents.fetch.ai/docs -
Brave Search API: https://brave.com/search/api/
Start by experimenting with search parameters, then extend functionality with custom filters. Join the Fetch.ai Developer Community to collaborate on agent development.