MODULE 5  Β·  AI Agents

Agent Frameworks: LangChain, CrewAI, AutoGen, Smolagents β€” The Real Story

Everyone has an opinion on agent frameworks. 'LangChain is bloated.' 'CrewAI is magical.' Here's what actually matters.

πŸ“… Mar 2026
⏱ 10 min read
🎯 Episode 34 of 98
LangChainCrewAIAutoGenFrameworks
In this episode

Everyone has an opinion on agent frameworks. "LangChain is bloated." "CrewAI is magical." "Just write raw API calls." "AutoGen is the future."

Here's the truth: every framework does the same thing β€” LLM + tools + loop. What differs is how much abstraction they add, how they handle multi-agent orchestration, and how much they fight you when you need something custom.

Let's open the hood on each one.

What Agent Frameworks Actually Do

Strip away the branding and docs, and every framework provides:

Tool registration β€” Define functions the LLM can call

The agent loop β€” Run think β†’ act β†’ observe repeatedly

Message management β€” Handle conversation history

Error handling β€” Retry failed tool calls, handle parsing errors

Orchestration β€” Coordinate multiple agents (some frameworks)

That's it. If you can build those five things yourself in 100 lines of Python, do you need a framework? Maybe. Depends on how complex your agents get.

⚑

LangChain

The OG. The one everyone has opinions about.

LangChain was the first major agent framework (2022). It tries to be everything β€” chains, agents, memory, retrieval, output parsing, callbacks, streaming. This ambition is both its strength and its biggest criticism.

Architecture

LangChain Stack:

β”œβ”€β”€ langchain-core # Base abstractions (Runnables, messages)

β”œβ”€β”€ langchain # Chains, agents, retrieval

β”œβ”€β”€ langchain-community # Third-party integrations

β”œβ”€β”€ langchain-openai # OpenAI provider

β”œβ”€β”€ langchain-anthropic # Anthropic provider

β”œβ”€β”€ langgraph # Graph-based agent orchestration

└── langsmith # Observability & tracing

A LangChain Agent

python

from langchain_openai import ChatOpenAI

from langchain.agents import create_tool_calling_agent, AgentExecutor

from langchain_core.tools import tool

from langchain_core.prompts import ChatPromptTemplate

Define tools

@tool

snippet
code
def search(query: str) -> str:
"""Search the web for information."""
    return web_search(query)

@tool

snippet
code
def calculate(expression: str) -> str:
"""Evaluate a mathematical expression."""
    return str(eval(expression))

Create agent

snippet
code
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful research assistant."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}")

])

snippet
code
agent = create_tool_calling_agent(llm, [search, calculate], prompt)
executor = AgentExecutor(agent=agent, tools=[search, calculate], verbose=True)

Run

snippet
code
result = executor.invoke({"input": "What's India's GDP per capita in USD?"})

LangGraph (The Real Power)

LangChain's newer LangGraph is where it gets interesting. Instead of a linear agent loop, you define a graph of states and transitions:

python

from langgraph.graph import StateGraph, MessagesState

def research_node(state: MessagesState):

example
code
"""Agent does research"""
    response = llm.invoke(state["messages"])
    return {"messages": [response]}

def review_node(state: MessagesState):

example
code
"""Agent reviews research"""
    response = reviewer_llm.invoke(state["messages"])
    return {"messages": [response]}

def should_continue(state: MessagesState):

example
code
last = state["messages"][-1]
    if last.tool_calls:
        return "tools"  # Continue to tool execution
    return "review"     # Move to review

Build the graph

snippet
code
graph = StateGraph(MessagesState)

graph.add_node("research", research_node)

graph.add_node("review", review_node)

graph.add_node("tools", tool_node)

graph.add_edge("start", "research")

graph.add_conditional_edges("research", should_continue)

graph.add_edge("tools", "research")

graph.add_edge("review", "end")

snippet
code
app = graph.compile()

Verdict

Pros Cons

Massive ecosystem, integrations for everythingAbstraction overload β€” too many layers
LangGraph is genuinely powerful for complex workflowsAPI changes frequently, docs lag
LangSmith tracing is excellent for debuggingSimple tasks feel over-engineered
Largest community, most tutorialsLearning curve is steep

Use when: You need complex, stateful workflows with many integrations. LangGraph is the right choice for production-grade multi-step agents.

Skip when: You're building a simple single-agent tool caller. The overhead isn't worth it.

πŸ”§

CrewAI

Multi-agent made simple.

CrewAI's pitch: define agents as "crew members" with roles, give them a mission, and let them collaborate. It's the most intuitive multi-agent framework.

Architecture

CrewAI Concepts:

β”œβ”€β”€ Agent β†’ A persona with role, goal, backstory, tools

β”œβ”€β”€ Task β†’ A specific assignment for an agent

β”œβ”€β”€ Crew β†’ A team of agents working on tasks

