DEV Community

Cover image for # 🌐 Lab 04B: Building a Web Search Tool for AI Agents | Strands Agentic AI
Jamal
Jamal

Posted on

# 🌐 Lab 04B: Building a Web Search Tool for AI Agents | Strands Agentic AI

Large Language Models are powerful, but they have one major limitation:

They only know what they were trained on.

What if you want your AI agent to access the latest information from the web?

That's where custom tools become incredibly useful.

In this lab, you'll build a custom web search tool using DuckDuckGo Search (DDGS) and connect it to a Strands Agent. This allows the agent to retrieve up-to-date information and provide responses based on real-time search results.

By the end of this lab, you'll have a Recipe Assistant that can search the web for recipes and cooking information.


🚀 What You'll Learn

In this lab, you'll learn:

  • How to create a custom web search tool
  • How to integrate third-party Python libraries into Strands tools
  • How agents use tools to access live information
  • How to handle API errors gracefully
  • How to build a specialized AI assistant

🤖 Why Web Search Matters

LLMs have knowledge cutoffs.

For example, an LLM may know:

✅ How recipes work

✅ Common cooking techniques

✅ Popular dishes

But it may not know:

❌ Latest recipes

❌ Current food trends

❌ Newly published cooking content

❌ Real-time information

A web search tool solves this problem.

User Question
      ↓
Agent Analysis
      ↓
Web Search Tool
      ↓
Search Results
      ↓
Agent Response
Enter fullscreen mode Exit fullscreen mode

Instead of relying only on training data, the agent can retrieve fresh information from the web.


🛠️ Prerequisites

Before starting, make sure you have:

  • Python 3.10+
  • AWS Account
  • Amazon Bedrock access
  • AWS credentials configured
  • uv installed
  • DDGS package installed

Install DDGS:

pip install ddgs
Enter fullscreen mode Exit fullscreen mode

📜 The Script

Let's start by looking at the complete example.

from strands import Agent, tool
from ddgs import DDGS
from ddgs.exceptions import RatelimitException
import logging
from strands.models.bedrock import BedrockModel

# Configure logging
logging.getLogger("strands").setLevel(logging.INFO)

# Define a websearch tool
@tool
def websearch(
    keywords: str,
    region: str = "us-en",
    max_results: int | None = None
) -> str:
    """Search the web to get updated information."""

    try:
        results = DDGS().text(
            keywords,
            region=region,
            max_results=max_results
        )

        return results if results else "No results found."

    except RatelimitException:
        return "RatelimitException: Please try again after a short delay."

    except Exception as e:
        return f"Exception: {e}"


# Bedrock
bedrock_model = BedrockModel(
    model_id="<YOUR_MODEL_ID>",
    region_name="eu-west-2",
    temperature=0.3,
)

# Create a recipe assistant agent
recipe_agent = Agent(
    model=bedrock_model,
    system_prompt="""
    You are RecipeBot, a helpful cooking assistant.
    Help users find recipes based on ingredients and answer cooking questions.
    Use the websearch tool to find recipes when users mention ingredients or to look up cooking information.
    """,
    tools=[websearch],
)

response = recipe_agent(
    "Suggest a recipe with chicken and capsicum."
)

print(f"Metrics : {response.metrics}")
Enter fullscreen mode Exit fullscreen mode

Now let's break it down step by step.


⚙️ Step 1: Import Dependencies

from strands import Agent, tool
from ddgs import DDGS
from ddgs.exceptions import RatelimitException
import logging
from strands.models.bedrock import BedrockModel
Enter fullscreen mode Exit fullscreen mode

We're importing:

Import Purpose
Agent Creates the AI agent
tool Converts a Python function into a Strands tool
DDGS Performs DuckDuckGo searches
RatelimitException Handles search rate limits
logging Displays runtime information
BedrockModel Connects to Amazon Bedrock

⚙️ Step 2: Configure Logging

logging.getLogger("strands").setLevel(logging.INFO)
Enter fullscreen mode Exit fullscreen mode

Logging helps us understand what the agent is doing during execution.

Example output:

INFO | strands.agent | Processing user request
INFO | strands.tools | Executing websearch tool
Enter fullscreen mode Exit fullscreen mode

During development, logs provide valuable visibility into agent behavior.


⚙️ Step 3: Create the Web Search Tool

@tool
def websearch(
    keywords: str,
    region: str = "us-en",
    max_results: int | None = None
) -> str:
Enter fullscreen mode Exit fullscreen mode

This function becomes a Strands tool through the @tool decorator.

The agent can now call this function whenever it needs information from the web.

Parameters

Parameter Description
keywords Search query
region Search region
max_results Maximum number of results

Example:

websearch(
    "chicken capsicum recipe"
)
Enter fullscreen mode Exit fullscreen mode

⚙️ Step 4: Search Using DDGS

results = DDGS().text(
    keywords,
    region=region,
    max_results=max_results
)
Enter fullscreen mode Exit fullscreen mode

