LangChain, LangGraph, and Strands: Concept Map
This guide compares LangChain, LangGraph, and the Strands Agents SDK using the
weather-agent examples in this repository. It is intended both for learning and
for explaining the technologies to others.
1. The short explanation
- Strands Agents SDK provides a concise, model-driven way to build agents, especially when working with Amazon Bedrock and AWS services.
- LangChain provides standard abstractions for models, messages, prompts, tools, retrieval, structured output, and agents.
- LangGraph provides explicit control over long-running, stateful agent workflows using nodes, edges, state, and checkpoints.
- Amazon Bedrock is the managed AWS service that hosts the foundation model.
- AgentCore is an AWS platform for operating agents securely in production.
LangChain and Strands help construct an agent. LangGraph becomes especially
useful when the workflow needs controlled routing, persistence, human approval,
or multiple collaborating agents.
2. Technology-layer mapping
| Layer | Strands / AWS choice | LangChain / LangGraph choice | Purpose |
|---|---|---|---|
| Foundation model | Amazon Nova, Claude, or another Bedrock model | The same model | Generates responses and decides when to call tools |
| Model service | Amazon Bedrock | Amazon Bedrock | Hosts and invokes the model |
| Model adapter | BedrockModel |
ChatBedrockConverse |
Connects application code to Bedrock |
| Agent API | Agent |
create_agent |
Runs the model–tool reasoning loop |
| Tool definition | Strands @tool
|
LangChain @tool
|
Exposes a Python function to the model |
| Conversation input | String or message objects | Message dictionaries or message objects | Carries user and assistant messages |
| Agent instructions | system_prompt |
system_prompt |
Defines the agent's role and behavior |
| Workflow orchestration | Agents, hooks, and custom application logic | LangGraph nodes and edges | Controls multi-step execution |
| Workflow state | Agent/application state | Typed LangGraph state | Shares data between workflow steps |
| Persistence | Application or runtime integration | LangGraph checkpointer/store | Saves conversation and workflow progress |
| Production runtime | AgentCore Runtime | AgentCore, containers, or another runtime | Hosts and operates the agent |
| Observability | AWS tooling and Strands integrations | LangSmith, callbacks, and AWS tooling | Traces and evaluates executions |
3. Weather-agent mapping
The files strand-agent.py and
langchain-agent.py implement the same use case.
| Concept | Strands example | LangChain example |
|---|---|---|
| Import the agent | from strands import Agent |
from langchain.agents import create_agent |
| Import the tool decorator | from strands import tool |
from langchain.tools import tool |
| Configure Bedrock | BedrockModel(...) |
ChatBedrockConverse(...) |
| Declare a tool |
@tool above get_weather
|
@tool above get_weather
|
| Register the tool | tools=[get_weather] |
tools=[get_weather] |
| Create the agent | Agent(...) |
create_agent(...) |
| Invoke the agent | agent(question) |
agent.invoke({"messages": [...]}) |
| Read the answer | Returned result | Last message in result["messages"]
|
The @tool decorators look similar, but they belong to different SDKs. In both
cases, the function name, type hints, and docstring help the model understand
when and how to call the tool.
4. How the weather agent works
import json
import os
import ssl
import sys
from urllib.parse import urlencode
from urllib.request import urlopen
import certifi
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_aws import ChatBedrockConverse
load_dotenv()
SSL_CONTEXT = ssl.create_default_context(cafile=certifi.where())
def get_json(url: str, params: dict[str, str | int]) -> dict:
"""Make a small JSON GET request using only the Python standard library."""
request_url = f"{url}?{urlencode(params)}"
with urlopen(request_url, timeout=10, context=SSL_CONTEXT) as response: # noqa: S310
return json.load(response)
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city. Use this for weather questions."""
try:
places = get_json(
"https://geocoding-api.open-meteo.com/v1/search",
{"name": city, "count": 1, "language": "en", "format": "json"},
).get("results", [])
if not places:
return f"I could not find a location matching {city!r}."
place = places[0]
weather = get_json(
"https://api.open-meteo.com/v1/forecast",
{
"latitude": place["latitude"],
"longitude": place["longitude"],
"current": "temperature_2m,apparent_temperature,weather_code,wind_speed_10m",
"timezone": "auto",
},
)["current"]
return (
f"Current weather in {place['name']}, {place.get('country', '')}: "
f"temperature {weather['temperature_2m']}°C, "
f"feels like {weather['apparent_temperature']}°C, "
f"wind speed {weather['wind_speed_10m']} km/h, "
f"WMO weather code {weather['weather_code']}."
)
except Exception as error:
return f"Weather lookup failed: {error}"
model = ChatBedrockConverse(
model_id=os.getenv("BEDROCK_MODEL_ID", "global.amazon.nova-2-lite-v1:0"),
region_name=os.getenv("AWS_REGION", "eu-west-2"),
temperature=0,
)
agent = create_agent(
model=model,
tools=[get_weather],
system_prompt="You are a helpful weather assistant. Use the weather tool when needed.",
)
if __name__ == "__main__":
question = " ".join(sys.argv[1:]) or "What is the weather in Kolkata, India?"
result = agent.invoke({"messages": [{"role": "user", "content": question}]})
print(result["messages"][-1].content)
*Strands SDK
*
import json
import os
import ssl
import sys
from urllib.parse import urlencode
from urllib.request import urlopen
import certifi
from dotenv import load_dotenv
from strands import Agent, tool
from strands.models.bedrock import BedrockModel
load_dotenv()
SSL_CONTEXT = ssl.create_default_context(cafile=certifi.where())
def get_json(url: str, params: dict[str, str | int]) -> dict:
"""Make a small JSON GET request using only the Python standard library."""
request_url = f"{url}?{urlencode(params)}"
with urlopen(request_url, timeout=10, context=SSL_CONTEXT) as response: # noqa: S310
return json.load(response)
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city.
Args:
city: City name, optionally including its state or country.
"""
try:
places = get_json(
"https://geocoding-api.open-meteo.com/v1/search",
{"name": city, "count": 1, "language": "en", "format": "json"},
).get("results", [])
if not places:
return f"I could not find a location matching {city!r}."
place = places[0]
weather = get_json(
"https://api.open-meteo.com/v1/forecast",
{
"latitude": place["latitude"],
"longitude": place["longitude"],
"current": "temperature_2m,apparent_temperature,weather_code,wind_speed_10m",
"timezone": "auto",
},
)["current"]
return (
f"Current weather in {place['name']}, {place.get('country', '')}: "
f"temperature {weather['temperature_2m']}°C, "
f"feels like {weather['apparent_temperature']}°C, "
f"wind speed {weather['wind_speed_10m']} km/h, "
f"WMO weather code {weather['weather_code']}."
)
except Exception as error:
return f"Weather lookup failed: {error}"
model = BedrockModel(
model_id=os.getenv("BEDROCK_MODEL_ID", "global.amazon.nova-2-lite-v1:0"),
region_name=os.getenv("AWS_REGION", "eu-west-2"),
temperature=0,
)
agent = Agent(
model=model,
tools=[get_weather],
system_prompt="You are a helpful weather assistant. Use the weather tool when needed.",
callback_handler=None,
)
if __name__ == "__main__":
question = " ".join(sys.argv[1:]) or "What is the weather in Kolkata, India?"
result = agent(question)
print(result)
User question
|
v
Agent sends the question and tool definition to the Bedrock model
|
v
Model selects get_weather(city="London")
|
v
Tool converts the city to latitude and longitude with Open-Meteo geocoding
|
v
Tool requests current weather from Open-Meteo
|
v
Tool result is returned to the model
|
v
Model produces a natural-language answer
Important distinction: the model does not directly access the weather service.
It chooses a registered tool, and the application executes that Python function.
5. Core vocabulary
Model
The foundation model performs language understanding, response generation, and
tool selection. In these examples, the model is accessed through Amazon Bedrock.
Prompt
A prompt is the information sent to the model. It can include system
instructions, conversation messages, tool descriptions, and tool results.
System prompt
The system prompt defines high-level behavior, for example:
You are a helpful weather assistant. Use the weather tool when needed.
Tool
A tool is an application-controlled capability exposed to the model. Examples
include calling an API, reading a database, searching documents, or creating a
support ticket.
Tool calling
Tool calling is the process in which the model returns a structured request such
as get_weather(city="London"). The SDK validates and executes the request and
returns the result to the model.
Agent
An agent combines a model, instructions, and tools with an execution loop. The
loop continues until the model returns a final answer or reaches a configured
limit.
State
State is data retained during a workflow. It may contain messages, tool results,
user information, approval status, or intermediate calculations.
Memory
Memory is information retained across interactions. Short-term memory commonly
means conversation history; long-term memory may store facts across sessions.
Memory is not the same as a model's context window.
Checkpoint
A checkpoint is a persisted snapshot of workflow state. LangGraph checkpoints
allow a workflow to pause, resume, recover, and maintain separate conversation
threads.
Node and edge
In LangGraph, a node performs a unit of work and an edge determines which
node runs next. A conditional edge routes execution based on current state.
Human in the loop
Human-in-the-loop design pauses execution before a sensitive action so a person
can approve, reject, or edit it. LangGraph supports this through interrupts and
persisted state.
Structured output
Structured output asks the model to return data matching a schema instead of
free-form prose. It is useful when downstream code needs reliable fields.
Retrieval-augmented generation (RAG)
RAG retrieves relevant information from external sources and includes it in the
model's context. Retrieval supplies knowledge; an agent decides and acts. A
system can use both.
6. Similarities
Both LangChain and Strands:
- support Amazon Bedrock models;
- allow Python functions to become model-callable tools;
- run a model–tool–model loop;
- use system prompts to guide behavior;
- support streaming and conversation messages;
- can be extended with custom tools and production integrations.
The central pattern is the same:
model + instructions + tools + execution loop = agent
7. Important differences
| Topic | Strands | LangChain / LangGraph |
|---|---|---|
| Primary style | Compact and agent-first | Broad component ecosystem plus graph orchestration |
| AWS alignment | Designed with strong AWS integration | Provider-neutral, with AWS integrations |
| Simple agent setup | Very concise | Concise with create_agent
|
| Explicit workflow control | Usually application logic or SDK patterns | A core LangGraph feature |
| State graph | Not a direct one-to-one abstraction | Nodes, edges, reducers, and subgraphs |
| Ecosystem | Focused agent SDK and AWS ecosystem | Large integration and retrieval ecosystem |
| Production hosting | Natural fit with AgentCore | Multiple deployment choices, including AgentCore |
These differences do not mean one framework is universally better. The choice
depends on the required integrations, workflow complexity, operating platform,
and the team's preferred abstractions.
8. When to introduce LangGraph
A simple weather agent does not require a custom graph. Introduce LangGraph when
the application needs one or more of the following:
- deterministic stages around the agent;
- conditional routing;
- durable conversation state;
- pause and resume;
- human approval before side effects;
- retry or recovery behavior;
- parallel branches;
- multiple specialized agents;
- a workflow that must be inspected and tested step by step.
Example controlled workflow:
START -> classify request -> retrieve data -> draft answer -> approval -> END
| |
+-> reject unsupported request +-> revise
9. Bedrock and AgentCore are different layers
It is useful to avoid combining these terms:
- Bedrock supplies access to foundation models and related AI services.
- The SDK or framework defines agent logic and connects models to tools.
- AgentCore supplies production capabilities for deploying and operating agents.
A possible production stack is:
User interface
|
AgentCore Runtime
|
LangChain/LangGraph or Strands application
|
Amazon Bedrock model + application tools
10. Suggested presentation order
- Start with the problem: answer a live weather question.
- Explain why the model alone cannot know guaranteed current weather.
- Introduce the
get_weathertool. - Show the agent deciding to call that tool.
- Compare the Strands and LangChain implementations line by line.
- Introduce LangGraph only after showing a need for controlled workflows.
- Finish by separating construction, model hosting, and production runtime.
11. Learning path
- Run both weather examples and compare their output.
- Add a second tool, such as a weather forecast tool.
- Return structured weather data using a schema.
- Add conversation history for follow-up questions like “How about tomorrow?”
- Build a LangGraph that routes current-weather and forecast requests.
- Add a human approval step before a tool with real-world side effects.
- Add persistence, tracing, evaluation, and deployment.
12. Commands for the examples
uv run python strand-agent.py "What is the weather in London?"
uv run python langchain-agent.py "What is the weather in London?"
Both examples use the same Bedrock defaults and accept these environment
variables:
export AWS_REGION="eu-west-2"
export BEDROCK_MODEL_ID="global.amazon.nova-2-lite-v1:0"
Normal AWS credentials must also be available through an AWS profile,
environment variables, or an assigned IAM role.
Top comments (0)