What's New in Vercel AI SDK 7 (October 2026): Harnesses, Tool Search, Retries

TL;DR
Vercel AI SDK is at 7.0.143. What changed since June: 10 harness adapters, tool search, toolCallConcurrency, streamRetries and WebSocket chat.
Last updated: October 17, 2026
The Vercel AI SDK is a TypeScript toolkit for calling models, running tool loops and streaming the results into UIs, and it has not had a minor release since 7.0 shipped on June 25, 2026. Every feature since then arrived as a 7.0.x patch: the ai package is at 7.0.143 as of October 16. The verdict: it is still the default for TypeScript teams who want one API across providers plus first-party React, Vue and Svelte hooks, and the four additions worth adopting now are tool search, toolCallConcurrency, streamRetries and onUIMessageStepEnd. HarnessAgent, batch, code mode and decide are still marked experimental.
This post is the changelog digest from 7.0.1 to 7.0.143 (June 25 to October 16, 2026). It does not repeat the launch features (typed tool context, runtimeContext, selective telemetry, WorkflowAgent basics) - those are in our AI SDK 7 launch recap.
Official Sources#
| Source | What it confirms |
|---|---|
ai CHANGELOG on GitHub | Which patch shipped each feature |
| ai-sdk.dev docs | Harnesses, Tool Search, Tool Calling, Batch, WorkflowAgent, MCP Tools, MCP Events |
| Migration guide: AI SDK 6.x to 7.0 | ESM-only, Node.js 22+, tested on Node.js 22, 24 and 26 |
| Vercel changelog: AI SDK 7 | Launch scope, the five harness adapters that shipped with 7.0 |
| Vercel changelog: Program agent harnesses | The earlier canary announcement and its three adapters |
| Vercel changelog: Cursor harness adapter | @ai-sdk/harness-cursor |
npm registry: ai | Version numbers and publish dates |
Why it is still the default for many TypeScript apps#
The core pitch is one generateText / streamText / ToolLoopAgent surface across Anthropic, OpenAI, Google, xAI and AI Gateway string IDs, and one UIMessage stream protocol that useChat and the other UI hooks all consume. Provider differences get normalized inside the SDK rather than in your code.
The newest example is the reasoning option. It accepts 'provider-default', 'none', 'minimal', 'low', 'medium', 'high', 'xhigh' and, since 7.0.129 (October 6), a portable 'max'. Per the reasoning docs, 'max' maps to the native max tier on supported OpenAI, Anthropic, DeepSeek and Moonshot models, coerces with a warning elsewhere, and maps to 95% of max output tokens on budget-based providers. You write one value and the SDK works out what each provider needs.
That is not the only valid design. LangChain and LangGraph offer graph-first state and Python parity, and Mastra takes the all-in-one framework route. If those matter more than a thin, provider-neutral core, read LangChain vs Vercel AI SDK and AI SDK 6 vs LangGraph for TypeScript agents before you pick.
How releases work now: everything is a 7.0.x patch#
There is no 7.1 or 8.0 on npm. The registry shows a steady patch train instead. Dates in this post are npm publish dates in UTC, so a release published early on a UTC morning may show as the previous evening in US time zones.
| Version | Date (UTC) | Notable |
|---|---|---|
| 7.0.0 | June 25, 2026 | AI SDK 7 launch |
| 7.0.50 | August 3, 2026 | - |
| 7.0.91 | September 2, 2026 | streamRetries |
| 7.0.100 | September 14, 2026 | - |
| 7.0.104 | September 16, 2026 | Native tool search |
| 7.0.132 | October 7, 2026 | onUIMessageStepEnd |
| 7.0.135 | October 8, 2026 | WebSocketChatTransport, default step-limit warning |
| 7.0.140 | October 14, 2026 | toolCallConcurrency |
| 7.0.143 | October 16, 2026 | Current latest |
Patch numbers run up to 7.0.143, but some numbers were never published (7.0.80 and 7.0.81, for example), so the registry holds 134 patch releases after 7.0.0. The older lines are still maintained: the ai-v6 tag is at 6.0.309 (October 16) and ai-v5 at 5.0.277 (October 15).
Two practical consequences. First, "patch" does not mean "nothing changed". Brand-new APIs land in patches, and experimental APIs such as batch and decide are documented as able to change in patch releases. Pin exact versions in production and read the changelog when you bump. Second, the 7.0 baseline still applies. Per the v7 migration guide, all packages are ESM-only (CommonJS support was removed), the minimum runtime is Node.js 22, and the SDK is tested on Node.js 22, 24 and 26. The guide also notes that Node.js 22 reached end-of-maintenance on April 30, 2026, and recommends Node.js 24 (LTS) or 26 for production workloads.
Two abstractions: providers and harnesses#
The biggest conceptual addition in AI SDK 7 is a second abstraction next to providers. A provider wraps one model call. A harness is a complete agent runtime - Claude Code, Codex, Pi - with its own skills, sessions, permissions and compaction. HarnessAgent is an AI SDK Agent backed by a harness adapter, and its generate() returns a GenerateTextResult while stream() returns a StreamTextResult. That is the useful part: useChat and @ai-sdk/tui consume a harness run exactly like a model run.
%% title: Two abstractions in AI SDK 7
flowchart TB
App[Your app code] --> Core[AI SDK Core]
App --> HA[HarnessAgent]
Core --> P[Providers: Anthropic, OpenAI, Google, Gateway]
HA --> AD[10 harness adapters, e.g. Claude Code, Codex, OpenCode]
AD --> SB[Sandbox session]
Core --> S[Stream and result types]
HA --> S
S --> UI[useChat / TUI / your UI]The adapter count grew in three stages. The canary announcement named three adapters: Claude Code, Codex and Pi. The 7.0 release on June 25 shipped five, adding Deep Agents and OpenCode (npm first published @ai-sdk/harness-deepagents and @ai-sdk/harness-opencode on June 24). The harness adapters page now lists 10: Claude Code, Cline, Codex, Cursor, Deep Agents (LangChain), fx, GitHub Copilot, Grok Build, OpenCode and Pi. The five later arrivals, by first-publish date on npm: Grok Build on August 5, Cline on August 14, Cursor and fx on August 24 (Vercel announced the Cursor adapter separately), and GitHub Copilot on September 8. Amp, Goose and Mastra are listed as coming soon and are not on npm yet.
The adapters are not interchangeable, and the docs' capability table says so plainly:
| Capability | Status across adapters |
|---|---|
| Runtime location | Sandbox bridge: Claude Code, Codex, Deep Agents, OpenCode. Host process: Cline, fx, Pi. Sandbox via ACP: Cursor, GitHub Copilot, Grok Build |
| Structured output | Not supported on Cursor, GitHub Copilot, Pi |
| Built-in tool approval | Not supported on Codex, Cursor, GitHub Copilot, Grok Build |
| History access | Not supported on any adapter yet |
If your product depends on structured output or reading back session history, check this table before you promise users "bring your own agent".
What changed in the harness API since launch#
Our Ship 26 recap showed the launch-day shape, where you passed sandbox: createVercelSandbox(...) straight to HarnessAgent. That is now deprecated. The change came in two steps, per the harness CHANGELOG: passing a caller-owned sandboxSession to agent.createSession() arrived in @ai-sdk/harness 1.0.76 (August 19), and the 1.0.126 sandbox API refactor (September 25) led to createVercelSandbox being deprecated. In @ai-sdk/sandbox-vercel@1.0.154, createVercelSandbox carries a @deprecated tag pointing to createVercelNetworkSandboxSession, whose result you pass to agent.createSession({ sandboxSession }).
The split makes the lifecycle explicit: the agent is configuration you can hold at module scope, while the sandbox session and the harness session are live resources you create per run and destroy yourself.
import { HarnessAgent } from '@ai-sdk/harness/agent';
import { claudeCode } from '@ai-sdk/harness-claude-code';
import { createVercelNetworkSandboxSession } from '@ai-sdk/sandbox-vercel';
// Module scope: configuration only, no live session.
const agent = new HarnessAgent({
harness: claudeCode,
model: 'claude-sonnet-4-6',
instructions: 'You are a careful coding assistant. Prefer small changes.',
});
const sandboxSession = await createVercelNetworkSandboxSession({
runtime: 'node24',
ports: [4000],
template: await agent.getSandboxTemplate(),
});
const session = await agent.createSession({ sandboxSession });
try {
const result = await agent.stream({
session,
prompt: 'Run the test suite and summarize any failures.',
});
for await (const part of result.stream) {
if (part.type === 'text-delta') process.stdout.write(part.text);
}
} finally {
await session.destroy();
await sandboxSession.destroy();
}
Two gotchas. Credentials come from environment variables, and the model ID format is harness-specific (here it is the bare Claude Code model name, not a Gateway provider/model string). And per the HarnessAgent docs, bridge-backed harnesses such as Claude Code and Codex need a real network sandbox such as @ai-sdk/sandbox-vercel, while host-runtime harnesses such as Pi can run on @ai-sdk/sandbox-just-bash.
Other harness additions from the same changelog:
askUserQuestionstool normalization across adapters (1.0.101, September 3)- Adapter-native subscriptions, a
headersoption andSystemModelMessageinstructions (1.0.102 to 1.0.108, through September 11) - Parallel and sequential tool approvals plus
toModelOutputsupport (1.0.151, October 14)
Tool search and tool concurrency in the agent loop#
Two changes to the core tool loop are the most broadly useful things in this release window.
Tool search. toolSearch() (native tool search, 7.0.104, September 16) addresses a problem every agent with a large tool catalog hits: dumping 60 tool definitions into every prompt costs tokens and degrades tool selection. Tools marked deferLoading: true stay out of the first prompt. The model sees a search tool, calls it with a query, and the matching tools become callable on the next step. Despite the name, this has nothing to do with the web - it searches your own tool registry.
The defaults: up to 5 matches per search, configurable with maxResults, plus an optional search({ query, tools }) callback if you want your own ranking (both arrived in 7.0.127, October 1). It respects activeTools, and MCP tools work too - add deferLoading to what client.tools() returns.
%% title: Tool search loads tools on the next step
sequenceDiagram
participant App
participant SDK as AI SDK loop
participant Model
App->>SDK: tools = search + deferred tools
SDK->>Model: step 1 sees only search
Model->>SDK: call search("refund invoice")
SDK->>SDK: rank deferred tools, keep top maxResults
SDK->>Model: step 2 sees search + matches
Model->>SDK: call getInvoice, refundInvoice
SDK->>SDK: run calls, toolCallConcurrency limit
SDK->>Model: step 3 with tool results
Model->>App: final answerThe tradeoff, from the docs: in direct mode the tool list changes between steps, which can invalidate the cached prompt prefix. If prompt caching is a big part of your cost model, code mode with toolDiscovery: 'conversation' keeps the tool definitions stable.
Tool call concurrency. By default, generateText, streamText and ToolLoopAgent run all SDK-executed tool calls in a step concurrently. That is fast, and it is wrong for tools with ordering side effects, like "check invoice, then refund". toolCallConcurrency (7.0.140, October 14) takes a positive integer; 1 runs calls sequentially in the order the model emitted them. It does not touch provider-executed or client-side tools (for whether the model generates parallel calls at all, use the provider's parallelToolCalls option). On abort, queued calls never start.
import { generateText, isStepCount, tool, toolSearch } from 'ai';
import { z } from 'zod';
// Deferred tools stay out of the first prompt until search loads them.
const getInvoice = tool({
deferLoading: true,
description: 'Fetch an invoice by ID from the billing system.',
inputSchema: z.object({ invoiceId: z.string() }),
execute: async ({ invoiceId }) => ({ invoiceId, status: 'paid' as const }),
});
const refundInvoice = tool({
deferLoading: true,
description: 'Issue a refund for a paid invoice.',
inputSchema: z.object({ invoiceId: z.string(), reason: z.string() }),
execute: async ({ invoiceId }) => ({ invoiceId, refunded: true }),
});
const result = await generateText({
model: 'anthropic/claude-sonnet-5',
tools: {
search: toolSearch({ maxResults: 3 }),
getInvoice,
refundInvoice,
},
toolCallConcurrency: 1, // run tool calls one at a time, in model order
stopWhen: isStepCount(6), // required: the generateText default is a single step
reasoning: 'max',
prompt: 'Customer says invoice inv_123 was charged twice. Check and refund if paid.',
});
console.log(result.text);
Note the stopWhen, and note that the default depends on which API you call (loop control docs):
generateTextandstreamTextdefault to a single step (isStepCount(1)). WithoutstopWhen, the model can callsearch, but the run ends before step 2, so the matched tools never become callable. With tool search,stopWhenis not optional on these two functions, and no warning will tell you it is missing.ToolLoopAgentdefaults toisStepCount(20). Since 7.0.135 (October 8) the SDK logs a warning when that default is what ended a loop. SettingstopWhenexplicitly silences it, andisLoopFinished()removes the cap entirely. If the warning starts appearing in your logs after an upgrade, the loop was already being cut off before - you just could not see it.
Mid-stream failures: streamRetries#
Ordinary maxRetries covers requests that fail before any tokens arrive. The harder case is a provider dropping the stream halfway through step 3 of a tool loop. streamRetries (7.0.91, September 2) handles that case, and it is scoped carefully: it reruns only the current model step. Earlier steps and their tool results are kept, so you do not pay for (or re-execute) the work that already succeeded.
%% title: streamRetries reruns only the failed step
flowchart LR
S1[Step 1 done: tool results kept] --> S2[Step 2 streaming]
S2 -->|provider error mid-stream| R{Retries left?}
R -->|yes| S2b[Rerun step 2 only]
R -->|no| CB{onError returns retry: true?}
CB -->|yes, once| S2b
CB -->|no| E[Error surfaces]
S2b --> S3[Step 3]The semantics worth memorizing, from the reference docs:
- Omitting the option disables retry behavior entirely.
streamRetries: 0disables automatic retries but still letsonErrorreturn{ retry: true }for one callback-directed retry. Total recovery attempts are bounded atstreamRetries + 1.- Tool output from the failed attempt is discarded, but text already sent to the client cannot be retracted. Your UI may show a partial sentence followed by a fresh one.
- Provider-executed tool work may repeat on the retry. If a provider-side tool is not idempotent, think twice.
Since 7.0.82 (August 26; the changelog entry sits under 7.0.80, which was never published to npm), mid-stream provider errors are normalized into a public StreamProviderError across supported providers, so one isInstance check works everywhere:
import { streamText, StreamProviderError } from 'ai';
const result = streamText({
model: 'openai/gpt-6-luna',
prompt: 'Draft release notes for v2.3 from these commits: ...',
streamRetries: 2, // rerun only the current step if the provider errors mid-stream
onError: ({ error }) => {
if (StreamProviderError.isInstance(error)) {
console.warn('provider stream error', error.message);
}
},
});
for await (const text of result.textStream) {
process.stdout.write(text);
}
Chat UI: per-step persistence and a WebSocket transport#
Per-step persistence. Most chat apps save the conversation in onFinish, which means a crash or a closed tab in the middle of a 10-step agent run loses everything. onUIMessageStepEnd (7.0.132, October 7) on createAgentUIStreamResponse, pipeAgentUIStreamToResponse and createAgentUIStream receives messages, isContinuation and the accumulated responseMessage, and it is awaited before the matching finish-step chunk goes out. When the client sees a step finish, the step is already saved.
%% title: Persisting a chat after every agent step
sequenceDiagram
participant Client as useChat
participant Route as POST /api/chat
participant Agent as ToolLoopAgent
participant DB
Client->>Route: messages
Route->>Agent: createAgentUIStreamResponse
loop each step
Agent-->>Route: UI message chunks
Route-->>Client: streamed parts
Route->>DB: onUIMessageStepEnd(responseMessage)
DB-->>Route: saved
Route-->>Client: finish-step
endThe docs recommend idempotent writes (the same message ID gets saved repeatedly as it grows) and treating tool outputs in the message as sensitive data. An upsert keyed on chat ID and message ID is the natural fit.
import { ToolLoopAgent, createAgentUIStreamResponse, isStepCount, tool, type UIMessage } from 'ai';
import { z } from 'zod';
declare function saveChat(chatId: string, message: UIMessage): Promise<void>;
const agent = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-5',
instructions: 'You are a support agent. Look up orders before answering.',
tools: {
lookupOrder: tool({
description: 'Look up an order by ID.',
inputSchema: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => ({ orderId, status: 'shipped' }),
}),
},
stopWhen: isStepCount(10), // explicit limit, so no default-limit warning
});
export async function POST(request: Request) {
const { id, messages } = (await request.json()) as { id: string; messages: UIMessage[] };
return createAgentUIStreamResponse({
agent,
uiMessages: messages,
abortSignal: request.signal,
// Persist after every step, not just at the end of the run.
onUIMessageStepEnd: async ({ responseMessage }) => {
await saveChat(id, responseMessage);
},
});
}
WebSocket transport. WebSocketChatTransport (7.0.135, October 8) is a ChatTransport that sends chat requests and receives UIMessageChunk streams over one persistent connection, with correlated streams, backpressure, cancellation and sequence-based resume. On the client it slots into useChat without other changes. The endpoint is a separate WebSocket server, not the HTTP route handler above:
'use client';
import { useChat } from '@ai-sdk/react';
import { WebSocketChatTransport } from 'ai';
import { useMemo } from 'react';
export default function Chat() {
const transport = useMemo(
// A separate WebSocket server, not the HTTP /api/chat route handler.
() => new WebSocketChatTransport({ url: 'wss://chat.example.com/ws' }),
[],
);
const { messages, sendMessage, stop, status } = useChat({ transport });
return (
<div>
{messages.map(m => (
<p key={m.id}>
{m.role}: {m.parts.map(p => (p.type === 'text' ? p.text : '')).join('')}
</p>
))}
<button onClick={() => sendMessage({ text: 'Hello' })}>Send</button>
{status === 'streaming' && <button onClick={() => stop()}>Stop</button>}
</div>
);
}
The server side is your job: it must hold WebSocket connections open as a long-lived process and implement the transport's frame protocol described in the reference docs, so a Next.js route handler cannot serve it. One more gotcha: the transport's headers option is sent inside application frames, not as WebSocket handshake headers. If your auth layer expects an Authorization header on the upgrade request, it will not see one. If plain HTTP streaming works for you today, there is no reason to switch.
Two smaller useChat fixes are worth knowing: with resume: true, it now resumes interrupted streams when the page becomes visible again (@ai-sdk/react 4.0.141), and default chat IDs are generated on first access so useChat can prerender (7.0.143 / react 4.0.147).
Durable agents: WorkflowAgent 2.0 on Workflow 5#
@ai-sdk/workflow 2.0.0 (August 19) moved to Workflow 5 and dropped Workflow 4 support. Version 2.0.66 (October 8) supports the stable Workflow 5.1.0 release. Per the WorkflowAgent docs, install both together:
npm install @ai-sdk/workflow workflow@5What is new on top of the version covered in our launch recap:
- A durable, non-streaming
WorkflowAgent.generate()(workflow 2.0.59 / ai 7.0.128, October 5). It defaults to a maximum of 20 steps, whilestream()stays unbounded unless you setstopWhen. That asymmetry is easy to miss when you switch between the two. - Approval requests are now created even when there is no writable stream, and signed tool approvals arrived in 7.0.86 (August 31).
toolCallConcurrencyapplies to WorkflowAgent too.
For how this compares with other durable runtimes, see Durable AI agent frameworks compared.
MCP client changes (@ai-sdk/mcp 2.x)#
The MCP client got steady hardening, per the @ai-sdk/mcp CHANGELOG:
- 2026 protocol support. 2.0.33 (August 18) added MCP 2026 streamable HTTP support, the 2026 protocol discovery foundation and hardened OAuth client registration.
- Complete tool lists. 2.0.37 fetches every page of a paginated tool list instead of stopping at the first.
- Tool annotations. 2.0.45 (September 4) surfaces server-provided tool annotations.
- Retries.
maxRetriesfor failed MCP tool calls (ai 7.0.10). - Drift detection.
fingerprintToolsanddetectToolDrift(ai 7.0.19, July 9) pin a tool set's server-controlled fields - description, input schema and title - at the moment you decide to trust a server, then diff later fetches. That catches a server that quietly injects instructions into a description or widens a schema after you approved it. Storing the baseline is your app's job. - MCP Events (experimental). The MCP Events APIs implement the webhook portion of the MCP Events design draft; polling and push-stream delivery are not supported. Managed adapters arrived in 2.0.70 (October 7), and 2.0.76 already made a breaking change: subscriptions now require
ttlMsinstead ofexpiresAt. That is the experimental label working as advertised.
Also shipped, briefly#
- Batch (experimental).
experimental_startBatch,experimental_getBatchStatus,experimental_getBatchResults,experimental_cancelBatchandexperimental_listBatches, with first-party support for Anthropic, Google, OpenAI, xAI and AI Gateway. Batch first landed in 7.0.55 (August 6) and later gained tool calling, per-request models, cancel/list and completion webhooks via AI Gateway. The docs say the API may change in patch releases. - Code mode (experimental).
@ai-sdk/code-mode(first published July 29) runs model-written JS/TS that calls your AI SDK tools inside an isolated QuickJS sandbox. It needs Node.js 22+ and does not run in browser or edge runtimes. - Decide (experimental).
experimental_evaluatewas renamed toexperimental_decidein 7.0.128; per the Decisions docs, it answers Choice, Score and Boolean questions against shared state. - Policy-based approvals.
@ai-sdk/policy-opamoves tool approval rules into Open Policy Agent.regopolicies, layered on the publictoolApprovalcallback. Useful when security, not the app team, owns the approval rules. - Realtime. Experimental OpenAI Live support via
openai.experimental_realtime, with optional browser-direct WebRTC (7.0.102, September 15). - Streaming transcription (7.0.14) and a shared citation representation separate from sources (7.0.138).
Honest tradeoffs#
None of this is free, and the documentation is candid about most of it:
- A lot of the new surface is experimental. HarnessAgent, batch, decide, code mode, realtime and MCP Events all carry experimental labels, and the docs warn of breaking changes, some in patch releases. The MCP Events
ttlMschange shows that is not theoretical. - The cadence is high. More than 130 patch releases in under four months is great for getting fixes and hard on anyone using caret ranges. Pin exact versions and bump deliberately.
- ESM-only and Node 22+ can block older stacks, especially CommonJS monorepos or platforms still on Node 20.
- WorkflowAgent requires Workflow 5. If you adopted durable agents on Workflow 4, the upgrade is mandatory for
@ai-sdk/workflow2.x. - Harness adapters vary widely. No adapter exposes history access yet, and Codex, Cursor, GitHub Copilot and Grok Build lack built-in tool approval in the capability table. "Swap the harness like you swap a model" is the goal, not yet the reality.
- Single-step defaults on the core functions.
generateTextandstreamTextstop after one step unless you setstopWhen, which is easy to forget when you move code from aToolLoopAgent. - Examples lean on AI Gateway. Many docs examples use Gateway string model IDs. Direct provider packages such as
@ai-sdk/anthropicand@ai-sdk/openaistill work if you do not want the Gateway in your path.
Where something else may fit better: if your agent is naturally a graph with explicit state transitions and checkpoints, if you need Python and TypeScript parity, or if you want an all-in-one framework, LangGraph or Mastra are reasonable choices. The AI SDK 6 vs LangGraph comparison linked above walks through that decision, and most of it still holds for 7.
Upgrade checklist#
If you are on an earlier 7.0.x, this is the order we would go in:
- Pin exact versions.
npm i ai@7.0.143 @ai-sdk/react@4.0.147(use--save-exactor remove the caret afterwards). - Check runtime and module format. Node.js 22 or later (the migration guide recommends 24 or 26 in production) and ESM imports.
- Set an explicit
stopWhenon everyToolLoopAgent, and on everygenerateText/streamTextcall that uses tools across steps (tool search included). It clears the default-limit warning and makes the step budget a deliberate choice. - Add
toolCallConcurrency: 1anywhere tool calls have ordering side effects (payments, writes, deploys). - Add
streamRetriesonstreamTextroutes where you have seen providers drop streams, and handleStreamProviderErrorinonError. - Move persistence to
onUIMessageStepEndwith idempotent upserts. - On harness code, replace
createVercelSandboxwithcreateVercelNetworkSandboxSessionplusagent.createSession({ sandboxSession }), and destroy both sessions in afinally. - On WorkflowAgent, install
workflow@5alongside@ai-sdk/workflow2.x.
How the examples were checked: every TypeScript snippet above was type-checked with tsc --noEmit (strict, moduleResolution: bundler, TypeScript 7.0.2) against ai@7.0.143, @ai-sdk/react@4.0.147, @ai-sdk/harness@1.0.154, @ai-sdk/harness-claude-code@1.0.158, @ai-sdk/sandbox-vercel@1.0.154 and zod@4.6.7. The step defaults (isStepCount(1) for generateText and streamText, isStepCount(20) for ToolLoopAgent) were read from the @default tags in ai@7.0.143's type declarations. No API calls were made, so model IDs and runtime behavior come from the docs, not from a live run.
FAQ#
What is the latest version of the Vercel AI SDK?#
The ai package is at 7.0.143, published October 16, 2026. There is no 7.1 or 8.0: every feature since the June 25 launch shipped as a 7.0.x patch, more than 130 of them. The 6.x and 5.x lines still receive patches under the ai-v6 and ai-v5 tags.
What is HarnessAgent in the AI SDK?#
HarnessAgent is an experimental Agent implementation that runs a complete agent runtime, such as Claude Code, Codex, Cursor or Pi, behind the same generate() and stream() methods as a model call. The canary announcement named three adapters, the 7.0 release on June 25 shipped five (Claude Code, Codex, Deep Agents, OpenCode and Pi), and the docs list 10 today. Capabilities differ per adapter, so check the capability table for structured output and tool approval support.
How does AI SDK tool search work?#
You mark tools with deferLoading: true and add toolSearch() to your tool set. The model first sees only the search tool; when it calls it, the top matches (5 by default, set with maxResults) become callable on the next step. That means the run needs more than one step: set stopWhen on generateText and streamText, which default to a single step. It searches your own tool registry, not the internet.
Does streamRetries replay the whole conversation?#
No. It reruns only the model step that failed mid-stream. Earlier steps and their tool results are kept, tool output from the failed attempt is discarded, and text already streamed to the client is not retracted.
Do I need to migrate WorkflowAgent for Workflow 5?#
Yes, if you use @ai-sdk/workflow 2.x. Version 2.0.0 dropped Workflow 4 support, so install workflow@5 alongside it. Version 2.0.66 supports the stable Workflow 5.1.0 release.
Sources#
- AI SDK
aipackage CHANGELOG @ai-sdk/harnessCHANGELOG@ai-sdk/mcpCHANGELOG@ai-sdk/workflowCHANGELOG@ai-sdk/reactCHANGELOG- Migration guide: AI SDK 6.x to 7.0
- AI SDK Harnesses overview
- Harness adapters
- HarnessAgent
- Tool Search
- Tools and Tool Calling: execution concurrency
- Loop control
- streamText reference
- createAgentUIStreamResponse reference
- WebSocketChatTransport reference
- Reasoning
- WorkflowAgent
- MCP Tools
- MCP Events
- Batch
- Code mode
- Decisions
- Policy-based tool approvals
- Vercel changelog: AI SDK 7
- Vercel changelog: Program agent harnesses with AI SDK
- Vercel changelog: Cursor AI SDK harness adapter
- npm registry: ai
- npm registry: @ai-sdk/harness
- npm registry: @ai-sdk/harness-deepagents
- npm registry: @ai-sdk/harness-opencode
- npm registry: @ai-sdk/harness-cursor
- npm registry: @ai-sdk/mcp
- npm registry: @ai-sdk/code-mode
- npm registry: @ai-sdk/policy-opa
Continue Reading#
- fx Deep Dive: Inside Vercel's Tiny Native Coding Agent - what fx is, now that it is one of the 10 harness adapters.
- The MCP 2026-07-28 Rewrite: What Breaks and How to Migrate - what changed in the spec that
@ai-sdk/mcp2.x now speaks. - Prompt Injection in Agent Apps: The Practical Version - why MCP tool drift detection matters.
- The Agent Loop Explained: How 5 SDKs Run Tools Until Done -
stopWhen, step defaults and stop rules compared with four other SDKs.
Get the next deep dive like this in your inbox
One email a week on Vercel AI SDK and the rest of the AI dev stack. Free.
Read next on AI coding tools
Vercel AI SDK 7: The Production Agent Upgrade
Vercel AI SDK 7 for production agents: typed tool context, WorkflowAgent durability, approvals, telemetry, realtime and the AI SDK 6 migration path.
9 min readEverything Vercel Shipped at Ship 26 (June 2026)
Everything Vercel shipped at Ship 26: the open-source eve agent framework, Vercel Drop, AI Gateway spend caps per API key and the AI SDK 7 HarnessAgent API.
8 min readVercel AI SDK 6 vs LangGraph 1.0: Which Agent Framework Should TypeScript Teams Use?
Vercel AI SDK 6 vs LangGraph 1.0 for TypeScript agents - ToolLoopAgent versus durable state graphs, and how to choose the right framework for your team.
8 min readNew here? Start with
Technical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.








