← Back to Learning Hub

Framework Comparison

LangChainLangGraphIntermediate13 min

By: Anacodic Team

TL;DR

Six frameworks, one decision. LangChain = compose linear LLM pipelines (LCEL chains). LangGraph = stateful graphs with branching/loops (workflows and agents). Strands = lightweight, model-driven agents with tools (AWS; great with Bedrock; "agents-as-tools" for multi-agent). AutoGen = agents that solve tasks by conversing. CrewAI = declarative role/task/process teams. OpenAI Agents SDK = minimal agents + handoffs + guardrails, provider-lean. Choose on two axes: how much control you want (low-level ↔ batteries-included) and single vs multi-agent. And keep Anthropic's principle in view: the most successful agent implementations use simple, composable patterns — not complex frameworks. Two apps in the same domain prove the point both ways: a single-agent trip-planning workflow built on LangChain/LangGraph, and a trip-planning assistant built on Strands — same domain (trip planning), two framework choices.


Simple explanation + analogy

Picture building a house:

  • LangChain = a pipe-fitting kit. Snap segments together into a line (prompt | llm | parser). Perfect for water flowing one direction.
  • LangGraph = the electrical blueprint with switches and loops. You draw exactly where current can branch and cycle back.
  • Strands = a smart contractor with a toolbox. You hand them tools and a goal; they decide which tool to use and when (a model-driven loop), with minimal ceremony.
  • AutoGen = a room of subcontractors talking it out. Emergent, conversational, self-correcting.
  • CrewAI = an org chart with job tickets. Named roles, assigned tasks, a manager or an assembly line.
  • OpenAI Agents SDK = a lean agent runtime — one agent that can hand off to another, with typed guardrails, and not much else in the way.

The meta-lesson (Anthropic): don't build a mansion when a shed will do. Start with the simplest pattern; add framework only when complexity earns it.


Diagram

                 CONTROL / TRANSPARENCY  ◀───────────────────────────▶  BATTERIES / ABSTRACTION
  low-level  ┌───────────────┐                                            ┌───────────────────┐  high-level
  (you own   │ Direct SDK    │  Strands   OpenAI Agents SDK   LangGraph   │  LangChain (LCEL) │  (framework
   the loop) │ (Anthropic:   │  (thin)    (thin)              (explicit   │  CrewAI  AutoGen  │   owns loop)
             │  "start here")│                                 graph)     │                   │
             └───────────────┘                                            └───────────────────┘

                     SINGLE-AGENT ◀──────────────────────────▶ MULTI-AGENT
        LangChain chain   Strands agent      Strands agents-as-tools   AutoGen group chat
        LangGraph (1 loop)                    LangGraph multi-node      CrewAI crew
                                               OpenAI Agents handoffs

   App A  → LangChain (LCEL chat) + LangGraph (team graph)     ┐
                                                                ├─ same domain, two choices
   App B  → Strands + Bedrock (orchestrator + specialists)     ┘

How it works (deep) — what each is best for

LangChain (LCEL)

Linear composition via the | operator over a uniform Runnable interface. Best for single-agent, mostly-linear flows: RAG, extraction, chat, routing. Batteries included (model connectors, prompt templates, output parsers, memory, retrievers). Ceiling: no native loops or shared mutable state → move to LangGraph.

LangGraph

Nodes + edges + shared State. Conditional edges give branching; back-edges give loops; checkpointers give durability. Builds both workflows (you write the routers — deterministic, auditable) and agents (LLM writes the routers). Best for complex, stateful, cyclic control flow and multi-step/multi-node agents. Higher learning curve; more boilerplate.

Strands (AWS)

A lightweight, model-driven agent framework: give an Agent a system prompt, a model (commonly Bedrock), and @tool-decorated functions; the model decides which tools to call in a loop. Multi-agent via "agents-as-tools" — an orchestrator agent exposes specialist agents as tools. Best when you want minimal ceremony, tight AWS/Bedrock integration, and a model-in-charge loop. Thinner and less opinionated than CrewAI; less graph control than LangGraph.

AutoGen (Microsoft)

