The simplest form of agentic AI: a query goes in, the LLM reasons over it, and a response comes back. No tools, no memory, no orchestration.
This sample covers building an agent with the Strands Agents SDK and is based off of the AWS Prescriptive Guidance - Basic Reasoning Agents pattern.
Prerequisites:
- Python 3.10+
- An AWS account with Amazon Bedrock access
- AWS credentials configured (
aws configure) with permission to invoke models on Bedrock
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Point the sample at your AWS profile and region (loaded by shared/model.py)
cp .env.example .env
# Edit .env: set AWS_PROFILE and AWS_REGION. Optionally pin a model with STRANDS_MODEL_ID.
# Run the simple agent
python simple_agent.py
# Run the RAG agent
python rag_agent.pyTry these exercises:
- Reshape the agent with the system prompt. Swap in a technical-explainer, code-reviewer, or customer-service persona and observe how the same model behaves differently.
- Swap the model. Point the agent at a faster, cheaper model (e.g., Claude Haiku) and compare latency and answer quality.
- Grow the knowledge base. Add entries to
KNOWLEDGE_BASEand confirm the agent uses retrieved context for those topics while falling back to general knowledge otherwise. - Add the error handling. Wrap the invocation in the try/except block above and force a failure (e.g., a very long prompt) to see graceful recovery.
- Receives input: User or system submits a query or instruction
- Invokes the LLM: Agent transforms the query into a structured prompt and sends it to the LLM
- Returns response: Generated output is formatted and returned to the user
Strands Agents is an open-source SDK developed by AWS for building production-ready AI agents. (Comparable frameworks include LangChain/LangGraph, CrewAI, and Pydantic AI.) Import it with:
from strands import AgentAn agent needs two things to start: a system prompt that sets its role and behavior, and a callback handler that controls how execution events are surfaced.
The system prompt is your primary tool for customization. It's a persistent instruction that gets sent with every user message, so it shapes the agent's voice, scope, and constraints across the entire conversation. Think of it as a job description: it tells the model who it is, what it should focus on, what it should avoid, and how to format its responses. A vague prompt like "You are a helpful assistant" gives the model wide latitude — fine for general Q&A, but unpredictable. A specific prompt like "You are a customer service agent for a cloud storage product. Always confirm the user's plan tier before suggesting features. Never quote pricing — direct billing questions to support" produces consistent, scoped behavior. Good system prompts tend to define the role, the domain, the tone, any guardrails (what not to do), and the desired output format.
Callback handlers let you intercept execution events for real-time monitoring, custom output formatting, or integration with external systems. By default, Strands uses PrintingCallbackHandler, which streams agent events (model tokens, tool calls, lifecycle events) to stdout as the agent runs. Setting callback_handler=None disables that streaming so you only see the final response. This can be useful when you want quick clean output.
agent = Agent(
system_prompt="""You are a helpful assistant that provides clear,
concise answers. Focus on being accurate and informative.""",
callback_handler=None
)Invoking the agent is a single call:
response = agent("What are the three laws of thermodynamics?")That's it. Everything below is just a while loop so you can chat with it interactively. The only Strands-specific line is agent(user_input).
def main():
while True:
user_input = input("You: ").strip()
if user_input.lower() in ["quit", "exit", "q"]:
break
if not user_input:
continue
response = agent(user_input) # ← the actual agent call
print(f"\nAgent: {response}\n")Strands defaults to a Bedrock model provider. Check which model your agent is using:
print(agent.model.config)
# eg. {'model_id': 'us.anthropic.claude-sonnet-4-5-20250929-v1:0'}To use a different model, pass a BedrockModel instance to the agent:
from strands.models.bedrock import BedrockModel
model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")
agent = Agent(model=model, system_prompt="...", callback_handler=None)Strands isn't limited to Bedrock. It has built-in support for Anthropic direct, OpenAI, Google Gemini, Ollama, LiteLLM, and others. See Model Providers in the Strands docs for the full list and configuration examples for each.
Note: Bedrock models released after mid-2024 require inference profile IDs (prefixed with
us.orglobal.) rather than direct model IDs. List them withaws bedrock list-inference-profiles. See Supported foundation models in Amazon Bedrock for the full list.
A basic reasoning agent only knows what the model learned at training time. The Retrieval-Augmented Generation (RAG) variant retrieves relevant context before calling the LLM, grounding responses in your own data.
For this sample, the knowledge base is a simple dictionary mapping topics to facts. This keeps the retrieval logic straight forward and simple, but larger systems would want to use a vector store such as the walkthrough describes in Amazon Bedrock Knowledge Bases.
KNOWLEDGE_BASE = {
"agentcore": "Amazon Bedrock AgentCore is a platform to build, deploy, and operate AI agents at scale.",
"strands": "Strands Agents SDK is a framework for building AI agents with tools, memory, and multi-agent patterns.",
"bedrock": "Amazon Bedrock is a fully managed service for foundation models from AI21, Anthropic, Meta, and more.",
"tim": "Tim is a fun loving guy with great hair.",
"bits": "bits are the best thing since sliced bread."
}If a knowledge-base context match appears in the query, its added to the LLM prompt:
def retrieve_context(query: str) -> str:
"""Simple keyword-based retrieval for JSON map."""
query_lower = query.lower()
relevant = [value for key, value in KNOWLEDGE_BASE.items() if key in query_lower]
return "\n".join(relevant)Note: When no context matches, the agent falls back to its general knowledge:
context = retrieve_context(user_input)
if context:
augmented_prompt = f"Context:\n{context}\n\nQuestion: {user_input}"
else:
augmented_prompt = user_input
response = agent(augmented_prompt)The injection step, retrieve->augment->generate, is the entire RAG pattern
Agent calls fail in agent-specific ways. The Strands SDK surfaces typed exceptions that deserve targeted handling rather than a generic catch-all:
from strands.types.exceptions import (
ContextWindowOverflowException,
ModelThrottledException,
MaxTokensReachedException,
)
try:
response = agent(user_input)
print(f"Agent: {response}")
except ContextWindowOverflowException:
# Conversation exceeded the model's context window — reset or summarize
print("Conversation too long — starting fresh.")
agent = Agent(system_prompt=SYSTEM_PROMPT, callback_handler=None)
except ModelThrottledException:
# Bedrock rate-limited the request — back off and retry
import time
print("Rate limited — retrying in a few seconds.")
time.sleep(5)
response = agent(user_input)
except MaxTokensReachedException:
# Response was cut off before completing
print("Response truncated — ask the agent to continue.")Other exceptions worth knowing:
| Exception | When it fires | What to do |
|---|---|---|
ToolProviderException |
A tool failed during execution | Log the error, check tool inputs |
MCPClientInitializationError |
MCP server connection failed | Verify the server is running |
ModelTimeoutException (Bedrock) |
Model took too long to respond | Retry with a simpler prompt |
ServiceQuotaExceededException (Bedrock) |
Hit account-level limits | Request a quota increase |
| Pattern | Description | Reference |
|---|---|---|
| Strands Agents SDK Quick Start | Build a basic reasoning agent with Strands using a model-driven approach on Amazon Bedrock | Introducing Strands Agents, an Open Source AI Agents SDK |
| RAG with Bedrock Knowledge Bases | Implement retrieval-augmented generation using managed vector stores and automatic chunking | Evaluate and improve performance of Amazon Bedrock Knowledge Bases |
| Model-Driven Agent Architecture | Design agents that leverage LLM reasoning for planning and tool selection without hardcoded workflows | Strands Agents and the Model-Driven Approach |
| Contextual Retrieval for RAG | Enhance RAG accuracy using contextual retrieval techniques with Amazon Bedrock Knowledge Bases | Contextual retrieval in Anthropic using Amazon Bedrock Knowledge Bases |
- AWS Prescriptive Guidance - Basic Reasoning Agents
- Strands Agents Documentation
- Amazon Bedrock User Guide
This sample is one of eleven, one per pattern in the AWS Prescriptive Guidance on agentic AI patterns. Each has a hands-on sample repository.
| # | Pattern | Sample |
|---|---|---|
| 01 | Basic Reasoning Agents | this repository |
| 02 | Tool-Based Agents (Functions) | sample-tool-based-agents-functions |
| 03 | Tool-Based Agents (Servers) | sample-tool-based-agents-servers |
| 04 | Computer-Use Agents | sample-computer-use-agents |
| 05 | Coding Agents | sample-coding-agents |
| 06 | Speech and Voice Agents | sample-speech-voice-agents |
| 07 | Workflow Orchestration Agents | sample-workflow-orchestration-agent |
| 08 | Memory-Augmented Agents | sample-memory-augmented-agents |
| 09 | Simulation and Test-Bed Agents | sample-simulation-testbed-agents |
| 10 | Observer and Monitoring Agents | sample-observer-monitoring-agents |
| 11 | Multi-Agent Collaboration | sample-multi-agent-collaboration |
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.

