Skip to main content

Command Palette

Search for a command to run...

AWS Strands SDK Masterclass: Introduction to Building AI Agents

Updated
6 min read
AWS Strands SDK Masterclass: Introduction to Building AI Agents

Published: June 6, 2025

In today's rapidly evolving AI landscape, building intelligent agents that can reason, use tools, and solve complex problems has become a critical capability for developers. AWS has introduced the Strands Agents SDK, a powerful Python framework that simplifies the creation of AI agents with advanced capabilities. In this first post of our 12-part series, we'll explore what Strands is, why it matters, and how to get started with your first agent.

What is AWS Strands?

Strands Agents SDK is an open-source Python framework developed by AWS that enables developers to build, customize, and deploy AI agents. These agents can leverage foundation models like Claude, use tools to interact with external systems, and maintain context across interactions.

At its core, Strands provides a clean, intuitive API for defining agents with three key components:

  1. Models: The foundation models that power your agent's reasoning

  2. Tools: Functions that extend your agent's capabilities

  3. Prompts: Instructions that guide your agent's behavior

Why Strands Matters

Before Strands, building AI agents required complex orchestration code, managing model interactions, and handling tool execution flows. Strands abstracts away this complexity, allowing developers to focus on defining agent capabilities rather than implementation details.

Key benefits include:

  • Simplified Agent Creation: Define agents in just a few lines of code

  • Tool Flexibility: Easily extend agents with custom tools

  • Model Provider Agnostic: Works with multiple model providers

  • Streaming Support: Real-time streaming of agent responses

  • Production Ready: Built for production use cases

Getting Started with Strands

Let's create our first agent using Strands. First, you'll need to install the SDK:

pip install strands strands-agents strands-agents-tools

Now, let's create a simple agent with login that can perform calculations and tell the current time:

import logging
from strands import Agent
from strands_tools import calculator, current_time

# Enables Strands debug log level
logging.getLogger("strands").setLevel(logging.DEBUG)

# Sets the logging format and streams logs to stderr
logging.basicConfig(
    format="%(levelname)s | %(name)s | %(message)s",
    handlers=[logging.StreamHandler()]
)

# Define our agent
agent = Agent(
    # Use Claude 3.7 Sonnet from Amazon Bedrock
    model="us.anthropic.claude-3-7-sonnet-20250219-v1:0",
    # Add calculator and current_time tools
    tools=[calculator, current_time],
    # Set the system prompt
    system_prompt="You are a helpful assistant that specializes in mathematics and time."
)

# Ask the agent a question
response = agent("What is 1234 * 5678 and what time is it now?")

# Print the response
print(response.message)

When you run this code, the agent will:

  1. Process the user's question

  2. Recognize that it needs to perform a calculation

  3. Use the calculator tool to compute 1234 * 5678

  4. Use the current_time tool to get the current time

  5. Formulate a response that includes both results

Response

DEBUG | strands.models.bedrock | config=<{'model_id': 'us.anthropic.claude-3-7-sonnet-20250219-v1:0'}> | initializing
DEBUG | strands.tools.registry | tool_name=<calculator>, tool_type=<function>, is_dynamic=<False> | registering tool
DEBUG | strands.tools.registry | tool_name=<current_time>, tool_type=<function>, is_dynamic=<False> | registering tool
DEBUG | strands.tools.registry | tools_dir=</Users/jayyanar/blogs-strands/tools> | tools directory not found
DEBUG | strands.tools.registry | tool_modules=<[]> | discovered
DEBUG | strands.tools.registry | tool_count=<0>, success_count=<0> | finished loading tools
DEBUG | strands.tools.registry | tools_dir=</Users/jayyanar/blogs-strands/tools> | tools directory not found
DEBUG | strands.tools.registry | getting tool configurations
DEBUG | strands.tools.registry | tool_name=<calculator> | loaded tool config
DEBUG | strands.tools.registry | tool_name=<current_time> | loaded tool config
DEBUG | strands.tools.registry | tool_count=<2> | tools configured
DEBUG | strands.tools.registry | getting tool configurations
DEBUG | strands.tools.registry | tool_name=<calculator> | loaded tool config
DEBUG | strands.tools.registry | tool_name=<current_time> | loaded tool config
DEBUG | strands.tools.registry | tool_count=<2> | tools configured
DEBUG | strands.event_loop.streaming | model=<<strands.models.bedrock.BedrockModel object at 0x10639f010>> | streaming messages
DEBUG | strands.types.models.model | formatting request
DEBUG | strands.types.models.model | invoking model
DEBUG | strands.types.models.model | got response from model
I'll calculate that multiplication for you and tell you the current time.

