Three tools, three different jobs
The trap is treating these as competitors on one axis. They are not. Each was built to solve a different layer of the stack, and many production systems run two of them together:
- LangChain is an orchestration toolkit — chaining prompt templates, model calls, parsers, memory, and tools into multi-step flows. Its team now builds LangGraph for stateful, graph-based agents, where the real production agent work has moved.
- LlamaIndex is a retrieval toolkit — ingestion, chunking, embedding, indexing, and query. Where LangChain orchestrates what happens between steps, LlamaIndex makes the retrieval step itself accurate and cheap.
- Raw API calls are not the primitive fallback they are sometimes made out to be. They are a stance on how much abstraction you actually need — and increasingly the one production teams are migrating back toward.
So the question is never “which framework wins.” It is: given what I am actually building, which layer of abstraction earns its cost?
The 2026 flip: abstraction that hides clarity
In 2022, wrapping tool calls and prompt chains reliably needed a framework because vendor APIs were inconsistent. By 2026 that reason has largely evaporated: OpenAI and Anthropic have absorbed tool calling, streaming, function schemas, and multi-turn memory into their native SDKs. The framework’s abstractions no longer hide meaningful differences — they hide the code path. And the costs of that are measurable, not rhetorical:
| Measure | Raw SDK | LlamaIndex | LangChain / Graph |
|---|---|---|---|
| Framework overhead / step | ~0 ms | ~6 ms | ~10–14 ms |
| Token overhead / query | 0 | ~1.6K | ~2.0–2.4K |
| Stack depth on error | 2–5 frames | 5–10 frames | 15–40 frames |
One documented comparison found LangChain costing 2.7× a native implementation on a basic RAG pipeline — abstraction consuming tokens the work did not need. Teams moving off it report 40–60% less code and 70–90% less framework maintenance. That is the flip: the default advice used to be “start raw, graduate to a framework.” The pattern worth watching now is the reverse.
Figures via MachineLearningMastery’s framework comparison (Jul 2026), collating several independent benchmarks. Treat them as directional, not lab-grade.
When each one genuinely earns it
None of this makes frameworks bad — it makes them situational. The value of an abstraction depends entirely on whether it hides complexity you actually face:
- Raw SDK wins for simple, one-shot, and latency-sensitive work: fastest to write, fastest to run, and when it breaks you know exactly where to look. Every message is a plain list you can inspect.
- LlamaIndex earns its dependency the moment retrieval gets real — multiple documents, chunking strategy, re-ranking, metadata filtering, hybrid search. Hand-rolling that costs ~30–40% more code and worse accuracy.
- LangGraph earns it for stateful agents: its checkpointing — pause mid-workflow, persist full state, resume hours later — is genuinely hard to build cleanly by hand.
The rule most teams converge on is not a single framework but a layered stack, and a discipline: start with the minimal option that handles today’s requirement, and add a framework when you hit the specific problem it was built for — not before. A retrieval problem is a reason to add LlamaIndex. A state problem is a reason to add LangGraph. Adding either early just buys maintenance for a future that may not arrive in the shape you guessed.
Why we took the raw road — and where it points next
This is the choice we already made. Our chatbot builder and Switchyard sit on a raw-SDK-plus-thin-wrapper stance on purpose: an allowlisted handler registry (a plain dispatch table — never eval), prompt assembly you can read in one file, and a zero-framework hot path so a client’s request is not paying 100–500 ms of orchestration tax per step. When a client needs their own data, we add a narrow, SSRF-guarded fetch — not a framework — and keep the code visible. That is the article’s recommendation, arrived at independently.
It leaves exactly one decision that every framework quietly hardcodes: the model string. LangChain puts it in ChatOpenAI(model=…); a raw agent puts it in the call. Either way it is a build-time constant — a guess frozen into the codebase. That guess is the one thing our measured routing turns into a number: the transparent quality-and-cost layer under the choice, not another wrapper around it. And the article’s honest signpost is our roadmap signpost too — the day a client bot needs real multi-document retrieval, that is the moment a purpose-built retrieval layer earns its place, and not a step sooner.