AWS Builder Center
Building AI Agents from Zero to Hero

Building AI Agents from Zero to Hero

Built AI agents with Strands SDK, Bedrock, and MCP from simple chatbots to an AWS Study Buddy with memory and tools.

Sharing, Learning, Growing Together

šŸ“– Introduction

I participated in the AWSUG MDU April Skill Sprint, a 5-challenge journey to build AI agents from scratch using the Strands Agents SDK and Amazon Bedrock. Each challenge builds on the previous one, going from a simple chatbot to a full MCP-powered study assistant.
Here's my complete journey through all 5 challenges, including the code, architecture, errors I hit, and how I solved them.

šŸ—ŗļø The Journey at a Glance


Challenge 1: My First Agent ⭐

Goal

Create a basic conversational agent using Strands SDK with a local LLM (Ollama).

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from strands import Agent
from strands.models.ollama import OllamaModel

model = OllamaModel(
host="http://localhost:11434",
model_id="llama3.2:3b"
)

agent = Agent(
model=model,
system_prompt="You are a helpful AI assistant.",
tools=[]
)

response = agent("What is Python?")
print(f"šŸ¤– Agent: {response}")

What I Learned

  • Strands SDK makes agent creation dead simple — 3 lines of config
  • OllamaModel connects to a local LLM (no cloud needed for testing)
  • The system_prompt shapes the agent's personality
  • tools=[] means no tools — just pure conversation

Output

1
2
šŸ¤– Agent: Python is a high-level, interpreted programming language known for
its simplicity and readability...

Challenge 2: Adding Tools ⭐⭐

Goal

Give the agent superpowers with custom tools using Amazon Nova Pro via Bedrock.

Architecture

Key Code — The @tool Decorator

1
2
3
4
5
6
7
8
9
10
11
12
13
from strands.tools import tool

@tool
def weather(city: str) -\> str:
"""Get the current weather for a given city.

Args:
city: The name of the city to get weather for.
"""

response = requests.get(f"https://wttr.in/{city}?format=j1")
data = response.json()
current = data["current_condition"][0]
return f"Weather in {city}: {current['weatherDesc'][0]['value']}, {current['temp_C']}°C"

How Tool Selection Works

The agent reads the docstring and type annotations to understand:
  1. When to use the tool (docstring describes purpose)
  2. What to pass (type annotations define parameters)
  3. What to expect back (return type)
You can see the agent's reasoning in \<thinking\> tags:
1
2
3
\<thinking\> I need to use the 'weather' tool to get the current weather
conditions in Chennai. \</thinking\>
Tool #1: weather

Output

1
2
3
4
5
🧮 Math: 42 * 17 = 714
šŸŒ¤ļø Weather: Chennai is thundery, 35°C, humidity 51%
šŸŽ‚ Age: Someone born Jan 15, 2000 is 26 years old
šŸ“ Conversion: 100 km = 62.14 miles
šŸŒ”ļø Multi-tool: Delhi is 44°C (111.2°F) — used weather + unit_converter!

Key Insight

The agent chains multiple tools automatically. When asked "weather in Delhi in Fahrenheit", it calls weather first, then unit_converter without being told to.

Challenge 3: Persistent Memory ⭐⭐

Goal

Give the agent memory that survives program restarts using FAISS vector store.

Architecture

The Two Types of Memory

TypePersists?How
Conversation HistoryāŒMessages sent to model each turn
mem0_memory + FAISSāœ…Vectors stored on disk

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
os.environ["MEM0_LLM_MODEL"] = "amazon.nova-pro-v1:0"
os.environ["MEM0_EMBEDDER_MODEL"] = "amazon.titan-embed-text-v2:0"
os.environ["BYPASS_TOOL_CONSENT"] = "true"

from strands_tools import mem0_memory

agent = Agent(model=model, tools=[mem0_memory])

# Store
agent.tool.mem0_memory(action="store", content="My name is DD", user_id="dd_user")

# Retrieve
agent.tool.mem0_memory(action="retrieve", query="name", user_id="dd_user")

šŸ”„ Errors I Hit (and Fixes)

