Web Search Agent#
This example demonstrates how to create an agent that can search the web for information. We’ll use a simple web search API to enable the agent to find up-to-date information.
Implementing a Web Search Tool#
First, let’s create a web search tool using a hypothetical search API:
from brain.agents.tool import tool
from pydantic import BaseModel, Field
import aiohttp
import os
from typing import List
class SearchResult(BaseModel):
title: str
snippet: str
url: str
class SearchResponse(BaseModel):
results: List[SearchResult]
total_results: int
@tool()
async def search_web(query: str, num_results: int = 5) -> SearchResponse:
"""
Search the web for information
Args:
query: The search query
num_results: Number of results to return (max 10)
Returns:
Search results including titles, snippets, and URLs
"""
# In a real implementation, you would use a search API
# For this example, we'll use a mock implementation
# Limit number of results to a reasonable range
num_results = min(max(1, num_results), 10)
# Example using a hypothetical search API
async with aiohttp.ClientSession() as session:
params = {
"q": query,
"num": num_results,
"api_key": os.environ.get("SEARCH_API_KEY")
}
async with session.get("https://api.example.com/search", params=params) as response:
if response.status != 200:
# For the example, we'll return mock data instead of raising an exception
return SearchResponse(
results=[
SearchResult(
title="Mock search result",
snippet="This is a mock search result since the actual API call failed.",
url="https://example.com"
)
],
total_results=1
)
data = await response.json()
# Transform API response to our model
results = [
SearchResult(
title=item["title"],
snippet=item["snippet"],
url=item["url"]
)
for item in data["items"][:num_results]
]
return SearchResponse(
results=results,
total_results=data["totalResults"]
)
Creating a Mock Implementation#
For testing without a real API, here’s a mock implementation:
@tool()
async def search_web(query: str, num_results: int = 5) -> SearchResponse:
"""
Search the web for information
Args:
query: The search query
num_results: Number of results to return (max 10)
Returns:
Search results including titles, snippets, and URLs
"""
# Limit number of results
num_results = min(max(1, num_results), 10)
# Mock data based on the query
mock_results = []
for i in range(num_results):
mock_results.append(
SearchResult(
title=f"Result {i+1} for {query}",
snippet=f"This is a snippet of information about {query}. This is just mock data for demonstration purposes.",
url=f"https://example.com/result/{i+1}"
)
)
return SearchResponse(
results=mock_results,
total_results=num_results
)
Building the Web Search Agent#
Now, let’s create an agent that uses the web search tool:
import asyncio
import os
from brain.agents.agent import Agent
from brain.agents.llm.openai import OpenAIBaseLLM
from brain.agents.callback import callback
@callback("message_stream.assistant")
async def stream_to_console(agent, event, stream):
print("\nAssistant: ", end="", flush=True)
async for chunk in stream:
if hasattr(chunk, "chunk"):
print(chunk.chunk, end="", flush=True)
async def main():
# Initialize the LLM
llm = OpenAIBaseLLM(
api_key=os.environ.get("OPENAI_API_KEY"),
default_model="gpt-4o" # Using a more capable model for better search queries
)
# Create the agent with the web search tool
agent = Agent(
llm=llm,
tools=[search_web],
instructions="""
You are a helpful web search assistant. You can search the web for information
to answer user questions. Use the search_web tool to find relevant information.
Follow these guidelines:
1. For factual questions, always search the web to provide up-to-date information
2. When searching, use precise and specific search queries
3. Include URLs in your responses so users can verify the information
4. If the search doesn't return useful results, try reformulating the search query
""",
callbacks=[stream_to_console]
)
# Run a conversation loop
print("Web Search Agent (type 'exit' to quit)")
while True:
# Get user input
user_input = input("\nYou: ")
if user_input.lower() == "exit":
break
# Process with the agent
await agent.run(user_input)
print() # Add a newline after the response
if __name__ == "__main__":
asyncio.run(main())
Complete Example#
Here’s the complete example with the mock web search implementation:
import asyncio
import os
from typing import List
from brain.agents.agent import Agent
from brain.agents.callback import callback
from brain.agents.llm.openai import OpenAIBaseLLM
from brain.agents.tool import tool
from pydantic import BaseModel
class SearchResult(BaseModel):
title: str
snippet: str
url: str
class SearchResponse(BaseModel):
results: List[SearchResult]
total_results: int
@tool()
async def search_web(query: str, num_results: int = 5) -> SearchResponse:
"""
Search the web for information
Args:
query: The search query
num_results: Number of results to return (max 10)
Returns:
Search results including titles, snippets, and URLs
"""
# Limit number of results
num_results = min(max(1, num_results), 10)
# Mock data based on the query
mock_results = []
for i in range(num_results):
mock_results.append(
SearchResult(
title=f"Result {i+1} for {query}",
snippet=f"This is a snippet of information about {query}. This is just mock data for demonstration purposes.",
url=f"https://example.com/result/{i+1}"
)
)
return SearchResponse(
results=mock_results,
total_results=num_results
)
@callback("message_stream.assistant")
async def stream_to_console(agent, event, stream):
print("\nAssistant: ", end="", flush=True)
async for chunk in stream:
if hasattr(chunk, "chunk"):
print(chunk.chunk, end="", flush=True)
async def main():
# Initialize the LLM
llm = OpenAIBaseLLM(
api_key=os.environ.get("OPENAI_API_KEY"),
default_model="gpt-4o" # Using a more capable model for better search queries
)
# Create the agent with the web search tool
agent = Agent(
llm=llm,
tools=[search_web],
instructions="""
You are a helpful web search assistant. You can search the web for information
to answer user questions. Use the search_web tool to find relevant information.
Follow these guidelines:
1. For factual questions, always search the web to provide up-to-date information
2. When searching, use precise and specific search queries
3. Include URLs in your responses so users can verify the information
4. If the search doesn't return useful results, try reformulating the search query
""",
callbacks=[stream_to_console]
)
# Run a conversation loop
print("Web Search Agent (type 'exit' to quit)")
while True:
# Get user input
user_input = input("\nYou: ")
if user_input.lower() == "exit":
break
# Process with the agent
await agent.run(user_input)
print() # Add a newline after the response
if __name__ == "__main__":
asyncio.run(main())