DEV Community

Jyoti Thakur
Jyoti Thakur

Posted on

Building AI Agents with Strands Agents: My Hands-On Experience from the AWS BeSA Workshop

Introduction

Artificial Intelligence is evolving rapidly, and one of the most exciting developments is the rise of AI Agent — systems that can reason, plan, and take actions autonomously.

Recently, I participated in the BeSA Workshop, where we explored how to build intelligent agents using the Strands Agents framework. The workshop focused on hands-on labs that demonstrated how AI agents can process tasks, interact with tools, and perform multi-step reasoning.

In this article, I will walk through my experience completing the workshop labs and explain how each lab helped me understand the concepts behind building AI agents.

By the end of this article, you will have a clear understanding of:

  • What is Agentic AI
  • How Strands Agents work
  • How to build and run AI agents step-by-step
  • Key insights from each workshop lab

What is Agentic AI?

Agentic AI refers to artificial intelligence systems that can autonomously plan and execute tasks to achieve a goal.

Unlike traditional AI models that simply respond to prompts, AI agents can:

  • Understand complex instructions
  • Break tasks into smaller steps
  • Use tools or external systems
  • Make decisions during execution

This approach allows AI systems to behave more like intelligent assistants capable of performing real tasks rather than just generating text responses.

What Are Strands Agents?

Strands Agents is a framework designed to help developers build AI-powered agents capable of reasoning and performing tasks.

Instead of manually managing prompts and logic, the framework allows developers to define:

  • Agents
  • Tools
  • Workflows
  • Task execution logic

This makes it easier to design AI systems that can solve problems step-by-step and interact with external services.

Workshop Overview

The BeSA workshop consisted of multiple hands-on labs designed to gradually introduce the concepts of building AI agents.

Each lab focused on a specific capability, starting from basic agent creation and moving toward more advanced agent workflows.

Disclaimer

This article reflects my experience participating in the BeSA Workshop. While I have summarized and explained the labs in my own words, some technical explanations and descriptions were guided with external assistance to ensure clarity. The concepts, architecture diagrams, and lab exercises are based on official AWS BeSA Workshop materials.

The labs covered:

  • Agent initialization
  • Prompt handling
  • Tool integration
  • Multi-step task execution
  • Advanced agent workflows

Table of Contents

Lab 1: Building Your First Strands Agent

Objective

The goal of this lab was to understand the basic structure of the Strands Agents framework and how AI agents are initialized.

Architecture


The architecture shows how the agent interacts with the language model to process user requests.
The workshop begins inside JupyterLab, where the first notebook introduces the most fundamental concept of the Strands SDK: the Agent primitive.

What makes this part exciting is how quickly you can build a working AI agent.

With just a few lines of Python, you can create an agent powered by Claude Sonnet 4 running on Amazon Bedrock.

from strands import Agent
agent = Agent(
    system_prompt="You are a helpful assistant that provides concise responses."
)

agent("Tell me a joke.")
Enter fullscreen mode Exit fullscreen mode

That’s all it takes.

  • No infrastructure setup
  • No API Gateway configuration
  • No complex deployment steps

By default, the Strands SDK connects to Amazon Bedrock and automatically uses Claude Sonnet 4 in the AWS region configured in your account.

Adding Tools to Your Agent

Once the basic agent is running, the lab walks through how to extend the agent’s capabilities using tools.

There are two types of tools you can add:

1️⃣ Built-in Tools

The strands-agents-tools package provides ready-to-use utilities like:

  • Calculator
  • Other helper tools

These tools allow your agent to perform tasks beyond simple text generation.

2️⃣ Custom Tools

You can also create your own tools using the @tool decorator.

This allows the AI agent to call your Python functions whenever it needs them.

Calling Tools Directly

The notebook also demonstrates that tools can be triggered directly from code.

For example:

agent.tool.calculator(...)
Enter fullscreen mode Exit fullscreen mode