ErrorRoot CauseFix
No module named 'strands_tools'Wrong package namepip install strands-agents-tools
No module named 'mem0'Missing dependencypip install "strands-agents-tools[mem0-memory]"
No module named 'opensearchpy'Missing dependencypip install opensearch-py
Unsupported vector store provider: faissmem0ai too new (1.x)pip install "mem0ai\>=0.1.99,\<1.0.0"
Unsupported embedding provider: aws_bedrockSame version issueSame fix as above
Authorization errormem0 defaults to Claude Haiku internallySet MEM0_LLM_MODEL env var

output :

Critical Lesson

> mem0ai must be \<1.0.0. Version 1.x removed FAISS and aws_bedrock support. Always install with: pip install "strands-agents-tools[mem0-memory]"

Challenge 4: The Full Agent ⭐⭐⭐

Goal

Combine everything – tools, memory and streaming – in an interactive chat.

Architecture

Key Innovation: Simple File-Based Memory

After fighting mem0ai version issues, I replaced it with a dead-simple JSON approach:
1
2
3
4
5
6
7
8
9
10
11
12
13
@tool
def remember(key: str, value: str) -\> str:
"""Store info to persistent memory."""
memory = json.load(open("memory.json"))
memory[key] = value
json.dump(memory, open("memory.json", "w"))
return f"āœ… Stored: {key} = {value}"

@tool
def recall(key: str) -\> str:
"""Retrieve from memory. Use key='all' for everything."""
memory = json.load(open("memory.json"))
return memory.get(key, "Not found")
Why this works better:
  • Zero dependencies
  • No version conflicts
  • No auth errors
  • Always works
  • Persists across restarts

Streaming Callback

1
2
3
4
5
def streaming_callback(**kwargs):
if "data" in kwargs:
print(kwargs["data"], end="", flush=True)
if "current_tool_use" in kwargs and kwargs["current_tool_use"].get("name"):
print(f"\nšŸ”§ Using tool: {kwargs['current_tool_use']['name']}")
> Important: Use **kwargs, NOT positional arguments. The SDK passes everything as keyword args.

output

Demo Conversation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
šŸ§‘ You: Remember my name is DD and I'm from Tanjore
šŸ¤– Buddy: šŸ”§ Using tool: remember
šŸ”§ Using tool: remember
āœ… Stored! Your name is DD and you're from Tanjore! šŸ›ļø

šŸ§‘ You: What's the weather in my city?
šŸ¤– Buddy: šŸ”§ Using tool: recall
šŸ”§ Using tool: weather
Weather in Tanjore: Sunny, 38°C ā˜€ļø

šŸ§‘ You: How old is someone born 2002-03-15? Also 365 * 24?
šŸ¤– Buddy: šŸ”§ Using tool: age_calculator
šŸ”§ Using tool: calculator
24 years old! And 365 Ɨ 24 = 8,760 hours in a year! 🧮

Challenge 5: MCP-Powered Innovation

Goal

Build a creative agent using MCP (Model Context Protocol) that solves a real problem.

My Project: AWS Study Buddy šŸ“š

An interactive AWS tutor that:
  • šŸ“š Searches real AWS documentation via MCP
  • 🧠 Remembers what you've studied
  • šŸ“ Quizzes you on learned topics
  • 🧮 Calculates AWS costs
  • ⚔ Streams responses in real time

Architecture

MCP Connection Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from strands.tools.mcp import MCPClient
from mcp import StdioServerParameters, stdio_client

aws_docs_mcp = MCPClient(
lambda: stdio_client(
StdioServerParameters(
command="uvx",
args=["awslabs.aws-documentation-mcp-server@latest"],
env={**os.environ, "FASTMCP_LOG_LEVEL": "ERROR"}
)
)
)

with aws_docs_mcp:
mcp_tools = aws_docs_mcp.list_tools_sync()
all_tools = mcp_tools + [save_note, get_notes, record_quiz_score, calculator]
agent = Agent(model=model, tools=all_tools)

Learning Flow

output :

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
šŸ“š AWS Study Buddy — Learn AWS with Official Docs + Memory

