The Agentic Stack on AWS: Notes for AWS Certification

AWS
Bedrock
Agents
AgentCore Runtime, Strands, Agent Squad, LangChain/LangGraph and Step Functions answer five different questions. This is a layer-by-layer guide to picking the right piece.
Published

September 1, 2026

The Agentic Stack on AWS: Notes for AWS Certification

The Agentic Stack on AWS

AWS’s agent tooling looks like a pile of overlapping options (AgentCore Runtime, Strands, Agent Squad, LangChain, LangGraph, Step Functions) until you notice they don’t answer the same question. They answer five different questions, stacked at different depths: how a model reasons within one call, who writes the reason-act-observe loop, where that loop actually runs, how a request gets routed to the right specialist agent, and what guarantees retries and audit trail around the whole thing. Most confusion about “which one do I use” disappears once you identify which depth a requirement is actually describing.

The Five Layers

The layer numbers below are depth, not sequence: L0 lives inside a single model call, and L4 wraps everything else.

Layer Question it answers Who lives there
L0: Reasoning pattern How does the model think within one call or turn? Chain-of-Thought, ReAct, Reflection, Plan-and-execute (prompt-level, not a service)
L1: Agent loop / framework Who writes the reason → act → observe → repeat cycle? Strands Agents, LangGraph, LangChain, Bedrock Agents (managed)
L2: Runtime / hosting Where does that agent process run, with what identity, memory and tools? AgentCore Runtime (+ Memory, Identity, Gateway, Observability), Lambda, Fargate/EKS
L3: Multi-agent routing Which of my already-built specialist agents should take this request? Agent Squad, Strands supervisor/swarm/graph, Bedrock multi-agent collaboration
L4: Durable outer workflow What guarantees retries, approvals, audit trail and long-running (up to a year) execution? AWS Step Functions (EventBridge and SQS as the triggers and buffers around it)

Reading the Question

Scenario descriptions are usually written around one distinguishing constraint. These are the tells:

The scenario says… The layer being tested
“…the sequence of steps is not known in advance / the agent must decide which tools to call” L1: Strands or LangGraph. Model-driven loop, not Step Functions.
“…must be auditable, retried, resumed after a human approval, run for days” L4: Step Functions Standard with waitForTaskToken.
“…we already have agents built in LangGraph and CrewAI, need them in production with session isolation and identity” L2: AgentCore Runtime. Framework- and model-agnostic hosting.
“…one chat entry point, several specialist agents, conversation context must follow the user across them” L3: Agent Squad (classifier + storage), or a Strands supervisor.
“…Lambda’s 15-minute limit is being hit by a long-running agent session” L2: AgentCore Runtime. A session lives up to 8 hours, but one synchronous request still caps at 15 minutes, so long work runs as an async task (or streams, up to 60 minutes).
“…minimum custom orchestration code, AWS should own the loop” L1, managed: Bedrock Agents, or the AgentCore harness (GA June 2026).
“…accuracy on multi-step arithmetic or logic is poor, no tools involved” L0: chain-of-thought, not an agent framework.
“…payload between steps exceeds the limit” Step Functions’ 256 KiB cap. Pass S3 references, not documents.

The Five, in Profile

Bedrock AgentCore Runtime (L2, hosting)

A serverless, session-isolated runtime for agents you’ve already written, plus a set of surrounding managed services: Memory, Identity, Gateway, Observability, Code Interpreter, Browser, Policy, Evaluations. It reached general availability in October 2025. It does not write your agent. It runs it, and it doesn’t care which framework wrote it.

Reach for it when an agent already exists (Strands, LangGraph, CrewAI, LlamaIndex, the OpenAI Agents SDK) and now needs production hosting; when sessions run longer than Lambda’s 15-minute ceiling (a Runtime session lasts up to 8 hours, though each synchronous request is still capped at 15 minutes, so long jobs go through async tasks); when per-user session isolation is a security requirement, since each session gets its own microVM; when you need OAuth/Cognito/IAM agent identity or want to expose Lambdas and REST APIs to the agent as MCP tools through Gateway; or when short- and long-term memory should be managed rather than hand-rolled in DynamoDB.