This gives developers flexibility to use tools either through the agent’s reasoning process or directly in the application code.

Implementation

In this lab, we initialized our first agent and explored how the framework handles prompts and responses.

The notebook demonstrates how an agent receives input, processes it using the underlying model, and returns a generated output.

Sample Execution

Lab 1 Sample Execution 1

Lab 1 Sample Execution 2

Lab 1 Sample Execution 3

Key Learning

Lab-1 demonstrates how the Strands SDK makes it incredibly simple to build AI agents.

Instead of worrying about infrastructure or complex setup, developers can focus on:

  • Building intelligent workflows
  • Adding useful tools
  • Designing agent behavior

This simplicity is what makes the framework powerful for rapidly building AI-driven applications.

Lab 2: Running Agents Locally with Ollama

Objective

The goal of this lab was to demonstrate that not every AI agent needs to rely on cloud services.
In some situations—such as offline environments, privacy-sensitive tasks, or cost-efficient development—running models locally can be a better option.

In this lab, we replace Amazon Bedrock with Ollama, allowing the agent to run entirely on a local machine.

Architecture

The Strands SDK supports multiple model providers through a flexible model abstraction layer. This means developers can easily switch between different model backends without changing the overall agent logic.

In this lab, the agent is configured to use a local model through the OllamaModel provider.

Implementation

from strands.models.ollama import OllamaModel
Enter fullscreen mode Exit fullscreen mode
ollama_model = OllamaModel(
    model_id="llama3.2:3b",
    host="http://localhost:11434",
    temperature=0.7,
)

agent = Agent(model=ollama_model, tools=[file_read, file_write, list_directory])
Enter fullscreen mode Exit fullscreen mode

Here’s what’s happening:

  • The agent connects to a locally running Ollama server.
  • The model used is Llama 3.2 with 3B parameters.
  • The agent is equipped with tools that allow it to interact with the local file system.

These tools include:

  • file_read → read files (including PDFs)
  • file_write → create or modify files
  • list_directory → explore folders

With these capabilities, the agent becomes a local file operations assistant. It can perform tasks such as:

  • Summarizing documents like a shareholder letter
  • Generating a project README
  • Creating or editing files automatically
  • Navigating directories on your system

The most interesting part is that everything happens locally, meaning no data is sent to external APIs or cloud services.

Sample Execution

Lab 2 Sample Execution 1

Lab 2 Sample Execution 2

Key Learning

One of the biggest advantages of the Strands SDK is model portability. Thanks to its provider abstraction layer, switching between models is very simple. For example, you can move from Claude on Amazon Bedrock to Llama running locally on Ollama with only a small code change. This flexibility allows developers to run agents in the cloud or locally depending on needs such as privacy, offline usage, or cost-efficient development.

Lab 3: Integrating AI Agents with AWS Services

Objective

The objective of this lab was to build a Restaurant Assistant that can answer menu-related questions and manage table reservations.

To achieve this, the agent integrates with two AWS managed services:

  • Amazon Bedrock Knowledge Bases for retrieving information from restaurant menus
  • Amazon DynamoDB for handling reservation data

This lab demonstrates how agents can interact with external systems using tools.

Architecture

1️⃣ Agent Layer
The assistant is built using the Strands Agents SDK with a model running on Amazon Bedrock.
The agent receives user requests and decides which tool to use.

2️⃣ Knowledge Retrieval (RAG)
For menu-related questions, the agent uses the retrieve tool connected to Amazon Bedrock Knowledge Bases to fetch relevant menu information.

3️⃣ Reservation Management
Reservation operations are handled through custom tools that interact with Amazon DynamoDB to create, retrieve, or delete bookings.

Implementation

The assistant is created using the Strands Agents SDK, and multiple tools are added to extend its capabilities.

The lab introduces three different ways to define tools:

1️⃣ Inline Tool Definition

Using the @tool decorator directly within the agent code.

2️⃣ Standalone Tool Module

