M19 notes: Build agents in many frameworks (the one idea)
The one idea: every agent framework, LangGraph, CrewAI, AutoGen, smolagents, LlamaIndex, the OpenAI Agents SDK, the Claude Agent SDK, even no-code n8n, wraps the same loop you wrote by hand in M9. Learn the loop once and every framework is just a new set of names for it.
1. The loop under all of them
ask the model ──▶ does it want a tool?
│ yes → run the tool, give the model the result ──┐
│ no → return the final answer │
└──────────────◀──────────────────────────────────┘
That's it. That's an agent (M9). 01_from_scratch.py is this loop in ~20 lines of plain Python with
the Anthropic SDK. A framework's job is to write this loop for you: and add conveniences: memory,
retries, streaming, multi-agent coordination, tracing, a visual canvas. None of them change the idea.
Analogy. Every car has an engine, wheels, and a steering wheel. A pickup, a sports car, and a minivan feel completely different to drive, but you already know how to drive, so you can get in any of them. Frameworks are the body styles; the loop is the engine.
2. The same agent, nine ways
We build one agent everywhere: a tool multiply(a, b), asked "What is 23 times 17?". Here's how
each framework spells the three steps, define a tool, make the agent, run it:
| Framework | Define tool | Make agent | Run |
|---|---|---|---|
| From scratch | a tools=[{json schema}] + a Python fn |
the while loop |
call run() |
| LangGraph | @tool on a fn |
create_react_agent(model, [tool]) |
agent.invoke({...}) |
| CrewAI | @tool("name") |
Agent(role, goal, tools, llm) + Task + Crew |
crew.kickoff() |
| AutoGen | a plain Python fn | AssistantAgent(model_client, tools=[...]) |
await agent.run(...) |
| Claude Agent SDK | @tool(...) + create_sdk_mcp_server |
ClaudeAgentOptions(mcp_servers=...) |
query(prompt, options) |
| smolagents | @tool (docstring schema!) |
ToolCallingAgent(tools, model) |
agent.run(...) |
| LlamaIndex | FunctionTool.from_defaults(fn) |
FunctionAgent(tools, llm) |
await agent.run(...) |
| OpenAI Agents SDK | @function_tool |
Agent(model, tools) |
Runner.run_sync(...) |
| n8n (no-code) | a "Code Tool" node | an "AI Agent" node + chat-model node | click Execute |
Read the table top-to-bottom: the columns are identical in meaning. That's the lesson.
3. Two things that bite beginners
The model string isn't the same everywhere. Frameworks that talk to Claude through LiteLLM
(CrewAI, smolagents, OpenAI Agents SDK) need the provider prefix: anthropic/claude-opus-4-8. The ones
with a native Anthropic integration (from-scratch, LangGraph, AutoGen, Claude Agent SDK, LlamaIndex)
take the bare claude-opus-4-8. Same model, different label.
Python version + install drift. Several frameworks don't ship wheels for the newest Python yet, use Python 3.10-3.12. And these libraries move fast: an import path can change between versions. If something breaks, the pattern (model + tools + run) still holds; just check the current docs for the new name. (This is exactly why M9 says "build the loop by hand first.")
4. How to choose (the actually-useful part)
- Just need one agent with tools? Any of them. LangGraph if you want explicit graph control; LlamaIndex if you're already doing RAG there; the Claude Agent SDK if you want to reuse the MCP tools you built in M16; smolagents if you want minimal.
- Need a team, agents talking to / handing off to each other? CrewAI (role-based crews) and AutoGen (conversational multi-agent) are built for that. They map straight onto the orchestration shapes from M18 (pipeline / router / fan-out / hierarchical).
- Want non-developers to build or edit the agent? n8n (visual canvas, connects to hundreds of apps), great for ops and automation.
- Production? Whatever your team can operate and debug. Add tracing/observability and the M10 guardrails + M18 oversight (human-in-the-loop) regardless of framework.
Don't collect frameworks. Pick one or two, go deep, and keep
01_from_scratch.pyin your head so you always know what the framework is doing on your behalf.
5. Why "from scratch" still matters
When an agent misbehaves, loops forever, ignores a tool, burns tokens, the framework's abstraction is
exactly what's in your way. Knowing the raw loop lets you reason about where it went wrong (bad tool
schema? model never emitted tool_use? result fed back wrong?) no matter which framework wraps it.
Words you'll hear
Framework vs. from-scratch, ReAct loop, tool / function calling, LiteLLM (a router that
gives many providers one interface), single-agent vs. multi-agent / crew, no-code / low-code
(n8n), provider prefix (anthropic/…). Full definitions in the glossary.