β”œβ”€β”€ Process β†’ How tasks are executed (sequential, hierarchical)

└── Tools β†’ Functions agents can use

A CrewAI Crew

python

from crewai import Agent, Task, Crew, Process

Define agents

snippet
code
researcher = Agent(
role="Senior Research Analyst",
    goal="Find comprehensive, accurate information on the given topic",
    backstory="You're a seasoned researcher with 15 years of experience "
              "in technology analysis. You're thorough and fact-driven.",
    tools=[search_tool, scrape_tool],
    llm="gpt-4o"

)

snippet
code
writer = Agent(
role="Technical Content Writer",
    goal="Write engaging, technically accurate blog posts",
    backstory="You're a developer-turned-writer who makes complex topics "
              "accessible. Your writing is concise, uses code examples, "
              "and avoids fluff.",
    tools=[],
    llm="gpt-4o"

)

Define tasks

snippet
code
research_task = Task(
description="Research the current state of AI agents in 2025. "
                "Focus on frameworks, patterns, and production use cases.",
    expected_output="Detailed research notes with sources",
    agent=researcher

)

snippet
code
writing_task = Task(
description="Write a 1500-word blog post based on the research. "
                "Include code examples and practical takeaways.",
    expected_output="Complete blog post in markdown",
    agent=writer

)

Create and run crew

snippet
code
crew = Crew(
agents=[researcher, writer],
    tasks=[research_task, writing_task],
    process=Process.sequential,  # Tasks run in order
    verbose=True

)

snippet
code
result = crew.kickoff()

Verdict

Pros Cons

Intuitive role-based designLess flexible than LangGraph for custom flows
Easy multi-agent setupLimited control over agent communication
Great for content pipelinesCan be expensive (multiple agents = multiple LLM calls)
Fast to prototype"Backstory" adds tokens but unclear value

Use when: You have clear roles and sequential/hierarchical tasks. Content creation, research pipelines, analysis workflows.

Skip when: You need fine-grained control over agent state, custom routing, or complex conditional logic.

πŸ“Š

snippet
code
AutoGen (Microsoft)

The academic powerhouse.

AutoGen is Microsoft's framework focused on multi-agent conversations. Its key idea: agents communicate through natural language conversations, and you define the rules for who speaks when.

Architecture

AutoGen Concepts:

β”œβ”€β”€ ConversableAgent β†’ Base agent that can chat

β”œβ”€β”€ AssistantAgent β†’ LLM-powered agent

β”œβ”€β”€ UserProxyAgent β†’ Human-in-the-loop or auto-executor

β”œβ”€β”€ GroupChat β†’ Multi-agent conversation

└── GroupChatManager β†’ Controls turn-taking in group chat

An AutoGen Conversation

python

from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager

Define agents

snippet
code
coder = AssistantAgent(
name="Coder",
    system_message="You write Python code. Only respond with code blocks.",
    llm_config={"model": "gpt-4o"}

)

snippet
code
reviewer = AssistantAgent(
name="Reviewer",
    system_message="You review code for bugs, security issues, and style. "
                   "Be critical but constructive.",
    llm_config={"model": "gpt-4o"}

)

snippet
code
executor = UserProxyAgent(
name="Executor",
    human_input_mode="NEVER",  # Auto-execute, no human approval
    code_execution_config={"work_dir": "coding"}

)

Set up group chat

snippet
code
group_chat = GroupChat(
agents=[coder, reviewer, executor],
    messages=[],
    max_round=10

)

snippet
code
manager = GroupChatManager(
groupchat=group_chat,
    llm_config={"model": "gpt-4o"}

)

Start the conversation

executor.initiate_chat(

example
code
manager,
    message="Write a Python script that scrapes HackerNews top stories "
            "and saves them to a CSV file."

)

The agents literally have a conversation β€” Coder writes code, Executor runs it, Reviewer critiques, Coder revises. The GroupChatManager decides who speaks next.

Verdict

Pros Cons

Natural conversation-based collaborationConversations can meander and waste tokens
Strong code execution supportComplex setup for simple tasks
Academic rigor, well-researchedTurn-taking can be unpredictable
Good for iterative refinementLess intuitive than CrewAI's role model

Use when: Tasks benefit from iterative discussion β€” code review, collaborative writing, complex problem-solving where multiple perspectives matter.

Skip when: You want predictable, fast pipelines. AutoGen conversations can be verbose and expensive.

Smolagents (Hugging Face)

The minimalist.

Smolagents is Hugging Face's answer to framework bloat. Its philosophy: agents should be simple, transparent, and easy to understand. The entire agent loop is ~200 lines of code.

Architecture

Smolagents Concepts:

β”œβ”€β”€ ToolCallingAgent β†’ Standard tool-calling agent

β”œβ”€β”€ CodeAgent β†’ Writes and executes Python code as actions

