The explosion of interest in AI agents has produced a rich ecosystem of frameworks, SDKs, and platforms. This chapter surveys the major options, their strengths, trade-offs, and ideal use cases.
A key piece of advice from Anthropic: start by using LLM APIs directly. Many agentic patterns can be implemented in just a few lines of code. Frameworks add convenience but also abstraction layers that can obscure what’s actually happening, make debugging harder, and tempt you into adding complexity you don’t need.
“If you do use a framework, ensure you understand the underlying code. Incorrect assumptions about what’s under the hood are a common source of customer error.” — Anthropic
LangChain is the most widely adopted framework for building LLM applications. It provides prebuilt agent architectures and model integrations. LangGraph, built on top of LangChain, provides low-level agent orchestration as a graph-based workflow system.
# See code/frameworks_langchain.py for the full implementation
from langchain.agents import create_agent
def get_weather(city: str) -> str:
"""Get weather for a given city."""
return f"It's 22°C and sunny in {city}"
agent = create_agent(
model="claude-sonnet-4-6",
tools=[get_weather],
system_prompt="You are a helpful assistant"
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "Weather in Paris?"}]}
)
CrewAI is a framework specifically designed for multi-agent collaboration. It models agent teams as “crews” with defined roles, goals, and processes.
# See code/frameworks_crewai.py for the full implementation
from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="Senior Researcher",
goal="Find comprehensive information on AI trends",
backstory="An experienced researcher with expertise in AI",
verbose=True
)
writer = Agent(
role="Technical Writer",
goal="Write clear, engaging content",
backstory="A skilled writer specializing in technology"
)
research_task = Task(
description="Research the latest AI agent frameworks",
agent=researcher,
expected_output="A detailed summary of current AI agent frameworks"
)
writing_task = Task(
description="Write a blog post based on the research",
agent=writer,
expected_output="A polished blog post about AI agent frameworks"
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential
)
result = crew.kickoff()
AutoGen is Microsoft’s framework for building multi-agent AI applications. It provides an event-driven architecture and supports both conversational and programmatic agent patterns.
# See code/frameworks_autogen.py for the full implementation
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def main():
model = OpenAIChatCompletionClient(model="gpt-4o")
agent = AssistantAgent("assistant", model)
result = await agent.run(task="Explain agentic programming patterns")
print(result)
asyncio.run(main())
Anthropic’s official SDK for building agents with Claude. Designed around Anthropic’s principles of simplicity and transparency.
AWS’s SDK for building agentic applications, designed for deployment on AWS infrastructure.
| Criterion | LangChain/LangGraph | CrewAI | AutoGen | Direct API |
|---|---|---|---|---|
| Learning Curve | Medium | Low | Medium | Low |
| Flexibility | High | Medium | High | Highest |
| Multi-Agent | Via LangGraph | Built-in | Built-in | Manual |
| Observability | LangSmith | Built-in logs | Built-in | Manual |
| Model Support | Many | Many | Many | One provider |
| Best For | General agents | Team collaboration | Research, distributed | Simple agents |
For many applications, you don’t need a framework. Here’s a minimal agent implementation using just an API client:
# See code/minimal_agent.py for the full implementation
import anthropic
client = anthropic.Anthropic()
def simple_agent(task, tools, max_turns=10):
messages = [{"role": "user", "content": task}]
for _ in range(max_turns):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)
# Check if done
if response.stop_reason == "end_turn":
return response.content[0].text
# Handle tool calls
if response.stop_reason == "tool_use":
messages.append({"role": "assistant", "content": response.content})
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result)
}]
})
return "Max turns reached"
This is ~30 lines of code and gives you a fully functional agent with tool use. No framework needed.
Navigation: