DEV Community

Jamal
Jamal

Posted on

LangChain vs Strands SDK with Amazon Bedrock

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)

Enter fullscreen mode Exit fullscreen mode

*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)

Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

10. Suggested presentation order

  1. Start with the problem: answer a live weather question.
  2. Explain why the model alone cannot know guaranteed current weather.
  3. Introduce the get_weather tool.
  4. Show the agent deciding to call that tool.
  5. Compare the Strands and LangChain implementations line by line.
  6. Introduce LangGraph only after showing a need for controlled workflows.
  7. Finish by separating construction, model hosting, and production runtime.

11. Learning path

  1. Run both weather examples and compare their output.
  2. Add a second tool, such as a weather forecast tool.
  3. Return structured weather data using a schema.
  4. Add conversation history for follow-up questions like “How about tomorrow?”
  5. Build a LangGraph that routes current-weather and forecast requests.
  6. Add a human approval step before a tool with real-world side effects.
  7. 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?"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Normal AWS credentials must also be available through an AWS profile,
environment variables, or an assigned IAM role.

Top comments (0)