from bedrock_agentcore import BedrockAgentCoreApp
from strands import Agent

app = BedrockAgentCoreApp()
agent = Agent(tools=[...])

@app.entrypoint
def invoke(payload, context):
    return agent(payload["prompt"])

# npm install -g @aws/agentcore
# agentcore create      (Agent → Strands)
# agentcore deploy      → runtime ARN (agentcore status)
# InvokeAgentRuntime(agentRuntimeArn=..., runtimeSessionId=...)

The same steps apply whatever the framework, because Runtime only needs your code to speak its HTTP contract (/invocations and /ping).

What tells it apart: framework-agnostic and model-agnostic (models inside or outside Bedrock) · 8-hour sessions · microVM session isolation · MCP and A2A support · OTEL/CloudWatch observability built in. Harness (GA June 2026, backed by a managed Runtime) is the newer managed-loop option, where you declare model + tools + behavior instead of writing the loop yourself.

Strands Agents (L1, model-driven loop)

AWS’s open-source agent SDK. The whole premise is that the ReAct loop is the framework: give it a model, a system prompt and tools, and the model decides the sequence. A working agent is a few lines of code.

Reach for it when you want a ReAct-style loop without hand-writing orchestration, want the AWS-native path (written by AWS, deploys straight into AgentCore Runtime, first-class MCP support), or need one of its multi-agent shapes: agents-as-tools (supervisor), swarm (autonomous handoffs), graph (conditional branching, loops), or workflow (fixed DAG, parallel). Observability is built into the loop, so OTEL traces and spans come for free.

from strands import Agent, tool

@tool
def get_order(order_id: str) -> dict:
    """Look up an order."""
    return ddb.get_item(...)  # ddb: a boto3 DynamoDB Table

agent = Agent(
    model="global.anthropic.claude-...",  # inference profile ID
    system_prompt="You are support...",
    tools=[get_order],
)
agent("Where is order 4471?")

# supervisor = agents-as-tools
Agent(tools=[billing_agent, tech_agent])

What tells it apart: “model-driven” means the LLM picks the path and you don’t script it · Python and TypeScript · runs on Lambda, Fargate/ECS/EKS, or AgentCore Runtime · multi-agent primitives shipped in 1.0 · return-of-control lets a tool execute client-side for data-residency cases.

Agent Squad (L3, routing)

An open-source orchestrator that started at AWS Labs and has been maintained by 2FastLabs since April 2026 (formerly Multi-Agent Orchestrator) that classifies an incoming request, routes it to the right specialist agent, and keeps one conversation history across all of them. It has no reasoning loop of its own and sits on top of agents built elsewhere.

Reach for it when several agents already exist and one front door needs to pick between them; when the agents are heterogeneous (a Bedrock Agent, a Lex bot, a Lambda, an OpenAI model) and still need shared context; when context has to survive a switch mid-conversation (“now about my bill…”); or when the router itself needs to run anywhere: Lambda, a laptop, another cloud.

orchestrator = AgentSquad(
    classifier=BedrockClassifier(...),
    storage=DynamoDbChatStorage(...),
)
orchestrator.add_agent(BedrockLLMAgent(...))     # tech
orchestrator.add_agent(LambdaAgent(...))         # billing
orchestrator.add_agent(AmazonBedrockAgent(...))  # KB

response = await orchestrator.route_request(text, user_id, session_id)

Classifier options are Bedrock, Anthropic, or OpenAI; storage can be in-memory, DynamoDB, or SQL (libSQL). There’s also a SupervisorAgent mode for agents-as-tools instead of pure routing.

What tells it apart: what you’re really getting is intent classification plus conversation persistence · Python and TypeScript · streaming and non-streaming · if a scenario describes building the agent’s own tool-calling loop, Agent Squad is the wrong answer, because it routes between agents and doesn’t build one.

LangChain & LangGraph (L1, developer-driven loop)