Defining the tool in a separate file and importing it into the project.

3️⃣ TOOL_SPEC Schema

Using a structured dictionary similar to the Amazon Bedrock Converse API schema.

This method allows precise control over:

  • Required and optional parameters
  • Success and error response structures

Example agent setup:

from strands_tools import current_time, retrieve
from strands import Agent
Enter fullscreen mode Exit fullscreen mode
agent = Agent(
    model=model,
    system_prompt=system_prompt,
    tools=[retrieve, current_time, get_booking_details, create_booking, delete_booking],
)
Enter fullscreen mode Exit fullscreen mode

One particularly useful tool is retrieve, which automatically connects to the Amazon Bedrock Knowledge Base when the KNOWLEDGE_BASE_ID environment variable is configured.

This means the agent can perform Retrieval-Augmented Generation (RAG) without building a custom retrieval pipeline.

Sample Execution

Lab 3 Sample Execution 1

Lab 3 Sample Execution 2

Lab 3 Sample Execution 3

Key Learning

Lab 3 shows how the Strands Agents SDK integrates with AWS services using tools and boto3. The built-in retrieve tool enables quick RAG with Amazon Bedrock Knowledge Bases, while custom tools allow interaction with Amazon DynamoDB. The TOOL_SPEC approach adds structured, production-ready tool definitions. Together, these features enable building AI assistants that work with real-time data and external systems.

Lab 4: Integrating MCP Servers with Strands Agents

Objective

In this lab, we explore how Model Context Protocol (MCP) servers can extend Strands Agents by exposing external tools.

Architecture

In this setup, the Strands Agents SDK connects to an MCP server that exposes tools.

The flow works like this:

User Query → Agent → MCP Server → External Tool → Agent Response

The MCP server can run:

  • Locally using stdio
  • Remotely using HTTP-based MCP servers

This makes it easy for agents to access tools such as documentation, APIs, or databases.

Implementation

In the lab, an MCP client connects to a server that provides AWS documentation tools.

from strands.tools.mcp import MCPClient
from mcp import StdioServerParameters, stdio_client
Enter fullscreen mode Exit fullscreen mode
mcp_client = MCPClient(
    lambda: stdio_client(
        StdioServerParameters(command="uvx", args=["awslabs.aws-documentation-mcp-server@latest"])
    )
)

with mcp_client:
    tools = mcp_client.list_tools_sync()
    agent = Agent(tools=tools)
    agent("What is Amazon Bedrock's pricing model?")
Enter fullscreen mode Exit fullscreen mode

The lab also demonstrates:

  • Creating custom MCP servers using FastMCP
  • Direct tool execution with call_tool_sync
  • Timeout configuration
  • Connecting multiple MCP servers to a single agent

Sample Execution

Lab 4 Sample Execution 1
Lab 4 Sample Execution 2

Key Learning

MCP enables a plug-and-play tool ecosystem for AI agents. Any MCP-compatible server—such as documentation services, APIs, or databases—can instantly become a tool for the agent without writing extra integration code. Multiple MCP servers can also be connected to one agent for more powerful workflows.

Lab 5: Streaming Agent Responses

Objective

The goal of this lab was to demonstrate how AI agents can stream responses in real time instead of waiting for the full output. This is useful for building interactive applications such as dashboards, APIs, or chat interfaces.

Architecture

In a streaming architecture, the Strands Agents SDK sends response events continuously as the model processes a request.

The flow looks like this:

User Request → Agent → Streaming Events → Application UI/API

Each event contains structured information such as:

  • message output
  • tool usage
  • intermediate data
  • final result

This allows applications to display partial responses, progress updates, and tool activity in real time.

Implementation

The lab demonstrates two ways to stream agent responses.

1️⃣ Async Streaming (stream_async)

Best suited for async frameworks like FastAPI.

async for event in agent.stream_async("Calculate 2+2"):
    if "data" in event:
        print(event["data"])
    if "current_tool_use" in event:
        print(f"Tool: {event['current_tool_use']['name']}")