First
DEBUG | strands.types.models.model | finished streaming response from model
DEBUG | strands.tools.executor | tool_count=<1>, tool_executor=<ThreadPoolExecutorWrapper> | executing tools in parallel
DEBUG | strands.handlers.tool_handler | tool=<{'toolUseId': 'tooluse_-8WO095dTgSQrV1uuOfdtw', 'name': 'calculator', 'input': {'expression': '1234 * 5678'}}> | invoking
DEBUG | strands.tools.executor | tool_count=<1> | submitted tasks to parallel executor
, let me calculate 1234 * 5678:
Tool #3: calculator
╭────────────────────────────────────────────── Calculation Result ───────────────────────────────────────────────╮
│                                                                                                                 │
│  ╭───────────┬─────────────────────╮                                                                            │
│  │ Operation │ Evaluate Expression │                                                                            │
│  │ Input     │ 1234 * 5678         │                                                                            │
│  │ Result    │ 7006652             │                                                                            │
│  ╰───────────┴─────────────────────╯                                                                            │
│                                                                                                                 │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
DEBUG | strands.event_loop.streaming | model=<<strands.models.bedrock.BedrockModel object at 0x10639f010>> | streaming messages
DEBUG | strands.types.models.model | formatting request
DEBUG | strands.types.models.model | invoking model
DEBUG | strands.types.models.model | got response from model
DEBUG | strands.types.models.model | finished streaming response from model
DEBUG | strands.handlers.tool_handler | tool=<{'toolUseId': 'tooluse_f9jfxZNRQCyswGER0z8RYA', 'name': 'current_time', 'input': {}}> | invoking
DEBUG | strands.event_loop.streaming | model=<<strands.models.bedrock.BedrockModel object at 0x10639f010>> | streaming messages
DEBUG | strands.types.models.model | formatting request
DEBUG | strands.types.models.model | invoking model
DEBUG | strands.types.models.model | got response from model
Now, let me check the current time:
Tool #4: current_time
1234 * 5678 = 7,006,652

The current time is 2025-06-06T12:26:12.985335+00:00 (which is June 6, 2025, at 12:26:12 PM UTC
DEBUG | strands.types.models.model | finished streaming response from model
DEBUG | strands.agent.conversation_manager.sliding_window_conversation_manager | window_size=<6>, message_count=<40> | skipping context reduction
).{'role': 'assistant', 'content': [{'text': '1234 * 5678 = 7,006,652\n\nThe current time is 2025-06-06T12:26:12.985335+00:00 (which is June 6, 2025, at 12:26:12 PM UTC).'}]}

The Agent Execution Flow

Understanding how Strands agents work internally helps you build more effective agents. Here's the typical execution flow:

Project Structure

When building more complex agents, it's helpful to organize your code. Here's a recommended project structure:

my_agent/
├── __init__.py
├── agent.py
├── tools/
│   ├── __init__.py
│   ├── custom_tools.py
├── config.py
└── requirements.txt

Next Steps

In this introduction, we've covered the basics of Strands Agents SDK and created our first simple agent. In the next post, we'll dive deeper into models and model providers, exploring how to use different foundation models with your Strands agents.

Stay tuned for the complete series:

  1. Introduction to Building AI Agents (this post)

  2. Models and Model Providers

  3. Building Custom Tools

  4. Advanced Tool Patterns

  5. Streaming and Real-time Responses

  6. Agent Memory and Context Management

  7. Multi-agent Systems with Strands

  8. RAG and Knowledge Integration

  9. Debugging and Testing Agents

  10. Production Deployment Patterns

  11. Performance Optimization

  12. Building Complex Agent Applications

Resources


This post is part of the AWS Strands SDK Masterclass series, where we explore building intelligent AI agents using AWS Strands Agents SDK.

More from this blog

D

DataOps Labs

77 posts

Stay updated on the latest in AI/ML, Cloud, DevOps, MLOps, Generative AI and cutting-edge techniques with this continuous learning free newsletters.