We asked Claude Sonnet 5.5 to write a file that redirects users without a session cookie to /login. Our test project had Next.js 16.4.1 installed. Claude Sonnet 5.5 wrote middleware.ts for us, adding a tiny note at the bottom about Next.js 16. With the docs tool, the model wrote proxy.ts, the name used by Next.js 16. It also used the list of installed packages to determine that the project was running Next.js 16.4.1. This single tool call took about 600 ms. The agent is a tiny Next.js chat app that uses AI SDK 7. It reads your installed versions, then searches the Context7 docs for the versions. It then streams each search to the chat page so you can see what docs were read.
We checked the output of 486 answers from nine models through tsc, including GPT-5.6, DeepSeek V4 Pro, Kimi K3, GLM-5.3 and Qwen3.8. 63% of answers from the eight current models passed with the installed versions in the prompt and 92% with the docs tool.
How the agent picks the right docs
An AI SDK agent in Next.js has three parts: a ToolLoopAgent with zod-typed tools in a server file, a route handler that streams it with createAgentUIStreamResponse, and a page that renders text and tool calls with useChat. Our agent adds one docs tool and the installed versions to that setup.
When the server starts up, it reads the versions of the packages in node_modules. These versions are listed as part of the agent's instructions, so the model knows it's writing code for, say, Next.js 16. They're also passed to the docs tool so that when the model looks something up, it gets the right version. The docs tool then makes a request to the Context7 Search API for that library and major version. The model takes the snippets returned by the docs tool and then answers the question. The chat page shows the lookups as they happen.
There are five files in the app:
lib/versions.ts: reads the version of each package installed innode_modules.lib/search-docs.ts: the docs tool.lib/agent.ts: the agent.app/api/chat/route.ts: streams the agent's output to the browser.app/page.tsx: the chat page.
Install the packages first:
How do I pin docs to the versions my project uses?
Get each package’s version from its own package.json file inside node_modules and pass the library and version to the docs search. This version will be the one your code runs against, as the version in node_modules is the one that gets used.
Your project's package.json holds a range such as ^16.0.0, and that range allows any 16.x release. The installed copy tells you the exact release. This file reads it for each package the agent should know about, and maps each npm name to its Context7 library ID:
In our project, readVersions() returned:
To add a library, add its npm name and its Context7 ID to the map. The ID can be obtained by looking up the library on context7.com.
Write the searchDocs tool
The tool receives two inputs from the model: a short query and, optionally, the package name if the question asks about one package. This package name is a zod enum based on the map above, so only libraries you've listed can be used. The API key and versions are provided by the server through the tool's context and cannot be seen or set by the model.
The tool sends only the major version. Our first version sent the exact installed version, and every search came back with current docs instead of versioned ones. Context7 indexes releases, so a patch version like 7.0.141 often has no exact match. When there is no match, the API starts its answer with a version note and serves current docs. Here is what each version string returned:
All three libraries resolved to a major version, but only some resolved to a minor version. (4.6 for zod, 7.0 for the AI SDK, and missed for Next.js 16.4.)
The tool also sends the library ID, such as /vercel/next.js, instead of a name like "Next.js". The ID names exactly one library, and the version only applies to that library, so the search can't drift to another package with a similar name.
Errors are returned as text, not as thrown exceptions. If no docs matched, a 404 error is returned and the model can choose to try a shorter query. The language hint asks for TypeScript examples to be returned first, but it's only a preference so if the docs don't have code in them they'll still show up.
Give the agent the versions and the API key
This agent is a ToolLoopAgent. At the time of module load, it reads the versions and writes them into instructions as a list. It also provides the same versions and the Context7 key to the tool via toolsContext. Each tool receives its own entry in tool context only; another tool that you might add later won't be able to access the Context7 key.
The above example uses OpenRouter with OPENROUTER_API_KEY. You can replace that model with any AI SDK model, such as an AI Gateway string like "anthropic/claude-sonnet-5.5".
By default, a ToolLoopAgent runs for up to 20 steps. A documentation lookup takes about one step for the search, one step to answer the question, and can leave room for a retry, so a limit like isStepCount(5) should be enough. Every step is a full model call that passes the previous tool results, so lower step count limits can also help contain the cost of tokens.
The Search API works without a key, but these requests are for testing only and rate-limited by IP address. For production use, set CONTEXT7_API_KEY. The free plan includes 1,000 requests per month, and each tool call is one API call.
Stream tool calls to the chat page
The route handler takes the chat messages from the browser and hands them to the agent. createAgentUIStreamResponse streams text and tool calls back in the format useChat reads:
On the page, useChat takes the DocsAgentUIMessage type from the agent file. Each tool call then arrives as a part with the type tool-searchDocs, and TypeScript knows its input and output. While the search runs, the page shows which docs it is searching. When the result arrives, the page reads the first Library: line of the output, so you can see the exact docs version the agent used:
As per Next.js requirements, we also need to add a root layout in app/layout.tsx. Our app is complete, and next build will succeed with the page and /api/chat route.
Same prompt, with and without the docs tool
We used the exact same prompt with Claude Sonnet 5.5. First we gave Claude Sonnet 5.5 access to zero tools, then we ran it through the agent. The project was using Next.js 16.4.1.
Without the tool, the model wrote middleware.ts:
The model even ends with "On Next.js 16+, name the file proxy.ts and export the function as proxy", showing it was aware of the change. It still ended up writing the old version, since the prompt didn't say which version of the project was being used.
The agent made one search and wrote proxy.ts:
The agent also noted that the proxy file only checks for the existence of the cookie. The session still needs to be validated in the pages or the data layer. In Next.js 16, the middleware file convention is deprecated and renamed to proxy. This run took 2 steps and 3,942 tokens.
There are two differences between the runs. The model now knows that Next.js 16.4.1 is installed. And the search has returned snippets from the v16.2.9 documentation. The benchmark in the next section tests the two apart.
Does a docs tool help an AI SDK agent write current code?
Yes, for almost every model we tried. Across eight current models from Anthropic, OpenAI, DeepSeek, Moonshot AI, Z.ai and Qwen, 44 percent of plain answers compiled and used the current API. Listing the installed versions raised that to 63 percent, and the Context7 docs tool raised it to 92 percent. Claude Sonnet 5.5 was the only model that reached 18 of 18 without the tool.
We wrote six coding tasks that depend on the versions in this project (ai 7.0.141, next 16.4.1, zod 4.6.7):
- Redirect users without a session cookie before any /dashboard page renders (Next.js 16 uses
proxy.ts). - Build a
ToolLoopAgentwith one tool that stops after 3 steps. - Pass an API key to a tool through typed tool context, not the model input.
- Render a typed tool result in a
useChatpage. - Call
generateTextwith the built-in total and per-step timeouts. - Write a zod schema for email and URL fields without the deprecated string methods.
Each task ran three times in three setups: the plain model, the model with the installed versions in its instructions, and the full agent with the versions and the docs tool. We type-checked every answer with tsc against the installed packages. A rule check then failed answers that compiled but skipped what the task asked for, such as middleware.ts instead of proxy.ts, or z.string().email() instead of z.email(). We ran it on eight current models and on the older Claude Haiku 4.5, all through OpenRouter, for 486 answers in total:
Across the eight current models, this is how each task did, out of 24 runs per setup:
No current model used the proxy.ts file without being told the Next.js version. After knowing the version list, 7 of the 8 models started using proxy.ts without searching. DeepSeek V4 Pro was the only exception, using middleware.ts in all three of its runs where it had the version list and proxy.ts in two out of three of its runs with the docs tool.
The version list could not correct the API errors, which were the majority of the failures. GPT-5.6 Terra used total and step to set the timeouts instead of totalMs and stepMs in all six of its answers without the tool, and DeepSeek V4 Pro used them in three of its answers. Haiku 5.5, GPT-5.6 Terra and GPT-5.6 Luna also used experimental_context to pass tool context, which is not present in the installed AI SDK version. DeepSeek V4 Pro imported a CoreTool type, which is also no longer present. Several models still used older useChat options, such as api and the input field. Typed tool context is a new feature in AI SDK 7, and proved to be the hardest task in this test, with 3 of the 24 runs passing without the docs tool, and 15 of 24 passing with the docs tool.
With the docs tool, 12 of the 144 answers still failed, with 9 of those 12 being the tool context task. Most of the misses were able to find the right names for contextSchema and toolsContext, but still ended up wiring them into a place that the agent doesn't accept. There were also two runs that never produced an answer, with GPT-5.6 Luna making 6 searches and GLM-5.3 making 9 searches, and the agent hitting its five-step limit before the model wrote any code. If your model makes many searches in parallel, consider increasing the step limit, or instructing the model to search at most two or three times.
The increase in token cost was also very dependent on how much the model tended to write before being provided the tool. Short-answering models like GPT-5.6 Luna grew 6x, GPT-5.6 Terra grew 9x, current Claude models grew 11-12x, and DeepSeek V4 Pro grew 19x. In contrast, GLM-5.3 and Qwen3.8 27B already spent 8,000 to 11,000 tokens reasoning before being provided the docs tool, and the addition of the docs tool had relatively little effect on their token spend (1.2x for GLM-5.3, about the same for Qwen3.8 27B).
Haiku 4.5 is the model that the docs tool was made for. It didn't benefit from the version list, since it doesn't know what changed in those versions, and made up options like stepTimeout and maxStepDurationMs, imported @anthropic-ai/sdk for an AI SDK agent, and used z.string().email(). With the docs tool, it passed all runs of the step limit, timeout and zod tasks. It still wrote middleware.ts three times, since all three of its searches were about "middleware". It's only possible to search for what the model knows to search for.
Putting it together:
- Always mention the installed version in the prompt, it’s basically free and fixed
proxy.tstask in 7/8 current models - Add the docs tool for APIs the model remembers incorrectly. That boosted the pass rate on top of the version list from 63% to 92% in 8 current models. It also worked for all models except Claude Sonnet 5.5, which already hit 18/18
- Test with the model that you actually use in production. Sonnet 5.5 didn’t need the docs tool while DeepSeek V4 Pro went from 5 to 16/18 with the docs tool added
- Be aware of the token budget. The tool added 6-19x tokens per answer on short answering models, while it was roughly equivalent on long reasoning models
- Give the agent enough steps. 5 steps were too short for two answers that had 6 or more searches
How do I check which docs version the agent used?
Log each tool call in the onToolExecutionEnd callback of your agent and then read the first line of the output. That first line starts either with Library: and the versioned ID when Context7 served that version or with Version note: when it fell back to current docs.
This is the callback we used for the runs above:
When our first version of the tool sent the exact patch version, its output started with the fallback note:
A version note doesn’t stop the run; the model still retrieves the docs, it just didn’t pin them to your release. If you find yourself frequently seeing the version note for a single library, consider shortening the version string you send for that library.
When the tools package is enough
If your agent answers questions about any library, not one project's dependencies, you could use the @upstash/context7-tools-ai-sdk package, which provides pre-built tools such as resolveLibraryId and queryDocs for finding a library and retrieving its documentation, respectively, as well as a Context7Agent with both of these tools and a system prompt. This approach would take two API calls for each lookup, and the model would choose the library and version on its own. See our guide to adding documentation search to a Vercel AI SDK agent to learn more about the package, and how Context7 compares to web search tools like Exa and Tavily.
On the other hand, a custom tool such as the one described in this guide would be better suited for an agent that writes code for a single project, and would search only the libraries you specify, at the versions you've installed, in one call per lookup.