Choosing a web search tool in LangChain, LangGraph, LlamaIndex and the Vercel AI SDK

The tool your agent framework imports in its quickstart is not a recommendation. LangChain's search examples reach for Tavily, LlamaIndex's tool specs do the same, and the tutorials downstream of both copy the import. That convergence dates from a distribution decision rather than an evaluation: Tavily shipped first-party framework packages early, when most of its competitors still had nothing but a REST endpoint and a curl example. The default stuck.
The practical question is not which vendor is best in the abstract. It is which wrapper exposes the parameters you need, how the framework behaves when the search call fails, and how hard it is to swap the vendor out six months from now when pricing or ownership changes. Those three answers differ by framework, and they differ more than the vendors do. A search API you can reach through a first-party LangChain package, an official Vercel AI SDK tool and an MCP server is three different products in practice, because each surface hides a different subset of the API.
This guide covers the four runtimes where that decision actually gets made: LangChain, LangGraph, LlamaIndex and the Vercel AI SDK. For the vendor-level comparison that sits behind it – pricing, latency, ownership – see how to choose a search API for your AI product. This one is about the wrapper.
The default tool in every tutorial is a convention
Tavily's position is well earned as distribution and weakly evidenced as quality. It shipped a LangChain package and a LlamaIndex TavilyToolSpec (published as llama-index-tools-tavily-research) when the alternative was writing your own wrapper, and it returns snippets already shaped for an LLM rather than HTML that you have to clean. That made it the cheapest thing to try first, and the first thing tried is what ends up in the docs everyone copies.
Two things have changed since that convention formed. Tavily was acquired by Nebius in February 2026, which is a procurement question rather than a technical one but a real one if vendor independence is on your checklist. And the integration gap closed: Exa publishes an official Vercel AI SDK package, Firecrawl publishes both LangChain and LlamaIndex adapters plus its own AI SDK tools, and Linkup lists LangChain, LlamaIndex and the Vercel AI SDK in its own documentation. The argument that you should pick Tavily because everything else is more work has mostly expired.
What has not changed is that the tutorial ecosystem still assumes it. If your reason for using a given tool is that it appeared in the LangGraph example you started from, you have not made a decision yet.
What the framework wrapper hides
Every framework wrapper is a lossy projection of the underlying API. The vendor exposes fifteen parameters; the tool class exposes four, because the tool schema is also the description the model reads, and a fifteen-field schema makes tool selection worse.
The parameters that get dropped are usually the ones that matter at production volume:
Search depth and cost tiers. Tavily bills basic search at one credit and advanced at two, with the depth chosen per call. If your wrapper pins the depth, you have pinned your unit economics. The same applies to Exa's fast, auto and deep modes and to Linkup's standard and deep tiers, which differ by roughly an order of magnitude in published price.
Content versus snippets. Some APIs return full page content in the search response; others return a snippet and expect a second call. Whether the wrapper exposes that switch determines whether your agent makes one round trip or two per search, which is usually the largest single term in loop latency.
Domain filters and recency. Include and exclude domain lists, date ranges, and language filters are the cheapest quality lever available and the most commonly dropped from a wrapper's schema.
Raw payload access. When something goes wrong in production, you want the vendor's response as it arrived. Wrappers that flatten results into a string throw away the score, the published date and the URL metadata you need to debug a bad answer.
Before you commit to a wrapper, read its source. Most of these files are under two hundred lines, and they tell you in one pass which of the four parameters above you can still reach and which you would have to fork the package to get.
LangChain and LangGraph: tool nodes, retries and state
LangChain and LangGraph are one decision in practice. LangChain's AgentExecutor is deprecated in favour of create_agent and LangGraph's StateGraph, so a new agent that loops, retries or pauses is a LangGraph agent whether or not you call it one.
That matters for search because search is the tool most likely to fail transiently. Rate limits, upstream index timeouts and occasional 5xx responses are normal at volume, and the framework does not paper over them for you. LangGraph gives you three explicit levers, which LangChain documented together in a June 2026 post on fault tolerance: RetryPolicy for per-node retries, TimeoutPolicy for bounding a node's runtime, and node-level error handlers. Separately, ToolNode takes handle_tool_errors=True, which converts a tool exception into a ToolMessage the model can read and react to rather than an exception that kills the graph.
The distinction between those two is the one people get wrong. RetryPolicy is for failures the model cannot fix – a 429, a socket timeout. handle_tool_errors is for failures the model can fix, such as a malformed query argument. Retrying a malformed argument is how you burn budget: one thread on the LangChain forum describes an agent whose tool call JSON was truncated by a max_tokens limit, producing a validation error with no hint about the truncation, after which the agent retried the same call 249 times before the run was killed by hand. Whatever your search vendor, bound the retries.
There is also a state consideration specific to graphs. LangGraph executes parallel branches in supersteps, and its own documentation of that execution model is explicit that if any branch in a superstep raises, none of that superstep's state updates apply. If you fan out three search queries in parallel and one vendor call fails, you can lose the two that succeeded. LangGraph's documented mitigation is a per-node retry policy, which keeps the failure inside the node instead of letting it discard the superstep.
On the vendor side, LangChain is where the widest selection exists. Tavily, Exa, Firecrawl, Brave Search API, Serper.dev and SearchAPI.io all have wrappers, with SearchAPI.io also supporting Haystack. If your constraint is "must have a maintained LangChain tool", the constraint does not narrow the field enough to decide anything.
LlamaIndex: where web data enters ingestion
LlamaIndex frames the same vendors differently, and the framing is the useful part. In LangChain a search API is a tool the agent calls. In LlamaIndex it can be a tool spec, a reader that feeds the ingestion pipeline, or a retriever that sits behind a query engine, and those three are different products built on the same endpoint.
The tool-spec path is the familiar one: TavilyToolSpec converts to a tool list an agent can call at reasoning time. The reader path is the one that gets underused. Firecrawl's FireCrawlReader pulls pages into LlamaIndex documents that then go through your normal chunking, embedding and indexing, which means web content becomes part of the index rather than something the agent fetches live on every query. Jina AI's Reader fits the same slot at the lowest possible friction, since it turns a URL into markdown with a URL prefix and no SDK at all.
The choice between them is a caching decision disguised as an integration decision. Live search per query gives you freshness and pays per call forever. Ingesting into an index gives you cheap repeated reads and a staleness problem you have to schedule around. Most production RAG systems end up doing both: an indexed corpus for the stable material and a live search tool for anything time-sensitive. Deciding which side a source falls on is a question about how fast that source changes, not about which vendor you bought.
Vercel AI SDK: tool calls under an edge-runtime clock
The AI SDK is the runtime the framework-integration literature ignores, and it has the tightest constraints of the four.
Tool calling is a first-class parameter rather than an agent abstraction: you pass a tools object and a stopWhen condition, and the SDK runs the loop until the condition fires or the model returns text instead of a tool call. The step-count condition is the one that matters for search, and its name has moved between versions – AI SDK 5 introduced it as stepCountIs(n) and the current documentation shows isStepCount(n), with a documented default around twenty steps when you pass tools without specifying anything. A hasToolCall condition lets a sentinel tool end the turn. Whichever version you are on, set the condition explicitly. The failure mode of an unbounded search loop is a provider bill, not an exception.
The harder constraint is the runtime. Vercel's Edge runtime documentation states that a function must begin sending a response within 25 seconds to keep streaming, and can then stream for up to 300 seconds. A search-and-read loop that makes three sequential calls to a deep-research tier will not begin streaming in time. This is the practical reason to prefer a search API that returns page content in the same call as the results: one round trip fits comfortably inside the window, two might not, and a deep tier that takes tens of seconds per call does not belong in an edge request at all.
First-party support here is better than its reputation. Exa ships @exalabs/ai-sdk with a webSearch() tool that takes content options such as a character cap per result, a cache-age bound and per-result summaries. Firecrawl ships firecrawl-aisdk exposing scrape and map as AI SDK tools. Where no first-party package exists, the SDK's tool() helper over the vendor's REST client is a short file. What you do not get is LangChain's retry machinery, so the backoff is yours to write.
One further note on placement. LangChain.js pulls in Node built-ins across much of its integration surface, which is why edge deployment of it tends to require pinning specific submodule imports, while the AI SDK targets the edge runtime directly. That difference, rather than any measured benchmark, is why "run LangChain on the backend, the AI SDK at the edge" has become a common split.
What each vendor actually ships
The table records what each vendor's own documentation and the framework integration directories listed when checked in July 2026. A dash means the integration was not listed where I looked, not that it cannot be wired up by hand.
| Tool | LangChain | LlamaIndex | Vercel AI SDK | MCP server |
|---|---|---|---|---|
| Tavily | First-party package | TavilyToolSpec | – | Hosted, with OAuth |
| Exa | Listed | Listed | @exalabs/ai-sdk | Yes |
| Firecrawl | FireCrawlLoader | FireCrawlReader | firecrawl-aisdk | Yes |
| Linkup | Listed by vendor | Listed by vendor | Listed by vendor | Listed by vendor |
| Brave Search API | Listed | – | – | Yes |
| Serper.dev | Listed | – | – | – |
| SearchAPI.io | Native, plus Haystack | – | – | – |
| Jina AI | Reader URL prefix, no SDK needed | Reader | – | – |
| Parallel AI | – | – | – | – |
Parallel is the instructive row. It is a serious index with a Search API and a tiered Task API, and it did not appear in the framework integration lists I checked. That is a statement about its go-to-market, not its quality, and it is exactly the case where wrapping the REST client yourself costs an afternoon and buys you an option the tutorial ecosystem does not offer.
MCP as the framework-agnostic option, and what it costs
The Model Context Protocol is the answer to "I do not want to write this wrapper four times." Define the search tool once as an MCP server, and any MCP-capable client calls it: your LangGraph agent, your IDE, a chat client. Tavily, Firecrawl, Exa and Brave all publish MCP servers, and Tavily hosts one remotely with OAuth so there is nothing to run locally.
The cost is that you have taken on a protocol dependency with its own release cycle, and that cycle is currently moving. The MCP maintainers published a release candidate for revision 2026-07-28 on 21 May 2026 and describe it as the largest revision since launch, scheduled to publish on 28 July 2026. Per the project's own announcement, it makes the protocol core stateless, removes the initialize/initialized handshake and the session header in favour of self-contained requests and a server/discover RPC, moves Tasks out of the core into an official extension, and lifts tool inputSchema and outputSchema to full JSON Schema 2020-12. It also changes the error code for a missing resource from MCP's custom -32002 to the JSON-RPC standard -32602. The announcement states plainly that the release contains breaking changes.
None of that is a reason to avoid MCP. It is a reason to be honest about what you are buying: a shared tool definition in exchange for a migration you will have to perform on someone else's schedule. If exactly one runtime calls your search tool, the framework wrapper is less code and fewer moving parts. If three do, MCP starts paying for itself. Our guide to MCP and tool use covers the protocol side in more depth.
Keeping the vendor swappable
Whatever you pick, the one thing worth doing early is refusing to let the vendor's type signature spread through your codebase.
Define one interface of your own – a function that takes a query plus a small set of options you actually use, and returns a normalized result with url, title, text, published date and score. Implement it once per vendor. Register that function as the tool in whichever framework you are using. The framework wrapper then becomes an adapter you own rather than a dependency you inherit, and switching vendors is one file plus an eval run.
This is not a hypothetical concern in this category. Tavily changed ownership in February 2026. Pricing across AI search APIs has been recut repeatedly through 2026. Free tiers have appeared and disappeared. A team that imported TavilySearch in forty places has a refactor; a team with one search() function has a config change. Exa versus Tavily sets out how different two vendors in the same category can be once you look past the wrapper, which is the reason the seam is worth building before you need it.
Two implementation notes. Keep the tool description in your interface, not in the vendor package, because the description is a prompt and you will want to tune it. And keep the raw vendor response available on the returned object, because the day you need it is a day something is already broken.
Evaluating inside the framework, not in a notebook
The last mistake is evaluating retrieval in isolation. A notebook comparison of three search APIs on twenty queries tells you which returns better documents. It does not tell you which produces better answers inside your agent, and those diverge for reasons that have nothing to do with search quality.
Payload shape burns context. A vendor that returns 5,000 characters per result across ten results fills a context window that a snippet API would leave room in, and the model's answer degrades for a reason your retrieval metric never sees. Latency interacts with your runtime limits, which is decisive under the Edge runtime's 25-second first-byte requirement. And tool descriptions compete: if your agent also has a document retriever and an internal knowledge base tool, adding a general web search tool whose description overlaps theirs makes selection worse across all three, which is a cost the search vendor gets blamed for and did not cause.
The evaluation that actually decides this is boring. Take fifty real queries from your own traffic. Run each candidate vendor behind the same interface, in the same graph, with the same model. Score the final answer, not the retrieved set. Log latency at p95 rather than the mean, because the tail is what breaks your loop. Public benchmarks such as SimpleQA are a reasonable shortlist filter and a bad decision procedure, because they measure the API and you are shipping the system.
The short version
Pick the framework for the orchestration you need, not for the search tools it advertises: every serious vendor now has a wrapper somewhere, and the wrapper is rarely the binding constraint. In LangGraph, spend your effort on RetryPolicy and handle_tool_errors rather than on vendor selection, because transient search failures are the thing that will actually take your agent down. In the Vercel AI SDK, set the stop condition explicitly and prefer a search API that returns content in the same call, because the edge runtime's response window is not generous. In LlamaIndex, decide whether web data belongs in your index or in a live tool before you decide whose API supplies it. And in all four, put one interface of your own between the framework and the vendor, so that the next acquisition or pricing change is an afternoon rather than a quarter.
Frequently asked
- Which web search tool should I use with LangChain?
- Do I need LangChain to use a web search API in an agent?
- Can I use the same search vendor in LangChain and the Vercel AI SDK?
- Should I use an MCP server instead of a framework tool?
- How do I stop my agent from calling search too many times?
- How should I evaluate a search tool inside my agent?
Related guides
- MCP, Tool Use & How AI Agents Access the Web
Mar 3, 2026 · 9 min read
- Are web scraping MCP servers safe? Running a third-party web data server in production
Jul 27, 2026 · 13 min read
- Search API, crawl API or extract API: picking the right retrieval primitive
Jul 27, 2026 · 12 min read
Compare the tools mentioned
Weekly briefing – tool launches, legal shifts, market data.