Two different things under one brand, even though AWS’s prescriptive guidance covers them on a single page. LangChain is the component library: loaders, retrievers, chains, integrations. LangGraph is the stateful graph: nodes, conditional edges, cycles, checkpoints.

Reach for LangChain for rapid prototyping, RAG plumbing, or reusing a broad pre-built integration ecosystem. Reach for LangGraph when control flow must be explicit and inspectable: complex branching, long-running stateful sessions, checkpointed human-in-the-loop interrupts, multi-agent supervisor graphs. It also fits when portability across clouds and models is a stated requirement. The general rule versus Strands: choose LangGraph when you want to own the topology rather than let the model choose it.

g = StateGraph(AgentState)
g.add_node("assistant", call_model)
g.add_node("tools", ToolNode(tools))
g.add_edge(START, "assistant")
g.add_conditional_edges(
    "assistant", needs_tool,
    {"yes": "tools", "no": END})
g.add_edge("tools", "assistant")   # the cycle
graph = g.compile(checkpointer=saver)

That cycle is ReAct, written by hand. Deploy the compiled graph on Lambda, ECS/EKS, or package it into AgentCore Runtime.

What tells it apart: LangChain is components, LangGraph is a state machine with cycles · both integrate with Bedrock (Claude, Nova) · AWS’s Strands deep dive calls LangChain “developer-first” (you assemble the chain) and Strands “LLM-first” (the model plans) · reflection, plan-and-execute and supervisor patterns are all just extra nodes on the graph.

AWS Step Functions (L4, durable workflow)

The deterministic outer shell. Use it when the sequence is known and you want it explicit, resilient and auditable. Don’t use it as the tight inner reasoning loop, where every transition costs money and latency.

Reach for it for durable, resumable execution up to a year (Standard workflows); for human approval gates via the callback pattern (waitForTaskToken, with TimeoutSeconds and HeartbeatSeconds); for fan-out over documents or agents (Map, Distributed Map, Parallel); for built-in retry/catch plus a full execution history as audit and compliance evidence; or for orchestrating across AWS services around the model call (extract, classify, store, notify).

// optimized integration
"Task": "arn:aws:states:::bedrock:invokeModel"
  Input:  { "S3Uri": "s3://in/doc.json" }
  Output: { "S3Uri": "s3://out/res.json" }

// naive ReAct, exam-flavoured
Model → Choice("tool_use"?)
  ├ yes → Lambda(tool) → back to Model
  └ no  → Succeed

// current AWS-native combo
Map → aws-sdk:bedrockagentcore:invokeAgentRuntime

What tells it apart: a 256 KiB payload limit between states, so pass S3 references and treat state as control plane, not data plane · Standard (1 year, callbacks) versus Express (5 minutes, no callbacks, cheaper at volume) · the optimized bedrock:invokeModel integration does not cover Converse or streaming, so use the generic SDK integration for those · March 2026 added direct AgentCore SDK integrations; June 2026 announced, in preview, an InvokeHarness Task (bedrockagentcore:invokeHarness) that runs an AgentCore harness as a step, with a session ID for context and per-invocation model, prompt and tool overrides. It is request-response only (no .sync, no waitForTaskToken) and the Task caps at 15 minutes, so long agent runs still belong in Runtime.

Reasoning Patterns, and Where Each One Lives

L0 patterns are prompt-and-control-flow techniques, not services. Each one can be implemented on more than one layer, and the real question is which implementation fits the constraint in front of you.

