strands-agents
An open source SDK from AWS for building AI agents with a model-driven loop: you hand an Agent a model, a system prompt, and plain Python functions decorated with @tool, and the SDK runs the reason-act loop, tool calls, streaming, and context management for you. It defaults to Amazon Bedrock but ships providers for Anthropic, OpenAI, Gemini, Ollama, LiteLLM, Writer, and custom backends, and MCP servers plug in directly as tool sources. The project now lives in a monorepo next to a TypeScript SDK and the docs site.
The cleanest way to build agents when Bedrock is already your model plane, and a genuinely small API for everyone else. Off AWS, weigh whether the defaults you will have to override are worth it versus a provider-neutral framework.
Use it if
- You are on AWS and want an agent framework whose default provider is Bedrock, using credentials and IAM you already have
- You want tools to be ordinary Python functions where the docstring and type hints become the schema, not framework-specific config
- You need MCP support built in so your agent can consume existing MCP servers as tools without adapter code
- You want to swap the model backend (Bedrock to OpenAI to a local Ollama) without touching the agent loop code
- You are not on AWS: the out-of-box path assumes AWS credentials plus a console step to enable Claude model access on Bedrock, and every other provider is something you configure yourself
- You need every surface to be stable: bidirectional voice streaming lives under strands.experimental with an explicit warning that its APIs may change
- You want the biggest ecosystem of integrations, examples, and Stack Overflow answers; the LangChain and LlamaIndex communities are still far larger
- You only need single LLM calls; an agent loop with hooks and tool orchestration is overhead when completion in, text out is enough
Setup reality
pip install strands-agents strands-agents-tools and a three-line agent runs, but only after the AWS part: the default Bedrock provider needs AWS credentials configured and model access enabled for Claude Sonnet in your region, a console approval step people routinely forget. Using a non-AWS provider means importing a different model class (GeminiModel, OllamaModel, and so on) and passing keys yourself. Python 3.10+ is required, the pre-built tools live in the separate strands-agents-tools package, and the experimental voice features want the bidi and bidi-io extras plus Python 3.12+ for Amazon Nova Sonic.
Patterns
Minimal agent with a prebuilt toolquickstart-agent
from strands import Agent
from strands_tools import calculator
agent = Agent(tools=[calculator])
agent("What is the square root of 1764")Defaults to Bedrock with Claude Sonnet, so this dies with an access error until AWS credentials are set and model access is enabled in the Bedrock console.
Turn a Python function into a toolcustom-tool
from strands import Agent, tool
@tool
def word_count(text: str) -> int:
"""Count words in text.
This docstring is used by the LLM to understand the tool's purpose.
"""
return len(text.split())
agent = Agent(tools=[word_count])
response = agent("How many words are in this sentence?")The docstring and type hints become the tool schema the model sees; skip the docstring and the model will use the tool badly or not at all.
Load and reload tools from a directoryhot-reload-tools
from strands import Agent
# Agent watches the ./tools/ directory for changes
agent = Agent(load_tools_from_directory=True)
response = agent("Use any tools you find in the tools directory")Handy in development, but a footgun in production: anything dropped into ./tools/ becomes callable by the model.
Use an MCP server as a tool sourcemcp-tools
from strands import Agent
from strands.tools.mcp import MCPClient
from mcp import stdio_client, StdioServerParameters
aws_docs_client = MCPClient(
lambda: stdio_client(StdioServerParameters(
command="uvx",
args=["awslabs.aws-documentation-mcp-server@latest"],
))
)
with aws_docs_client:
agent = Agent(tools=aws_docs_client.list_tools_sync())
response = agent("Tell me about Amazon Bedrock")Build and run the agent inside the with block; the MCP session owns the tools, and they stop working once the context manager exits.
Configure the Bedrock providerbedrock-model-config
from strands import Agent
from strands.models import BedrockModel
bedrock_model = BedrockModel(
model_id="us.amazon.nova-pro-v1:0",
temperature=0.3,
streaming=True,
)
agent = Agent(model=bedrock_model)
agent("Tell me about Agentic AI")model_id is the Bedrock identifier; the us. prefix selects cross-region inference profiles, and the model must be enabled for your account and region.
Swap in Google Geminigemini-provider
from strands import Agent
from strands.models.gemini import GeminiModel
gemini_model = GeminiModel(
client_args={"api_key": "your_gemini_api_key"},
model_id="gemini-2.5-flash",
params={"temperature": 0.7},
)
agent = Agent(model=gemini_model)
agent("Tell me about Agentic AI")Each provider is its own model class with its own import path; some providers need pip extras, so check the per-provider docs page before wiring keys.
Run against a local Ollama modelollama-local
from strands import Agent
from strands.models.ollama import OllamaModel
ollama_model = OllamaModel(
host="http://localhost:11434",
model_id="llama3",
)
agent = Agent(model=ollama_model)
agent("Tell me about Agentic AI")Good for offline development, but small local models handle tool calling much worse than the hosted defaults; expect flakier agent loops.
Experimental bidirectional voice agentbidi-voice-agent
import asyncio
from strands.experimental.bidi import BidiAgent
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands.experimental.bidi.io import BidiAudioIO, BidiTextIO
from strands_tools import calculator, stop
async def main():
model = BidiNovaSonicModel()
agent = BidiAgent(model=model, tools=[calculator, stop])
audio_io = BidiAudioIO()
text_io = BidiTextIO()
await agent.run(
inputs=[audio_io.input()],
outputs=[audio_io.output(), text_io.output()],
)
asyncio.run(main())Requires pip install strands-agents[bidi,bidi-io], and Nova Sonic needs Python 3.12+. The whole namespace is experimental and the API is expected to change.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| langgraph | PyPI | You want graph-structured, stateful orchestration and the LangChain ecosystem around it |
| pydantic-ai | PyPI | You want type-safe agents built around Pydantic validation with no cloud-provider default |
| crewai | PyPI | You want role-based multi-agent crews and a large library of ready-made templates |