"Which agent framework should I use" is usually the second question. The first one is "which layer of the problem am I actually stuck on", and once you answer that the shortlist picks itself.
Because these tools do not compete as directly as the comparison posts suggest. LangGraph and the Vercel AI SDK overlap on maybe a third of their surface. CrewAI solves a problem the Vercel AI SDK does not attempt. And there is one layer that none of them touch, which is the layer that decides whether your agent has users.
The stack
Every production agent has six layers. Most frameworks own one or two and are honest about it.
| Layer | The question it answers | Who owns it |
|---|---|---|
| 1. Model access | How do I call a model, and switch providers later? | Provider SDKs, AI gateways |
| 2. Orchestration | Who decides the next step, and how do several agents hand off? | LangGraph, OpenAI Agents SDK, CrewAI, Mastra, Vercel AI SDK |
| 3. Knowledge | How does it answer from my documents? | LlamaIndex, vector databases, built-in RAG |
| 4. Runtime | Where does this run when my laptop is closed? | Your cloud, serverless platforms |
| 5. Channels | How does a human start a conversation with it? | Almost nobody |
| 6. Observability | What did it do, and why was it wrong? | LangSmith, Langfuse, Braintrust |
The framework wars happen at layer 2. Layer 5 is where projects die.
The orchestration frameworks
LangGraph models the agent as a state graph: nodes are steps, edges are transitions, and state is explicit. That is more ceremony than a loop for a simple agent, and exactly right when you need cycles, checkpoints, human approval in the middle, or the ability to resume a run that stopped three days ago. Its pairing with LangSmith for tracing is the most mature debugging story of the group. Python and TypeScript.
The OpenAI Agents SDK is the smallest thing that is still an agent framework: agents, handoffs between agents, guardrails, and tracing. Very little to learn, opinionated toward OpenAI models though not locked to them. If your architecture is "one agent that sometimes passes to a specialist agent", this is the least code you will write. Python and TypeScript.
CrewAI is built around roles. You define agents as job titles with goals and backstories, put them in a crew, and give the crew a task. It is genuinely good at the thing it is for, which is decomposing a piece of work across several specialists. It is a strange fit for a single support agent answering one customer, which is most production agents. Python.
The Vercel AI SDK is a TypeScript-first toolkit where the loop is a call with tools and a stopping condition rather than a graph. Its provider abstraction is the cleanest in the group: swapping OpenAI for Anthropic is one import. Streaming and the React bindings are best in class, which matters if the agent has a web UI and matters not at all if it lives on WhatsApp. TypeScript.
Mastra is the most batteries-included TypeScript option: agents, workflows, RAG, evals and a local dev playground in one package. Good when you want structure without assembling five libraries. TypeScript.
Pydantic AI brings typed, validated structured output to Python agents, which is the right instinct if your tools return data that has to be correct rather than merely plausible.
LlamaIndex started as a retrieval library and grew agent workflows. If your agent's job is mostly "answer accurately from a large document corpus", starting here rather than bolting RAG onto an orchestration framework is often less work.
No framework deserves a row in this table. A loop with tool calls is about thirty lines, shown in full in how to build an AI agent. For a single agent with four tools, the raw provider SDK is frequently the correct engineering decision, and you can adopt a framework the day you need graphs or handoffs.
Picking one
| If your problem is | Start with |
|---|---|
| A single agent, a handful of tools, TypeScript | Vercel AI SDK, or no framework |
| A single agent, a handful of tools, Python | OpenAI Agents SDK, or no framework |
| Long-running work that pauses for human approval | LangGraph |
| Several specialists collaborating on one task | CrewAI |
| Answering accurately from a big document corpus | LlamaIndex |
| You want one package with agents, RAG and evals | Mastra |
| Tool outputs must be type-safe | Pydantic AI |
| You cannot explain why it answered that | Add LangSmith or Langfuse, whatever else you chose |
Notice that none of those rows say "and this is how customers reach it".
Layer 5, and why it is empty
Every framework above assumes a caller. You wrap the agent in an HTTP endpoint, and something calls it.
In a demo, that something is a web chat widget. In production, it needs to be where your customers already are: WhatsApp, SMS, email, a phone call. That is not a wrapper. Each of them is its own integration with its own rules:
- WhatsApp: Meta Business verification, a webhook with signature verification, template approval before you can start a conversation, and a 24 hour window after the customer's last message inside which you can reply freely. Outside it, only approved templates.
- SMS: A2P 10DLC registration in the US before carriers will deliver, per-country sender rules everywhere else, and segment counting that changes when someone uses an emoji.
- Email: DKIM, SPF and DMARC, a sending domain whose reputation you can destroy in a week, plus threading and attachment handling on the way back in.
- Voice: a media pipeline where speech recognition, the model and speech synthesis all have to finish inside about a second, or the caller thinks the line dropped.
- Telegram, Instagram, Messenger: three more identity models, three more webhook formats.
Building this once is a quarter of engineering. Building it for four channels is most of a year. It is also completely undifferentiated: no customer has ever chosen a product because its DKIM records were well configured.
This is the layer Zavu owns, and the reason to be precise about it: Zavu is not a competitor to LangGraph or the Vercel AI SDK. It is layers 4 and 5, plus optional 1, 2, 3 and 6 if you want them.
Two ways to combine them
You keep your framework, Zavu carries the messages
Your agent stays exactly as it is, in whatever framework you already chose. Zavu delivers the inbound message and sends the reply.
You do not hand-write that adapter. Install the skills and the CLI once, then say what you want:
terminalnpx skills add zavudev/zavu-skills npx zavudev@latest login
> Wrap my existing LangGraph agent so it answers on WhatsApp. Inbound messages should feed the graph, and the final answer should go back on the same channel. Deploy it and test it.
The skills carry the channel rules your coding agent has never seen: the 24 hour window, signature verification, which events exist. What it writes looks like this:
TypeScriptimport { defineFunction } from "@zavudev/functions" import { generateText } from "ai" import { openai } from "@ai-sdk/openai" import Zavudev from "@zavudev/sdk" const zavu = new Zavudev({ apiKey: process.env.ZAVU_API_KEY }) export default defineFunction({ on: ["message.inbound"], handler: async (event) => { const { text } = await generateText({ model: openai("gpt-4o-mini"), prompt: event.data.text, tools: myTools, }) await zavu.messages.send({ to: event.data.from, text }) }, })
The Vercel AI SDK is running your loop. Zavu handles the webhook, the signature, the channel, the 24 hour window and the delivery. Declare ai and @ai-sdk/openai in package.json and they are installed at build time. ZAVU_API_KEY is provisioned automatically when the function is created, so the callback needs no setup.
The same shape works with LangGraph, CrewAI or a bare provider SDK, and it works from your own infrastructure too: point a webhook at your server instead of running inside a Zavu Function.
You skip layer 2 as well
If your agent is a prompt plus tools rather than a graph, you can declare it and let the runtime own the loop. Again, you describe it:
> Build a support agent for an online store. One tool that looks up an order by ID against our API. Two sentences maximum per reply, never invent a delivery date.
And review what comes back:
TypeScriptimport { defineAgent, defineTool } from "@zavudev/functions" defineAgent({ senderId: process.env.SENDER_ID!, name: "Nora", provider: "zavu", model: "openai/gpt-4o-mini", prompt: "You are Nora, support for an online store. Two sentences maximum.", }) defineTool({ name: "lookup_order", description: "Get the status of a customer order. Use when they ask where their package is.", parameters: { type: "object", properties: { orderId: { type: "string" } }, required: ["orderId"], }, handler: async ({ orderId }) => { const res = await fetch() return res.json() }, })https://api.example.com/orders/${orderId}
npx zavudev deploy and it is answering on every channel the sender has.
The trade is real and worth stating plainly. You give up graph-shaped control flow and multi-agent handoff. You get the loop, per-contact conversation state, knowledge base retrieval, execution records and every channel, without writing any of it. The provider field takes openai, anthropic, google and mistral with your own key, so this is not a lock-in on models.
When option two is wrong: you need a human approval step in the middle of a run, several agents negotiating, or a workflow that pauses for two days and resumes. Use LangGraph and option one.
The question that actually predicts success
After all of this, the framework choice is rarely what determines whether an agent works. Six months of watching them ship, the pattern is consistent: agents succeed or fail on their tools and their channel.
Good tools with a mediocre framework beat a beautiful graph with vague tool descriptions. And an agent on WhatsApp with a plain loop gets ten times the usage of an agent with perfect multi-agent orchestration behind a widget nobody clicks.
Pick the framework in an afternoon. Spend the week on the tools and on being where your customers already are.
Keep reading
- How to build an AI agent: the loop from scratch, then deployed.
- What is an AI agent: the definition and the four parts.
- AI agent vs chatbot: the decision before the framework decision.
- Build AI agents with your coding agent: the CLI and skills workflow.
- WhatsApp AI agents with Next.js, NestJS or FastAPI: layer 5, framework by framework.