šŸ§‘ You: Explain Lambda in simple terms

šŸ¤– Study Buddy:
šŸ”§ Using tool: search_documentation
šŸ”§ Using tool: read_documentation

AWS Lambda is serverless compute! ⚔
• Run code without managing servers
• Pay only for compute time used
• Triggers: API Gateway, S3, DynamoDB, etc.
• Max execution: 15 minutes
• Supports Python, Node.js, Java, Go, .NET

šŸ”§ Using tool: save_note
šŸ“ Note saved for 'Lambda'! You've now studied 1 topic.

šŸ§‘ You: How much for 1 million Lambda requests?

šŸ¤– Study Buddy:
šŸ”§ Using tool: calculator
Lambda pricing: $0.20 per 1M requests
1,000,000 Ɨ $0.0000002 = $0.20/month šŸ’°
Plus compute time based on memory and duration.

šŸ§‘ You: Quiz me!

šŸ¤– Study Buddy:
šŸ”§ Using tool: get_notes

Q1: What's the max execution time for Lambda?
Q2: Name 3 Lambda triggers.
Q3: Do you manage servers with Lambda?

šŸ“Š Summary: Skills Progression

ChallengeNew SkillModelKey Feature
1Agent basicsOllama (local)System prompt, simple Q&A
2@tool decoratorNova Pro (Bedrock)Weather, age calc, unit converter
3Persistent memoryNova Pro + Titan EmbedFAISS/JSON storage across sessions
4Streaming + multi-toolNova ProCallback handler, interactive chat
5MCP protocolNova Pro + MCP ServerAWS docs search, quiz system

šŸ”„ Top Errors & Lessons

#ErrorLesson
1pip install strands-tools failsPackage is strands-agents-tools
2mem0ai 1.x breaks everythingPin to \<1.0.0 or use [mem0-memory] extra
3streaming_callback(event) failsUse **kwargs not positional args
4mem0 authorization errorsSet MEM0_LLM_MODEL env var or use simple JSON memory
5MCP server not foundInstall uv for uvx command

šŸ› ļø Full Tech Stack

ComponentTechnology
Agent FrameworkStrands Agents SDK
LLMAmazon Nova Pro v1 (Bedrock)
EmbeddingsAmazon Titan Embed Text V2
MCP Serverawslabs.aws-documentation-mcp-server
MemoryJSON file (simple) / FAISS (advanced)
Weather APIwttr.in
LanguagePython 3.12
Regionus-east-1

šŸ—ļø Project Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
may-skill-sprint/
ā”œā”€ā”€ challenge-1-first-agent/
│ └── starter.py # Basic agent with Ollama
ā”œā”€ā”€ challenge-2-tools/
│ └── starter.py # Custom tools + Bedrock
ā”œā”€ā”€ challenge-3-memory/
│ ā”œā”€ā”€ starter.py # mem0_memory + FAISS
│ ā”œā”€ā”€ verify_memory.py # Persistence test
│ └── debug_mem0.py # Debug script
ā”œā”€ā”€ challenge-4-full-agent/
│ ā”œā”€ā”€ starter.py # Full interactive agent
│ └── memory.json # Persistent memory store
ā”œā”€ā”€ challenge-5-mcp-agent/
ā”œā”€ā”€ starter.py # MCP-powered study buddy
└── study_notes.json # Study progress

šŸŽ“ Final Thoughts

Building AI agents is easier than you think but getting the dependencies right is harder than you'd expect. The Strands SDK itself is elegant and simple. The pain points are all in the ecosystem (version conflicts, auth issues, package naming).
My biggest takeaway: start simple, add complexity gradually. Challenge 1 → 5 is the perfect progression. And when something complex breaks (like mem0), don't be afraid to replace it with something simpler that just works.
The future of AI development is agents + tools + memory + MCP. This sprint gave me hands-on experience with all four.

Built with ā¤ļø by DD for the AWSUG MDU April Skill Sprint 2026
Thank you for taking the time to read my article! If you found it helpful, feel free to like, share, and drop your thoughts in the comments; I’d love to hear from you.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article