Pattern Use it when How to apply, by layer
Chain-of-Thought: reason before answering, one call Multi-step arithmetic, logic, policy decisions where the answer needs derivation. No tools involved. Prompt “think step by step”, or few-shot examples showing the reasoning, or the model’s extended-thinking mode. Store the template in Bedrock Prompt Management. Costs more output tokens and latency; chain-of-draft is the terse variant.
ReAct: reason → act → observe → repeat The task needs external facts or side effects, and the number/order of tool calls is unknown up front. Strands: the default agent loop. LangGraph: assistant node ⇄ ToolNode cycle. Bedrock Agents: managed, with action groups. Step Functions: a Choice state looping back to the model. It works, but pays a transition per thought.
Reflection / self-critique: generate, critique, revise Output quality matters more than latency: code, long-form drafts, anything scored against a rubric. Strands: a critic agent used as a tool. LangGraph: a critic node with an edge back to the generator plus a max-iteration guard. Offline: LLM-as-a-Judge in Bedrock Evaluations / AgentCore Evaluations.
Plan-and-execute: plan first, then run the steps Long horizons where a pure ReAct loop drifts; when the plan itself must be shown to a human before execution. LangGraph: planner node → executor loop → replanner. Step Functions: one model call produces the plan, then Map executes it with retries, with an approval gate between the two.
Routing: classify, then dispatch Distinct request types needing different tools, costs or models; also cheap-model-first cost optimization. Agent Squad classifier (Bedrock/Anthropic/OpenAI). Strands: supervisor with agents-as-tools. Step Functions: Choice on a classification result. Bedrock intelligent prompt routing for pure model-tier selection.
Parallel sampling / Tree-of-Thought: explore several branches, then judge One-shot, quality-critical answers where independent attempts can be compared, or multi-perspective analysis. Step Functions Parallel/Map fan-out then a judge state. Strands swarm for autonomous multi-perspective work. Watch cost: token spend multiplies by branch count.
Human-in-the-loop: pause for a person Irreversible or regulated actions: payments, account changes, clinical or legal output. Step Functions waitForTaskToken is the canonical answer. LangGraph: checkpointed interrupt. Strands: return-of-control back to the caller. Bedrock Agents: user confirmation on an action group.

Three Compositions Worth Memorizing

Most real designs combine several of these. These three keep showing up in AWS samples and reference architectures.

The AWS-native default

Strands Agents writes the ReAct loop, AgentCore Runtime hosts it with 8-hour sessions, AgentCore Gateway turns Lambdas into MCP tools, and AgentCore Memory + Identity handle context and auth. This is the fastest AWS-blessed path from a laptop prototype to a production agent. Pick it when the requirement stresses “minimal infrastructure management.”

Durable enterprise workflow

Step Functions (Standard) is the outer, auditable process; Map fans out over documents; InvokeAgentRuntime calls the agent per item (keep each call under the 15-minute synchronous limit, or start an async task and poll); waitForTaskToken gates on human approval before commit. Pick this combination when the words are compliance, audit trail, retries, approval, long-running.

Many specialists, one door

API Gateway is the chat entry point, Agent Squad classifies and keeps DynamoDB history, specialist agents (Strands, Bedrock Agents, or Lex) do the actual work, and AgentCore Runtime hosts each specialist. Pick this when several teams own separate agents and context has to survive the handoff between them.

Traps

Where these terms get deliberately swapped or conflated:

  • Step Functions gets offered as the reasoning loop. It can loop a Choice state back to the model, and that pattern is real, but if the requirement says the path is chosen by the model at runtime, the right tool is Strands or LangGraph. Step Functions is for known sequences.
  • Agent Squad gets mistaken for something that builds an agent. It routes between agents and keeps history; it does not implement tool-calling reasoning. If nothing in the requirement mentions multiple existing agents, it’s the wrong fit.
  • AgentCore Runtime gets mistaken for a framework. It’s hosting plus managed services and doesn’t decide how your agent thinks. If a scenario says “framework-agnostic”, it’s pointing at Runtime.
  • Bedrock Agents and AgentCore get conflated. Bedrock Agents is the fully managed console/API agent: action groups, knowledge bases, AWS owns the loop, and you get the least control. AgentCore is the platform for agents you built.
  • LangChain and LangGraph get treated as one thing. “Stateful”, “cycles”, “checkpoint”, “human-in-the-loop interrupt”, or “multi-agent orchestration” all point to LangGraph specifically, not the LangChain component library.

The one-line version to keep straight: pattern (L0) decides how it thinks, framework (L1) decides who writes the loop, runtime (L2) decides where it runs, router (L3) decides which agent, workflow (L4) decides what is guaranteed.

Sources