Multi-agent as conversation: AssistantAgent + UserProxyAgent, GroupChat + GroupChatManager selecting speakers. Best for open-ended, iterative, code-executing tasks and debate/critique. Least predictable; watch O(T²) transcript growth.

CrewAI

Declarative role-based teams: agents (role/goal/backstory), tasks (expected_output), process (sequential | hierarchical). Best when you can name the roles and the workflow and want a clean, opinionated API. Standalone (not on LangChain). Also offers Flows for deterministic control.

OpenAI Agents SDK

A minimal, production-lean agent loop: an Agent with instructions + tools, handoffs to other agents, guardrails (typed input/output validation), sessions, and tracing. Provider-flexible but OpenAI-first. Best when you want a thin, typed, few-abstraction agent runtime — close in spirit to Anthropic's "just build it" advice, with a little scaffolding.

The Anthropic principle

From Building Effective Agents: across dozens of teams, the most successful implementations use simple, composable patterns rather than complex frameworks. Start with the simplest thing (often a single well-prompted LLM call, or a direct SDK loop); add a framework only when the task genuinely needs orchestration. Frameworks add abstraction layers that can hide the actual prompts/context and complicate debugging. Five patterns cover most needs without heavy machinery: prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer. (Anthropic: Building Effective Agents)


The comparison table

