DEV Community

Cover image for # 🛠️ Lab 04A: Creating Your First Custom Tool | Strands Agentic AI
Jamal
Jamal

Posted on

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

AI agents become truly powerful when they can perform actions beyond generating text.

While large language models are great at reasoning, tools allow them to interact with the real world, process data, and execute custom logic.

In this lab, you'll learn how to create your first custom tool using the @tool decorator in Strands and expose it to an AI agent.

By the end, your agent will be able to count words using your own Python function.


🚀 What You'll Learn

In this lab, you'll learn:

  • What tools are in Strands Agents
  • How the @tool decorator works
  • How to create your own custom tool
  • How agents automatically discover and use tools
  • How tool docstrings help the LLM understand capabilities

🤖 Why Custom Tools Matter

Without tools, an AI agent can only generate responses based on its training and reasoning.

With tools, agents can:

  • Query databases
  • Call APIs
  • Read files
  • Write files
  • Perform calculations
  • Execute business logic

Think of a language model as a brain.

Tools are its hands.

The brain can think about counting words, but a tool can perform the counting accurately and consistently.


🛠️ Prerequisites

Before starting, make sure you have:

  • Python 3.10+
  • AWS Account
  • Amazon Bedrock access
  • Access to a model such as amazon.nova-2-lite-v1
  • AWS credentials configured
  • uv installed
  • Completed Lab 01 and Lab 02

📜 The Script

Let's start by looking at the complete example.

# Just an example of using creating your custom tool

from strands import Agent, tool
from strands.models.bedrock import BedrockModel

# Bedrock
bedrock_model = BedrockModel(
    # Set your preferred model ID here
    model_id="<YOUR_MODEL_ID>",
    region_name="eu-west-2",
    temperature=0.3,
)


@tool
def word_count(text: str) -> int:
    """Count words in text.

    This docstring is used by the LLM to understand the tool's purpose.
    """
    return len(text.split())


agent = Agent(model=bedrock_model, tools=[word_count])

response = agent("How many words are in this sentence?")
Enter fullscreen mode Exit fullscreen mode

Now let's break it down step by step.


⚙️ Step 1: Import Required Modules

from strands import Agent, tool
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
BedrockModel Connects the agent to Amazon Bedrock

The tool decorator is the star of this lab.

It allows Strands to expose a Python function to the language model.


⚙️ Step 2: 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 creates the model that powers the agent.

Parameters

Parameter Description
model_id Bedrock model identifier
region_name AWS region
temperature Controls creativity and randomness

For utility tools, lower temperatures often produce more predictable results.


⚙️ Step 3: Create a Custom Tool

@tool
def word_count(text: str) -> int:
    """Count words in text."""
    return len(text.split())
Enter fullscreen mode Exit fullscreen mode

This is where the magic happens.

The @tool decorator transforms a normal Python function into a tool that the agent can invoke.

Function Breakdown

def word_count(text: str) -> int:
Enter fullscreen mode Exit fullscreen mode

Input:

text: str
Enter fullscreen mode Exit fullscreen mode

Output:

int
Enter fullscreen mode Exit fullscreen mode

The function simply splits text into words and returns the total count.

Example:

word_count("hello world")
Enter fullscreen mode Exit fullscreen mode

Returns:

2
Enter fullscreen mode Exit fullscreen mode

🧠 Why the Docstring Matters

One of the most important parts of a custom tool is the docstring.

"""Count words in text."""
Enter fullscreen mode Exit fullscreen mode

The LLM reads this description to understand:

  • What the tool does
  • When it should use it
  • What inputs it expects

Think of the docstring as instructions for the AI.

A clear docstring helps the model choose the correct tool at the correct time.


⚙️ Step 4: Register the Tool

agent = Agent(
    model=bedrock_model,
    tools=[word_count]
)
Enter fullscreen mode Exit fullscreen mode

Here we provide the tool to the agent.

tools=[word_count]
Enter fullscreen mode Exit fullscreen mode

The agent now knows:

  • The tool exists
  • What it does
  • How to call it

From this point forward, the model can decide when to use it.


⚙️ Step 5: Ask the Agent a Question

response = agent(
    "How many words are in this sentence?"
)
Enter fullscreen mode Exit fullscreen mode

When the agent receives this request, it reasons about the task.

The model recognizes that counting words is exactly what the word_count tool is designed to do.

Instead of guessing, it invokes the tool and uses the result.


▶️ Run the Agent

Execute the script:

uv run labs/04a-custom-tool/agent.py
Enter fullscreen mode Exit fullscreen mode

Or:

python agent.py
Enter fullscreen mode Exit fullscreen mode

📊 Example Interaction

User

How many words are in this sentence?
Enter fullscreen mode Exit fullscreen mode

Agent Reasoning

This task requires counting words.
A tool named word_count is available.
I'll use the tool.
Enter fullscreen mode Exit fullscreen mode

Tool Execution

word_count(
    "How many words are in this sentence?"
)
Enter fullscreen mode Exit fullscreen mode

Result:

7
Enter fullscreen mode Exit fullscreen mode

Agent Response

There are 7 words in the sentence.
Enter fullscreen mode Exit fullscreen mode

🔍 How Tool Calling Works

When a user sends a request:

User Prompt
     ↓
Agent Analysis
     ↓
Tool Selection
     ↓
Tool Execution
     ↓
Result Returned
     ↓
Final Response
Enter fullscreen mode Exit fullscreen mode

The agent automatically decides whether a tool should be used.

You don't explicitly call the function yourself.

The LLM handles that decision-making process.


💡 Real-World Tool Examples

The same pattern can be used to build more powerful tools:

Calculator Tool

@tool
def add(a: int, b: int) -> int:
    return a + b
Enter fullscreen mode Exit fullscreen mode

Date Tool

@tool
def current_date() -> str:
    ...
Enter fullscreen mode Exit fullscreen mode

Database Tool

@tool
def get_customer(customer_id: str):
    ...
Enter fullscreen mode Exit fullscreen mode

AWS Tool

@tool
def list_s3_buckets():
    ...
Enter fullscreen mode Exit fullscreen mode

This is the foundation of building production-ready AI agents.


🎯 Key Takeaways

  • Tools extend the capabilities of AI agents
  • The @tool decorator converts Python functions into agent tools
  • Docstrings help the LLM understand tool functionality
  • Agents automatically decide when to use tools
  • Custom tools are the foundation of real-world agent workflows

📚 Source Code

Lab Source:

https://github.com/d3vjamal/strands-agents-labs/tree/master/labs/04a-custom-tool


🚀 Next Lab

In the next lab, we'll create more advanced tools with parameters and learn how agents can chain multiple tool calls together to solve complex tasks.

Top comments (0)