Enter fullscreen mode Exit fullscreen mode

This approach lets developers process events as they arrive and build real-time streaming applications.

2️⃣ Callback Handlers

For synchronous environments such as scripts or CLI applications, a callback_handler function can be used to capture events as they occur without using async code.

Sample Execution

Lab 5 Sample Execution 1

Lab 5 Sample Execution 2

Lab 5 Sample Execution 3

Key Learning

Lab-5 shows how agents can stream responses using async iterators or callback handlers. The stream_async method with FastAPI is ideal for production APIs, while callback handlers provide a simple option for scripts and command-line tools. Both methods give developers real-time visibility into agent responses and tool usage.

Lab 6: Securing Agents with Guardrails

Objective

The objective of this lab was to build a safe and compliant AI assistant by integrating Amazon Bedrock Guardrails with the Strands Agents SDK.
The guardrails ensure the agent cannot respond to harmful or restricted requests such as financial advice, hate speech, or sharing sensitive data.

Architecture

In this setup, guardrails are placed between the user input and the AI model.

User Request → Guardrails Check → AI Model → Safe Response

The guardrails filter or block unsafe content before the model generates a response. If a policy is violated, the system returns a predefined blocked message instead of the model output.

Implementation

The guardrails are attached directly to the Amazon Bedrock model configuration.

bedrock_model = BedrockModel(
    model_id="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
    guardrail_id=guardrail_id,
    guardrail_version="DRAFT",
    guardrail_trace="enabled",
    guardrail_redact_input=True,
    guardrail_redact_input_message="Guardrail Intervened and Redacted"
)

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

The guardrails apply multiple safety controls, including:

  • Topic policies → block restricted topics like financial advice
  • Content policies → filter hate, violence, or harmful prompts
  • Word policies → block specific words or phrases
  • Blocked messaging → show a custom message when a rule is triggered

A useful feature is automatic input redaction, where blocked user input is replaced with a neutral placeholder in the conversation history.

Sample Execution

Lab 6 Sample Execution 1

Lab 6 Sample Execution 2

Lab 6 Sample Execution 3

Key Learning

Lab-6 shows how Amazon Bedrock Guardrails can protect AI applications by enforcing safety policies at the model level. With a simple BedrockModel configuration, the entire agent gains enterprise-grade security and content filtering, making it safer for real-world applications like customer support systems.

Lab 7: Adding Persistent Memory to Agents

Objective

The objective of this lab was to enable long-term memory for agents so they can remember user preferences across conversations. This is achieved using Mem0, integrated as a tool in the Strands Agents SDK.

Architecture

In this setup, the agent connects to a memory layer that stores user information.

User Interaction → Agent → Memory Tool → Memory Database → Personalized Response

The agent can store and retrieve user preferences, enabling more personalized interactions over time.

Implementation

The memory functionality is added using the built-in mem0_memory tool.

from strands_tools import mem0_memory
Enter fullscreen mode Exit fullscreen mode
memory_agent = Agent(
    system_prompt=SYSTEM_PROMPT,
    tools=[mem0_memory, websearch],
)

# Store a preference
memory_agent.tool.mem0_memory(action="store", content="I prefer tea over coffee.", user_id=USER_ID)

# Retrieve it later
memory_agent.tool.mem0_memory(action="retrieve", query="drink preferences", user_id=USER_ID)
Enter fullscreen mode Exit fullscreen mode

The memory backend can be configured using different storage options:

  • Amazon OpenSearch Serverless for scalable cloud deployments
  • FAISS for local development
  • Mem0 Platform API for a fully managed service

Sample Execution

Lab 7 Sample Execution 1

Lab 7 Sample Execution 2

Lab 7 Sample Execution 3

Key Learning