snippet
code
β”œβ”€β”€ Tool              β†’ Simple function wrapper

└── ManagedAgent β†’ Agent that can be used as a tool by another agent

A Smolagent

python

from smolagents import CodeAgent, Tool, HfApiModel

Define a tool

class SearchTool(Tool):

example
code
name = "web_search"
    description = "Search the web for information"
    inputs = {"query": {"type": "string", "description": "Search query"}}
    output_type = "string"
example
code
def forward(self, query: str) -> str:
        return web_search(query)

Create agent

snippet
code
agent = CodeAgent(
tools=[SearchTool()],
    model=HfApiModel("Qwen/Qwen2.5-72B-Instruct"),
    max_steps=10

)

Run

snippet
code
result = agent.run("Find the latest Python version and its release date")

The CodeAgent Difference

Smolagents' CodeAgent is unique β€” instead of generating JSON tool calls, it writes Python code as its action:

python

Standard tool calling (other frameworks):

Action: search(query="latest Python version")

Smolagents CodeAgent:

The agent writes actual Python code:

snippet
code
results = web_search("latest Python version 2025")
version = results[0]["title"].split("Python ")[1]
print(f"Latest version: {version}")

This is more flexible β€” the agent can use variables, loops, conditionals, and string manipulation directly. No need to create a tool for every little operation.

Verdict

Pros Cons

Dead simple, easy to understandFewer integrations
CodeAgent is genuinely innovativeSmaller community
Minimal dependenciesLess battle-tested in production
Transparent β€” you can read the entire sourceLimited orchestration for multi-agent

Use when: You want simplicity and transparency. Great for learning, prototyping, and when you want to understand exactly what your agent is doing.

Skip when: You need complex multi-agent orchestration or extensive third-party integrations.

πŸ’‘

Head-to-Head Comparison

Feature LangChain/LangGraph CrewAI AutoGen Smolagents

Complexity High Medium Medium-High Low

Multi-agentLangGraph (powerful)Built-in (simple)GroupChat (flexible)ManagedAgent (basic)
Learning curveSteepGentleModerateMinimal
Integrations700+50+30+20+
Best forComplex workflowsRole-based pipelinesIterative discussionSimple agents, learning
Code executionVia toolsVia toolsBuilt-in sandboxCodeAgent (native)
ObservabilityLangSmithBasic loggingBasic loggingBasic logging
Production readyYesGrowingYesEarly
Stars (GitHub)105K+25K+40K+15K+

πŸ”¬

When to Skip Frameworks Entirely

Sometimes the best framework is no framework:

python

A complete agent in 40 lines, no framework

from openai import OpenAI

import json

snippet
code
client = OpenAI()
tools = [...]  # Your tool definitions
def run_agent(task, max_steps=15):
messages = [
        {"role": "system", "content": "You are a helpful agent. Use tools to complete tasks."},
        {"role": "user", "content": task}
    ]
for _ in range(max_steps):
        response = client.chat.completions.create(
            model="gpt-4o", messages=messages, tools=tools
        )
        msg = response.choices[0].message
        messages.append(msg)
if not msg.tool_calls:
            return msg.content
for tc in msg.tool_calls:
            result = execute_tool(tc.function.name, json.loads(tc.function.arguments))
            messages.append({"role": "tool", "tool_call_id": tc.id, "content": str(result)})
return "Max steps reached"

Use raw API when:

Your agent is simple (1-3 tools, single agent)

You want full control over every decision

Framework abstractions are getting in your way

You're optimizing for cost or latency

Use a framework when:

Multi-agent coordination

Complex state management

You need built-in error handling and retries

Your team needs shared conventions

πŸ›‘οΈ

Practical Takeaways

All frameworks do the same thing β€” LLM + tools + loop, with varying abstraction levels

LangGraph for complex workflows β€” the most powerful orchestration, but steep learning curve

CrewAI for role-based teams β€” intuitive, fast to prototype, great for content pipelines

AutoGen for iterative discussion β€” agents that argue and refine, good for code review

Smolagents for simplicity β€” minimal, transparent, great for learning

Raw API for simple agents β€” 40 lines of code beats a framework when your needs are simple

πŸ“¦

What's Next?

Episode 35: Agent Failure Modes β€” Infinite loops, cost explosions, hallucinated actions, tool abuse. Agents can go wrong in spectacular ways. We'll catalog the failure modes, how to detect them, and how to build guardrails that keep your agent (and your wallet) safe.

← Previous

Ep 33: Agent Memory

Next β†’

Ep 35: Agent Failure Modes

Next: Episode 35 β€” Agent Failure Modes

A chatbot that gives wrong answers is annoying. An agent that takes wrong actions is dangerous. Here's how they fail.

This is part of a 98-episode series covering AI engineering from tokens to production deployment.

← Previous Ep 33: Agent Memory: Why Your AI Keeps Forgetting (And How to …