The Framework Question Every Agent Builder Faces
Pick the wrong abstraction for your agent infrastructure and you’ll spend more time fighting the framework than shipping features. LangGraph, CrewAI, and vanilla Python with tool-calling each represent a genuine philosophy about how agents should be built—and each has a real cost.
We evaluated all three against the same benchmark: a multi-step research agent that searches the web, summarizes sources, cross-references claims, and produces a structured report. Same task, same underlying model (GPT-4o), different scaffolding.
LangGraph: Power at the Price of Ceremony
LangGraph, built by the LangChain team, treats your agent as a directed graph of nodes and edges. Each node is a function; edges define control flow. State is typed and explicit. The graph is compiled before execution.
For our research agent, defining the graph looked like this: a search node, a summarize node, a cross_reference node, and a conditional edge that loops back to search if confidence is low. Visualizing that graph with graph.get_graph().draw_mermaid() produced an actual diagram in under two seconds.
Where LangGraph Excels
- Debuggability is exceptional. LangGraph Studio lets you pause execution at any node, inspect state, and replay from a checkpoint. For complex agents with 10+ steps, this is not a nice-to-have.
- Cycles and branching are first-class. If you need a reflection loop—where the agent evaluates its own output and retries—LangGraph handles it cleanly without recursive spaghetti.
- Persistence is built in. The
SqliteSaverorPostgresSavercheckpointers give you durable state with two lines of code.
Where LangGraph Hurts
The boilerplate is real. Defining a State TypedDict, wiring nodes, compiling the graph, and handling streaming output took roughly 180 lines for our research agent. A junior developer new to the framework spent 40 minutes debugging a ToolMessage sequencing error that an experienced LangGraph user would have spotted immediately.
The abstraction also leaks. When something breaks at the LangChain layer beneath LangGraph, you end up reading framework source code to understand why your tool call was serialized incorrectly.
Best for: Teams of 3+ building production agents where debuggability and state persistence matter more than time-to-first-working-prototype.
CrewAI: Fast Start, Fragile at Scale
CrewAI’s mental model is role-based: you define Agents with roles and goals, give them Tools, and assemble them into a Crew that executes Tasks. It reads almost like a product requirements document, which makes onboarding fast.
Our research agent became a three-agent crew: a ResearchAgent, a SummaryAgent, and a FactCheckerAgent. The whole definition fit in about 60 lines. A developer unfamiliar with any agent framework got it running in 25 minutes.
Where CrewAI Excels
- Onboarding velocity is unmatched. The declarative role syntax maps well to how product teams already think about workflows.
- Built-in delegation. Agents can hand off tasks to each other without manual routing logic, which simplifies crew design for straightforward sequential pipelines.
- Active ecosystem. CrewAI’s tool integrations—Serper, Browserbase, Firecrawl—work out of the box without adapter code.
Where CrewAI Hurts
The abstraction hides too much. When our FactCheckerAgent produced inconsistent output formats, tracing the failure meant reading through CrewAI’s internal task execution loop. There’s no equivalent of LangGraph Studio. Logging is verbose but unstructured—lots of print statements, not structured traces.
CrewAI also has a token overhead problem. The framework injects role context and task descriptions into every LLM call. On our research benchmark, CrewAI consumed 23% more tokens than the equivalent LangGraph implementation for identical outputs. At scale, that cost compounds.
Customizing control flow is awkward. If you want a task to conditionally skip based on an intermediate result, you’re working against the framework rather than with it.
Best for: Solo developers or small teams prototyping quickly, or use cases where sequential task pipelines map cleanly to the crew/agent model.
Vanilla Python with Tool-Calling: Boring, Brilliant, Brittle
The third approach: skip the frameworks entirely. Define your tools as functions with JSON schemas, pass them to the OpenAI API (or Anthropic, or whoever), and write your own loop that handles tool calls, appends results to the message history, and re-calls the model.
This is genuinely how many production agent systems at larger companies work. Stripe’s internal tooling, several Notion AI features, and reportedly portions of Cursor’s codebase follow this pattern.
Where Vanilla Python Excels
- Zero abstraction overhead. You see exactly what goes into the API call and exactly what comes back. Debugging is reading the request/response log.
- Minimal token overhead. No injected role context, no framework system prompts. Our vanilla implementation was 18% cheaper per run than LangGraph and 38% cheaper than CrewAI.
- Full control. Rate limiting, retry logic, custom logging, streaming—you build exactly what you need, nothing more.
Where Vanilla Python Hurts
You own everything. State management across multi-step agents requires discipline. Checkpointing requires building it. Handling parallel tool calls, managing message history length, and implementing retry with exponential backoff are each their own small project.
The research agent in vanilla Python took 220 lines and worked perfectly—until we added a web search tool that occasionally returned malformed JSON. Handling that failure gracefully required another 40 lines of error handling that LangGraph would have absorbed automatically.
Best for: Teams with strong Python engineering culture, high-volume production workloads where token cost matters, or situations where the framework overhead would exceed the complexity you’re managing.
Verdict
There’s no universal winner, but the choice is cleaner than the ecosystem drama suggests.
- Use LangGraph if you’re building anything with complex control flow, need production-grade debugging, or have a team that will maintain the agent over time. The ceremony pays dividends.
- Use CrewAI if you need a working prototype this week and your use case maps to sequential role-based tasks. Budget for refactoring when you hit the edges of the abstraction.
- Use vanilla Python if you have senior engineers who find frameworks more annoying than helpful, or if you’re running millions of agent calls and the token overhead is a real budget line.
The most common mistake is choosing a framework because it looked good in a demo. Choose based on what breaks first: for most teams building serious agents, that’s debuggability—which points to LangGraph.