Lab-7 shows how agents can maintain persistent memory using the mem0_memory tool. It supports three main actions—store, retrieve, and list—allowing agents to remember user preferences without building a custom database. When combined with Amazon OpenSearch Serverless, it provides a scalable and serverless memory layer for personalized AI applications.

Lab 8: Observability and Evaluation for Agents

Objective

The objective of this lab was to add observability and evaluation to an AI agent so developers can monitor its behavior and measure response quality. This is achieved using Langfuse for tracing and RAGAS for automated evaluation.

Architecture

The architecture introduces a monitoring layer around the agent.

User Query → Agent → Trace Data → Langfuse → Evaluation (RAGAS) → Score Results

Every agent action—such as tool calls, reasoning steps, and model responses—is captured as a trace. These traces are then evaluated using metrics to measure the quality and relevance of the agent’s output.

Implementation

Tracing is enabled using OpenTelemetry by setting environment variables:

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = langfuse_endpoint
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {auth_token}"
Enter fullscreen mode Exit fullscreen mode
agent = Agent(
    model=model,
    tools=[retrieve, current_time, ...],
    trace_attributes={
        "session.id": "abc-1234",
        "user.id": "user@domain.com",
        "langfuse.tags": ["Agent-SDK", "Observability"]
    }
)
Enter fullscreen mode Exit fullscreen mode

With this setup, the Strands Agents automatically sends traces to Langfuse without modifying the agent code.

For evaluation,RAGAS metrics analyze the responses using an LLM judge such as Amazon Nova Premier.

The system evaluates responses using metrics like:

  • AspectCritic → checks if the response meets specific criteria
  • RubricsScore → evaluates response quality using multi-level scoring
  • Context Relevance → checks if retrieved documents match the query
  • Response Groundedness → verifies if the answer is based on retrieved context

Evaluation scores are then written back to the Langfuse trace:

langfuse.create_score(
    trace_id=trace_id,
    name="rag_context_relevance",
    value=0.92
)
Enter fullscreen mode Exit fullscreen mode

Sample Execution

Lab 8 Sample Execution 1

Lab 8 Sample Execution 2

Lab 8 Sample Execution 3

Key Learning

Lab-8 demonstrates how to build a complete monitoring and evaluation pipeline for AI agents. By combining Langfuse for tracing and RAGAS for response evaluation, developers can track not only what the agent did, but also how well it performed, creating a powerful feedback loop for improving AI applications.

Conclusion

The BeSA Workshop provided a hands-on introduction to building intelligent AI agents using the Strands Agents SDK.

Throughout the labs, we explored how agents can be progressively enhanced with powerful capabilities such as tool integration, local model execution, AWS service connectivity, streaming responses, safety guardrails, persistent memory, and observability.

Each lab demonstrated how modern AI systems are moving beyond simple prompt-response models toward agentic architectures that can reason, interact with tools, and perform real-world tasks.

By combining Strands Agents with AWS services like Amazon Bedrock, DynamoDB, and OpenSearch Serverless, developers can build scalable AI applications that are both powerful and production-ready.

The workshop clearly shows that the future of AI development lies in building intelligent agents that can plan, act, and improve continuously through feedback and monitoring.

What This Workshop Taught Me

This workshop helped me understand how AI is evolving from simple prompt-based systems to agents that can actually perform tasks. Instead of just generating responses, agents can now use tools, access external data, and make decisions step by step.

One thing that stood out to me was how easy the Strands AgentsSDK makes it to build these systems. Starting with a simple agent, we gradually added capabilities like tool integration, streaming responses, guardrails, memory, and observability.

Overall, the workshop gave me a clearer picture of how developers can build more practical and reliable AI applications by combining agent frameworks with cloud services. It was a great hands-on experience that made the concepts of agentic AI much easier to understand.

Acknowledgement

Note: All architecture diagrams and lab materials referenced in this article are from the BeSA Workshop provided by AWS. I sincerely thank the BeSA team for designing these learning labs and enabling hands-on experience with Strands Agents and AWS services.

Top comments (0)