DDGS performs a DuckDuckGo search and returns matching results.

These results are then sent back to the agent.

The agent uses them to generate an informed response.


⚙️ Step 5: Handle Errors Gracefully

Production-ready tools should always handle failures.

Rate Limit Handling

except RatelimitException:
Enter fullscreen mode Exit fullscreen mode

If too many requests are made, DDGS may temporarily block searches.

Instead of crashing, the tool returns a helpful message.

General Error Handling

except Exception as e:
Enter fullscreen mode Exit fullscreen mode

Unexpected failures are captured and returned safely.

This improves reliability and user experience.


🧠 Why the Docstring Matters

"""Search the web to get updated information."""
Enter fullscreen mode Exit fullscreen mode

The docstring helps the LLM understand:

  • What the tool does
  • When it should use it
  • What kind of information it can retrieve

Think of the docstring as instructions for the AI.

A clear description leads to better tool selection.


⚙️ Step 6: Configure Amazon Bedrock

bedrock_model = BedrockModel(
    model_id="<YOUR_MODEL_ID>",
    region_name="eu-west-2",
    temperature=0.3,
)
Enter fullscreen mode Exit fullscreen mode

This model powers the reasoning and decision-making process.

The agent determines:

  • Whether web search is needed
  • What search query to generate
  • How to interpret results
  • How to respond to users

⚙️ Step 7: Create a Specialized Recipe Agent

recipe_agent = Agent(
    model=bedrock_model,
    system_prompt="""
    You are RecipeBot...
    """,
    tools=[websearch],
)
Enter fullscreen mode Exit fullscreen mode

This agent has a clear responsibility:

Find recipes
Answer cooking questions
Search the web when necessary
Enter fullscreen mode Exit fullscreen mode

The system prompt defines the agent's personality and capabilities.


⚙️ Step 8: Ask the Agent a Question

response = recipe_agent(
    "Suggest a recipe with chicken and capsicum."
)
Enter fullscreen mode Exit fullscreen mode

The agent receives the request and reasons about how to solve it.

Because recipe information may require fresh data, it can choose to invoke the web search tool.


▶️ Run the Agent

Execute the script:

python agent.py
Enter fullscreen mode Exit fullscreen mode

Or:

uv run labs/04b-websearch-tool/agent.py
Enter fullscreen mode Exit fullscreen mode

📊 Example Interaction

User

Suggest a recipe with chicken and capsicum.
Enter fullscreen mode Exit fullscreen mode

Agent Workflow

User Request
      ↓
Agent Analysis
      ↓
Web Search Tool
      ↓
Recipe Search Results
      ↓
Response Generation
Enter fullscreen mode Exit fullscreen mode

Agent Response

You can make a Chicken Capsicum Stir Fry.

Ingredients:
- Chicken breast
- Capsicum
- Onion
- Garlic
- Soy sauce

Instructions:
1. Sauté garlic and onion.
2. Add chicken and cook thoroughly.
3. Add sliced capsicum.
4. Stir in soy sauce.
5. Serve hot with rice.
Enter fullscreen mode Exit fullscreen mode

Actual responses may vary depending on model and search results.


📈 Understanding Agent Metrics

At the end of the script:

print(f"Metrics : {response.metrics}")
Enter fullscreen mode Exit fullscreen mode

Metrics help monitor agent performance.

You may see information such as:

Input Tokens
Output Tokens
Latency
Tool Calls
Enter fullscreen mode Exit fullscreen mode

These metrics become extremely useful when optimizing production agents.


🔍 How Tool Calling Works

When a user asks a question:

User Prompt
      ↓
Agent Reasoning
      ↓
Tool Selection
      ↓
Web Search
      ↓
Results Returned
      ↓
Final Response
Enter fullscreen mode Exit fullscreen mode

The agent automatically decides whether the tool should be used.

You don't need to manually call the function.

This is what makes agentic systems powerful.


💡 Real-World Use Cases

The same approach can be used for:

News Assistant

Search latest headlines
Enter fullscreen mode Exit fullscreen mode

Research Assistant

Search technical documentation
Enter fullscreen mode Exit fullscreen mode

Travel Assistant

Search destinations and hotels
Enter fullscreen mode Exit fullscreen mode

Shopping Assistant

Search products and reviews
Enter fullscreen mode Exit fullscreen mode

Support Assistant

Search knowledge bases
Enter fullscreen mode Exit fullscreen mode

A web search tool unlocks countless possibilities.


🎯 Key Takeaways

  • Custom tools allow agents to access live information
  • DDGS provides a simple web search capability
  • Error handling improves reliability
  • Docstrings help the LLM understand tool functionality
  • Agents automatically decide when to invoke tools
  • Tool-based architectures make AI assistants far more useful

📚 Source Code

GitHub Repository:

https://github.com/d3vjamal/strands-agents-labs


🚀 Previous Lab

Lab 04A: Creating Your First Custom Tool | Strands Agentic AI

Top comments (0)