FrameworkWhat it's best forControl levelLearning curveSingle vs multi-agentCore primitive
LangChain (LCEL)Linear pipelines: RAG, chat, extractionMedium (some abstraction)Low–MediumSingle-agent (chains)Runnable + | pipe
LangGraphStateful workflows & agents; loops, branching, HITLHigh (explicit graph)Medium–HighBoth (nodes/subgraphs)Nodes + edges + State
StrandsLean model-driven agents; AWS/Bedrock; tool useMedium (model-driven loop)LowBoth (agents-as-tools)Agent + @tool
AutoGenOpen-ended, conversational, code-exec, debateLow–Medium (emergent)MediumMulti-agent (conversation)Conversable agents + GroupChat
CrewAIDeclarative role/task teams; pipelines & delegationMedium (declarative)LowMulti-agent (crews)Agents + Tasks + Process
OpenAI Agents SDKThin, typed agent runtime with handoffs/guardrailsMedium (few abstractions)LowBoth (handoffs)Agent + handoffs + guardrails
Direct SDK (no framework)Simplest patterns; max transparency (Anthropic's default)Highest (you own the loop)Low (concept) / High (build)Both (you wire it)messages.create() + your loop

Rules of thumb:

  • Linear task? LangChain chain (or just a direct call).
  • Needs loops / shared state / auditability? LangGraph.
  • Model-in-charge agent with tools, on AWS? Strands.
  • Emergent, conversational, code-heavy? AutoGen.
  • Nameable roles + workflow? CrewAI.
  • Thin typed agent with handoffs? OpenAI Agents SDK.
  • Not sure you need any of it? Start with a direct SDK loop (Anthropic).

Real code

The same idea in two apps — same domain, two framework choices.

App B — Strands + Bedrock (multi-agent orchestrator-as-tools) (orchestrator.py). Specialist agents are wrapped as @tools the orchestrator can call:

from strands import Agent, tool
from strands.models import BedrockModel
from agents.budget_agent import budget_agent
from agents.flights_agent import flights_search_agent
from agents.hotels_agent import hotels_profile_agent

bedrock_model = BedrockModel(
    model_id="anthropic.claude-3-5-sonnet-20241022-v2:0",
    region_name=os.getenv("AWS_REGION", "us-east-1"),
    guardrail_id=get_guardrail_id(),
)

@tool
def budget_agent_tool(query: str) -> str:
    """Handle budget and price-related queries."""
    return str(budget_agent(query))

@tool
def hotels_profile_agent_tool(query: str) -> str:
    """Handle hotel matching AND preference/date filtering."""
    return str(hotels_profile_agent(query))

# The orchestrator is itself an Agent; the specialists are its tools
orchestrator_agent = Agent(
    model=bedrock_model,
    system_prompt=ORCHESTRATOR_PROMPT,   # "coordinate these specialist agents..."
    tools=[budget_agent_tool, flights_search_agent_tool,
           hotels_profile_agent_tool, activities_agent_tool],
    conversation_manager=SummarizingConversationManager(summary_ratio=0.3),
)

def process_query(query: str) -> str:
    return str(orchestrator_agent(query))   # model decides which specialist tools to call

App A — LangChain LCEL (single-agent chain) (trip_planner.py):

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_groq import ChatGroq

llm = ChatGroq(model=GROQ_MODEL, temperature=0.75, api_key=GROQ_API_KEY)
recommend_chain = _RECOMMEND_PROMPT | llm | StrOutputParser()   # linear pipe
text = recommend_chain.invoke({"query": q, "context": ctx, "trip_style": style, ...})

And App A — LangGraph for the branching group-trip feature (group_trip_graph.py):

g = StateGraph(GroupTripState)
g.add_conditional_edges("classify_request", _route_after_request_type, {
    "followup": "retrieve", "new_suggestion": "retrieve",
    "create_task_node": "create_task_node",
})
graph = g.compile()   # explicit stateful control flow

Same problem — plan trips for people. App B models it as specialists an orchestrator calls (Strands, model-driven). App A models the single-user path as a linear chain (LCEL) and the group path as an explicit graph (LangGraph). Neither is "right" — they reflect different control/structure preferences.


Real-world example (App B vs App A — the tradeoff)

Both apps plan trips. The framework choice shaped their architecture:

  • App B (Strands + Bedrock, multi-agent). Four domain specialists (budget, flights, hotels+preferences, activities) plus an orchestrator. Strands' model-driven loop lets the orchestrator decide which specialists a query needs (an activities question skips budget). Wins: clean separation of expertise, easy to add a specialist, native Bedrock + guardrails, minimal orchestration code. Costs: multiple LLM hops per query (latency/cost), and behavior depends on the orchestrator's routing judgment. Notably, the code even ships a fallback when Strands isn't installed — a reminder that a multi-agent framework is a real dependency with operational weight.

  • App A (LangChain + LangGraph, mostly single-agent). The 1:1 chat path is a single LCEL chain (parse → retrieve → recommend) — one primary LLM call, fast and cheap. Only the genuinely branching feature (group chat: suggest vs follow-up vs book) escalates to a LangGraph state machine. Wins: low latency on the common path, transparent linear flow, escalate to a graph only where branching is real. Costs: less "autonomous" — the developer wires the control flow rather than letting a model orchestrate.

The interview-ready takeaway: App B bought flexibility and separation with more moving parts and hops; App A bought speed and transparency by staying single-agent until branching forced a graph. This is exactly Anthropic's guidance in practice — don't reach for multi-agent orchestration until the task demands it. Both are defensible; the right answer depends on whether the extra autonomy pays for its latency, cost, and complexity.


Interview questions companies actually ask

1. How do you choose an agent framework? [easy] Two axes: (1) control vs abstraction — how much of the loop you want to own, and (2) single vs multi-agent. Then match the task: linear → LangChain; stateful/branching → LangGraph; model-driven tool agent → Strands; conversational → AutoGen; role-based team → CrewAI; thin typed handoffs → OpenAI Agents SDK. Start simple and escalate only when complexity earns it. (Anthropic: Building Effective Agents)

2. LangChain vs LangGraph — when each? [easy] LangChain (LCEL) for linear pipelines (RAG, extraction, chat). LangGraph when you need loops, dynamic branching, shared mutable state, checkpointing, or human-in-the-loop. You use LangChain components inside LangGraph nodes.

3. Strands vs CrewAI vs AutoGen for multi-agent — contrast them. [medium] Strands: model-driven, "agents-as-tools" (an orchestrator calls specialists as tools) — lean, AWS/Bedrock-native. CrewAI: declarative roles + tasks + process (sequential/hierarchical). AutoGen: emergent conversation with speaker selection. Structure decreases and openness increases: CrewAI (most structured) → Strands → AutoGen (most emergent).

4. What is the OpenAI Agents SDK and where does it fit? [medium] A minimal agent runtime: Agent + tools, handoffs to other agents, guardrails (typed validation), sessions, and tracing — few abstractions, production-lean. Good when you want a thin, typed agent loop closer to direct-SDK simplicity but with handoffs and safety rails.

5. Explain the Anthropic principle that "the best agents don't rely on complex frameworks." [hard] Anthropic found that successful production agents use simple, composable patterns (prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer) rather than heavy frameworks, which add abstraction that hides prompts/context and complicates debugging. Start with the simplest solution — often a single LLM call or a direct SDK loop — and add orchestration only when demonstrably necessary. (Building Effective Agents)

6. Same domain, two frameworks: why might one team pick Strands and another LangChain? [hard] The Strands app wanted separated specialist expertise, Bedrock-native guardrails, and a model-orchestrated loop — accepting multiple LLM hops. The LangChain app wanted low latency and transparency on the common single-user path, escalating to LangGraph only for genuinely branching flows. The choice trades autonomy/flexibility against latency/cost/predictability.

7. What performance considerations differ across frameworks? [medium] Latency and cost scale with the number of LLM hops: multi-agent (AutoGen, CrewAI hierarchical, Strands orchestration) makes several calls per query; a single chain makes one. Watch transcript growth (O(T²) in group chats), context accumulation in sequential crews, and manager overhead in hierarchical modes. Predictability is highest with deterministic graphs/workflows, lowest with free-form conversation.

8. How do you migrate between frameworks safely? [medium] Keep prompts, tools, and business logic decoupled from the orchestration layer. Migrate one workflow at a time behind a stable interface, snapshot inputs/outputs as regression tests (golden traces), and A/B the new orchestration against the old before cutover. Because tools and prompts are portable, the graph/chain wiring is usually the only thing that changes.

9. When would you use no framework at all? [hard] When the task is a single call, a fixed few-step pipeline you can hand-roll, or when transparency/latency/dependency-weight matter more than convenience. A direct SDK loop (while stop_reason == "tool_use") gives full control of context and prompts — Anthropic's recommended default before adopting any framework.

10. Which framework for: a nightly research report with tool use and a fixed 4-step flow? [medium] A fixed 4-step flow with tools is a workflow, not an open-ended agent. Prefer a LangGraph workflow (or even an LCEL chain with tool-calling) for determinism and auditability, rather than a conversational AutoGen crew — the steps are known, so you don't need emergent behavior.


When to use / tradeoffs

  • Latency/cost: single chain (1 hop) ≪ multi-agent (N hops). Multi-agent buys separation and flexibility at the price of more calls.
  • Predictability/auditability: LangGraph workflows and CrewAI Flows are most deterministic; AutoGen conversation is least.
  • Learning curve: LangChain/Strands/CrewAI/OpenAI Agents SDK are quick to start; LangGraph is heavier.
  • Lock-in: Strands leans AWS/Bedrock; OpenAI Agents SDK leans OpenAI (both support other providers). LangChain/LangGraph/CrewAI/AutoGen are provider-agnostic.
  • The default: per Anthropic, start with the simplest pattern (direct SDK / single call) and add a framework only when orchestration is genuinely required. More agents ≠ better; it's more failure modes, cost, and latency.

There's no universally "best" framework — only the best fit for control level and single vs multi-agent needs, tempered by Anthropic's rule that simple, composable patterns beat complex frameworks. LangChain composes linear chains; LangGraph adds stateful graphs; Strands runs lean model-driven agents (great on Bedrock); AutoGen conversates; CrewAI declares role-based teams; the OpenAI Agents SDK offers a thin typed runtime. A LangChain/LangGraph app and a Strands app solve the same problem with different tradeoffs — the clearest evidence that framework choice is an engineering decision, not a fashion.

Related articles:

  • LangChain — LCEL chains and the Runnable interface.
  • LangGraph — stateful graphs, conditional edges, loops.
  • AutoGen — conversation-driven multi-agent.
  • CrewAI — role-based crews, sequential/hierarchical processes.
  • Building Effective Agents — Anthropic's simple, composable patterns.