Build AI agents from scratch — from a three-line chatbot to a multi-agent system — with the open-source Strands Agents SDK on Amazon Bedrock. Learn custom tools, MCP integration, agent skills, AWS service connections, hierarchical composition, and deployment to AWS Lambda. Domain-neutral by design: the patterns fit any workload, and the "Apply It" tab maps them to AnyCompany Payments.
You start with three lines of agent code and progressively add custom tools, MCP integrations, agent skills, AWS service connections, and multi-agent orchestration. Each lab builds on the last — by Lab 5 you have a hierarchical multi-agent system, and by Lab 6 it runs as a serverless endpoint on AWS Lambda.
🚀 Access the lab environment
This lab runs in a pre-provisioned AWS Workshop Studio environment. One click opens it in your browser with temporary AWS credentials — no personal account or setup required.
How to join. Click Open the workshop to join in one step, or go to catalog.workshops.aws/join and enter the access code above. Sign in with Email one-time passcode when prompted, then follow the lab instructions in Workshop Studio alongside these tabs.
👥 Everyone — read the flow, run the notebooks, watch the agents reason⌨️ Developer detail — the Strands SDK code behind each step
💡The big picture: Strands is model-driven. The foundation model does the reasoning and planning; you supply a system prompt and some tools. There are no chains, graphs, or orchestration DSLs to learn for most use cases — which is exactly why it's a good first agent framework.
🤖
First Agent
Create an agent with a system prompt, add tools with the @tool decorator, and pick a Bedrock model — all in three lines.
🔧
Tools & MCP
Build custom tools with the @tool and TOOL_SPEC patterns, then connect MCP servers for external capabilities like AWS Docs search.
🎯
Agent Skills
Package domain expertise into modular SKILL.md bundles the agent loads on demand — keeping context lean and behaviour specialised.
☁️
AWS Services
Connect the agent to a Bedrock Knowledge Base and DynamoDB — RAG retrieval plus create/read/delete on real AWS infrastructure.
🏗️
Agents as Tools
Compose specialised agents into a hierarchy. An orchestrator routes each query to the right sub-agent.
🚀
Deploy
Package the agent as a container image and deploy it to AWS Lambda with the AWS CDK — a serverless, pay-per-use endpoint.
🧪 How to run this as a workshop activity
This page is a self-guided activity. Work through it in order, tab by tab:
Read the Architecture tab — use the Auto-Tour to see how an agent loops: plan → act → observe.
Skim the Code Deep-Dive — the four core patterns you'll use in every lab.
Follow the Lab Journey — click each of the six labs and run the matching notebook.
Check the Patterns tab — a cheat-sheet of every SDK feature mapped to its lab.
Finish on Apply It — map what you built to a real workload of your own.
Prerequisites. The Workshop Studio environment above comes pre-provisioned — Python, Bedrock model access, the SDK, and the lab notebooks are already set up, so just open it and start. Running it on your own instead? You'll need Python 3.10+, an AWS account with Amazon Bedrock model access (Claude) in your region, pip install strands-agents strands-agents-tools, and the strands-agents/samples01-learn notebooks.
🛡️ Security note. Run every lab in a non-production account. Give each agent's execution role least-privilege access — only the Bedrock models and data it needs — and keep real customer or cardholder data out of sample datasets. Deploying an agent to a production environment is a deliberate, reviewed step, never a default.
The Strands Agents framework
Strands Agents is an open-source SDK (Apache 2.0) that takes a model-driven approach to building agents: you supply a model, some tools, and a prompt — the model does the planning, tool-calling, and reflection. No hand-built workflow graphs for most use cases. It scales from a three-line script to production, and it already runs real AWS services like Amazon Q Developer, AWS Glue, and VPC Reachability Analyzer.
🧬Why the name? Like the two strands of DNA, Strands ties together the two core pieces of an agent — the model and the tools — and lets the model's reasoning drive what happens next.
An agent = model + tools + prompt
🧠
Model
Any model with reasoning + tool-use. Bedrock is the default; you can switch providers by changing one line of code.
🔧
Tools
Any Python function via @tool, built-in tools, or external tools over MCP — the model decides when to call them.
📝
Prompt
A system prompt sets the agent's role and guardrails. That plus the tools is usually all you write.
The agent loop
This is the foundational concept — everything else builds on it. The model reasons, optionally picks a tool, the tool runs, and the result feeds back for another round of reasoning. The cycle repeats until the model has enough to give a final answer. Context accumulates each turn, which is what enables multi-step reasoning.
Model providers — one interface, swap freely
Strands abstracts the provider behind a unified interface, so you can switch models (or mix them) by changing the model object — not your application code. Amazon Bedrock is the default provider.
# Switch providers without touching the rest of your appfrom strands import Agent
from strands.models.bedrock import BedrockModel
from strands.models.openai import OpenAIModel
agent = Agent(model=BedrockModel()) # default: Amazon Bedrock
agent = Agent(model=OpenAIModel(model_id="gpt-4o")) # same Agent API
What the SDK gives you
🔧
Tools & MCP
Python functions via @tool, built-in tools, and any Model Context Protocol server — over stdio or streamable HTTP.
🏗️
Multi-agent
Agents-as-tools, orchestration, and agent-to-agent (A2A) for hierarchical and collaborative systems.
🧠
Sessions & memory
Pluggable session state and memory so agents keep context across turns and requests.
📡
Streaming & observability
Stream tokens and tool events; trace runs and inspect result.metrics for tokens and latency.
🚀
Deploy anywhere
Run locally, in a container, on AWS Lambda (this lab), or on managed runtimes — same agent code.
🐍
Python & TypeScript
Mature Python SDK plus a TypeScript SDK for Node.js and the browser.
📚 Where to get the docs
🔗 Official Strands Agents resources
Everything on this page is distilled from the official documentation. Go straight to the source for API references, guides, and examples.
Tip — search the docs from your agent. Strands ships an MCP documentation server, so your IDE or an agent can query strandsagents.com directly (search + fetch pages) while you build — handy for looking up an API or a model-provider setup without leaving your editor.
Source. Summarised from the Strands Agents documentation and launch announcement at strandsagents.com. Content rephrased for teaching; see the site for authoritative, current details.
The agentic loop
A Strands agent is not a fixed pipeline. The agent sits at the centre and loops: plan → use a tool → observe the result → re-plan. The model decides which tool to call and when — you never hard-code the sequence. Press Auto-Tour, or click any component to explore it.
👤User Request: The user asks a natural-language question — e.g., "Why was my card declined?" The agent interprets the intent and begins its reasoning loop, deciding which tools to call.
🔗 Course tie. This is the reason–act loop from Module 9 (Tools & Agents). The agent observes, plans, acts (calls a tool), and reflects on the result — repeating until it can answer. Strands gives you that loop for free.
Code deep-dive
The core agent is just three lines. Everything else in the labs is variations on four patterns. Here they are, end to end.
🐍Model-driven, not framework-driven. The foundation model handles reasoning and planning. You provide tools and a system prompt — that's it. No chains, no graphs, no orchestration DSL.
1
The simplest agent (three lines)
This is everything needed to create an AI agent with Strands:
# first_agent.pyfrom strands import Agent
agent = Agent(
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
system_prompt="You are a helpful assistant that gives concise answers.",
)
response = agent("Hello! Explain what a chargeback is in one sentence.")
2
A custom tool with the @tool decorator
Any Python function becomes an agent tool with @tool. The docstring becomes the tool's description, and the agent decides when to call it:
# custom_tool.pyfrom strands import Agent, tool
from strands_tools import calculator
@tooldef get_exchange_rate(base: str, quote: str) -> str:
"""Return the exchange rate between two currency codes."""return"1 USD = 0.92 EUR"
agent = Agent(
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
tools=[calculator, get_exchange_rate],
system_prompt="You can do math and look up exchange rates.",
)
response = agent("Convert 250 USD to EUR.")
3
MCP integration (external tools)
Connect to any MCP server and use its tools — no custom tool code needed:
# mcp_agent.pyfrom mcp import StdioServerParameters, stdio_client
from strands import Agent
from strands.tools.mcp import MCPClient
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(model="us.anthropic.claude-sonnet-4-5-20250929-v1:0", tools=tools)
response = agent("What is Amazon Bedrock pricing?")
4
Agents as tools (multi-agent)
Wrap a specialised agent inside a @tool function — an orchestrator then routes to the right specialist:
# orchestrator.py@tooldef research_assistant(query: str) -> str:
"""Answer research questions with cited, factual responses."""
research_agent = Agent(
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
system_prompt="You are a research specialist. Cite sources.",
)
return str(research_agent(query))
orchestrator = Agent(
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
system_prompt="Route research questions to research_assistant, ""account questions to account_assistant.",
tools=[research_assistant, account_assistant],
)
▶⌨️ Developer detail — the TOOL_SPEC alternative
When you need an explicit JSON schema (the Bedrock Converse API format) instead of an inferred one, define a TOOL_SPEC dictionary alongside the function. You get full control over parameter names, types, and descriptions:
from strands.types.tools import ToolResult, ToolUse
TOOL_SPEC = {
"name": "lookup_transaction",
"description": "Look up a transaction by its id.",
"inputSchema": {"json": {
"type": "object",
"properties": {"txn_id": {"type": "string"}},
"required": ["txn_id"],
}},
}
def lookup_transaction(tool: ToolUse) -> ToolResult:
txn_id = tool["input"]["txn_id"]
...
Key insight. The same Agent interface works everywhere — connect to AWS with built-in tools like retrieve, compose with @tool for multi-agent systems, and swap models without changing application code. No framework lock-in.
The lab journey
Six labs, each building on the last. Click any lab to see what it covers and its architecture. Run the matching notebook from the strands-agents/samples01-learn track as you go.
Lab 1🤖First Agent
Lab 2🔧Tools & MCP
Lab 3🎯Agent Skills
Lab 4☁️AWS Services
Lab 5🏗️Agents as Tools
Lab 6🚀Deploy
Step 1 — Simplest agent (no tools)
Step 2 — Agent with tools
MCP Agent — AWS Documentation server
Retrieval-augmented generation — what the retrieve() tool does under the hood
How this maps to Strands. You don't build this pipeline yourself. The retrieve() built-in tool embeds the user's query (1), runs a semantic (or hybrid) search against your Amazon Bedrock Knowledge Base (2), and returns the matching passages. Strands drops that context into the prompt (3) before the model answers (4) — so the whole orchestrator layer is managed for you. The documents and data here are sample: swap in your own corpus and the flow is unchanged.
The agent and its AWS services — Knowledge Base + DynamoDB
Multi-agent orchestrator with multiple MCP servers
Deploy to AWS Lambda (CDK + container image)
Why Lambda for an agent? The function is stateless — each invoke rehydrates conversation history from S3 (sessions/{session_id}.json), runs the agentic loop, then writes the updated state back. Because the agent calls Bedrock and can wait on tool I/O, the CDK stack sets a 120s timeout and 512 MB memory, and packages dependencies (Strands + boto3) as a container image rather than a zip. Front it with API Gateway when you need an HTTP endpoint.
Key patterns
A cheat-sheet of the production patterns you meet across the six labs, with the SDK feature behind each and the lab that introduces it.
Pattern
What it does
SDK feature
Lab
Agent(system_prompt, tools)
Create an agent with a personality and capabilities in one line
Agent class
1
@tool decorator
Turn any Python function into an agent-callable tool
Custom tools
1–2
MCPClient + list_tools_sync()
Connect external MCP servers and use their tools
MCP integration
2
TOOL_SPEC dictionary
Define tools with an explicit JSON schema (Bedrock format)
Advanced tools
2
AgentSkills plugin + SKILL.md
Modular instruction bundles loaded on demand to keep context lean
Skills plugin
3
retrieve (Knowledge Base)
RAG retrieval from a Bedrock Knowledge Base with vector search
Built-in tools
4
@tool + DynamoDB CRUD
Custom tools that read/write DynamoDB for state management
AWS integration
4
Agent-as-@tool
Wrap specialised agents as callable tools for an orchestrator
Multi-agent
5
Orchestrator routing
Route a query to the best sub-agent based on intent
Multi-agent
5
Sequential chaining
Pipe one agent's output as input to the next
Multi-agent
5
Lambda handler(event, _context)
Entry point that reads the prompt/session from the event, runs the agent, returns the reply
AWS Lambda
6
S3 session state
Persist conversation history per session so the function stays stateless across invocations
Amazon S3
6
npx cdk deploy (container image)
Build a Docker image, push to ECR, and provision the Lambda + IAM with the AWS CDK
AWS CDK
6
Strands philosophy: model-driven, not framework-driven. The model handles reasoning and planning; you provide tools and a system prompt. No chains, graphs, or orchestration DSLs are needed for most use cases.
Knowledge check
1. What makes a Strands agent, at minimum?
Strands is model-driven: define a model, tools (any Python function), and a prompt, and the built-in agentic loop handles the reasoning. Modern models are good enough at tool use that heavy orchestration is rarely needed.
2. You want an agent to search official AWS docs without writing tool code. What do you use?
MCP servers expose ready-made tools. Connecting the AWS Documentation MCP server gives the agent search_documentation, read_documentation, and recommend with no custom code — that's Lab 2.
3. In the multi-agent pattern, how is a specialist agent exposed to the orchestrator?
"Agents as tools" wraps each specialist inside a @tool function. The orchestrator treats it like any other tool and routes queries to it — that's Lab 5.
Apply it to your own workload
The Strands patterns are domain-neutral. Here they are mapped to AnyCompany Payments — swap in your own workload and the shapes stay the same.
💬
Cardholder Support Agent
Pattern: First Agent + Tools + AWS Services (Labs 1, 2, 4). A support agent with @tool functions for transaction lookup in DynamoDB, refund status, and FAQ retrieval from a Bedrock Knowledge Base.
🕵️
Fraud & Dispute Triage
Pattern: Agents as Tools (Lab 5). An orchestrator routes to a fraud-scoring agent, a dispute-evidence agent, and a compliance agent — each specialised, each independently improvable.
🏪
Merchant Partner Bot
Pattern: Tools & MCP (Lab 2). Connects to internal services via MCP — settlement status, chargeback rates, payout schedules — all as discoverable MCP tools shared across agents.
🎯
Domain Support Skills
Pattern: Agent Skills (Lab 3). Separate instruction sets for chargebacks, PCI-DSS questions, billing, and account recovery — the agent loads only the relevant skill per query, keeping context lean and answers accurate.
✍️ Your turn — a 10-minute design activity
Before you build, sketch one agent for a workload you own. Answer these five questions — they map directly onto the Strands code you'll write:
Role — one sentence describing what the agent is for. → becomes the system_prompt.
Tools — what does it need to read or do? (lookups, calculations, writes) → each becomes a @tool function.
Data — where does its knowledge live? A Knowledge Base? A database? An MCP server?
Guardrails — what must it never do, and when must it escalate to a human?
Shape — is this one agent, or an orchestrator routing to specialists?
Source notebooks: every lab in this activity mirrors the strands-agents/samples repository → python/01-learn/. Clone it and run the notebooks alongside these tabs. Content on this page is rephrased for teaching.
🎉 What you built
A first agent in three lines, then extended it with custom and built-in tools
Connected MCP servers for external capabilities, over stdio and HTTP
Packaged domain expertise as agent skills loaded on demand
Wired the agent to a Knowledge Base and DynamoDB on real AWS infrastructure
Composed multiple agents under an orchestrator, then deployed to AWS Lambda with the AWS CDK