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
@tooldecorator 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
-
uvinstalled - 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?")
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
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,
)
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())
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:
Input:
text: str
Output:
int
The function simply splits text into words and returns the total count.
Example:
word_count("hello world")
Returns:
2
🧠 Why the Docstring Matters
One of the most important parts of a custom tool is the docstring.
"""Count words in text."""
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]
)
Here we provide the tool to the agent.
tools=[word_count]
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?"
)
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
Or:
python agent.py
📊 Example Interaction
User
How many words are in this sentence?
Agent Reasoning
This task requires counting words.
A tool named word_count is available.
I'll use the tool.
Tool Execution
word_count(
"How many words are in this sentence?"
)
Result:
7
Agent Response
There are 7 words in the sentence.
🔍 How Tool Calling Works
When a user sends a request:
User Prompt
↓
Agent Analysis
↓
Tool Selection
↓
Tool Execution
↓
Result Returned
↓
Final Response
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
Date Tool
@tool
def current_date() -> str:
...
Database Tool
@tool
def get_customer(customer_id: str):
...
AWS Tool
@tool
def list_s3_buckets():
...
This is the foundation of building production-ready AI agents.
🎯 Key Takeaways
- Tools extend the capabilities of AI agents
- The
@tooldecorator 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)