1.11 Terminal UI --- @ai-sdk/tui
定位 :在终端里交互式跑 agent,用于本地开发、demo 与内部工具 ------ 提供 prompt 输入、流式响应、tool cards、reasoning 区块、滚动、工具审批提示,而不需要自己写界面。
入口 :runAgentTUI({ title, agent, transport, sandbox, tools, reasoning, responseStatistics, contextSize });安装 pnpm add @ai-sdk/tui ai @ai-sdk/openai。
本地 vs 远程 :传 agent 直接本地跑 ToolLoopAgent;传 transport(new DefaultChatTransport({ api: 'https://example.com/api/chat' }))即走远程 AI SDK UI-message endpoint,endpoint、鉴权、请求体行为由 transport 控制,TUI 的内部 chat id 与消息历史对 transport 契约保持私有。
沙箱 :来自 @ai-sdk/sandbox-just-bash 的 createJustBashNetworkSandboxSession({ cwd: '/home/user' }) → sandboxSession.restricted() 传给 TUI、sandboxSession.destroy() 放在 finally 释放。传 sandbox 时,TUI 把该 sandbox 以 experimental_sandbox 转发到每一次 agent 调用 ,工具的 description 函数与 execute 可从 options 读取并委派命令/文件操作。
审批交互 :toolApproval 支持策略函数,例如 weather: ({ location }) => cond ? 'approved' : 'user-approval';命中 user-approval 时暂停并等待用户按键。
选项取值:
| 选项 | 取值 | 默认 |
|---|---|---|
tools |
'full'(显示输入+输出)/ 'collapsed'(只显示卡片)/ 'auto-collapsed'(最新一条展开,直到出现其他可见区块)/ 'hidden' |
'auto-collapsed' |
reasoning |
同上四值 | 'auto-collapsed' |
responseStatistics |
'outputTokensPerSecond'(吞吐)/ 'outputTokenCount'(输出 token 数) |
'outputTokensPerSecond' |
contextSize |
数值(如 200_000),提供后按模型上下文窗口百分比显示总 token 占用 |
无 |
快捷键 :Enter 提交、y/n 批准或拒绝工具调用、Up/Down 滚动、PageUp/PageDown 整页滚动、Ctrl+L 重绘、Esc / Ctrl+C 退出。
注意事项 :用 agent 选项时,agent 必须能被终端自由文本直接驱动 ------ 不得依赖 per-call options(即不能用 callOptionsSchema) ,不得使用 structured output ,因为 TUI 无法从自由 prompt 推断这些值;需要它们请改走 transport,或本地直接调 agent.generate() / agent.stream()。sandbox 的 description(工作目录、公网 hostname、暴露端口)不会自动进入 prompt ,需手动写进 agent instructions。restricted() 与 destroy() 必须成对使用,否则沙箱泄漏。
2. AI SDK Core 板块
定位 :Core 是对 LLM 的标准化集成层 ------ 统一的 prompt 结构、settings、结果形状,让上层(Agents/UI/RSC)不依赖具体厂商 API。
Core 函数清单(Overview 明确列出):
generateText--- 生成文本与工具调用,适合非交互自动化(起草邮件、网页摘要)以及使用工具的 agent。streamText--- 流式生成文本与工具调用,适合聊天机器人、内容流式输出等交互场景。- 两者都通过
output属性支持结构化输出(Output.object()、Output.array()),用于信息抽取、合成数据生成、分类任务与流式生成 UI。
其余 Core 能力按工具(Tool Calling、MCP、Code Mode、Tool Search)、上下文(runtime/tool context)、设置(Settings、Prompt Engineering)、推理(Reasoning、Decisions)、模态(Embeddings、Reranking、图像/视频/语音/转写/翻译、File/Skill Uploads、Realtime)、工程化(Middleware、Batch、Provider & Model Management、Error Handling、Testing、Telemetry、DevTools、Lifecycle Callbacks)分组展开。
2.1 Generating Text --- generateText 与 streamText
generateText 结果字段 (result.*):content(所有步骤生成的内容)、text(最终一步 的文本)、files(所有步骤生成的文件)、sources(所有步骤引用的来源,仅部分模型可用)、toolCalls、toolResults、finishReason、rawFinishReason(来自 provider 的原始原因)、usage(多步骤总量)、warnings(provider 警告,如不支持的设置)、steps(各步详情)、finalStep、output(按 output 规格产出的结构化结果)。原始响应头/ body 通过 finalStep.response 访问。
每步 performance 指标 :effectiveOutputTokensPerSecond(outputTokens / requestSeconds)、outputTokensPerSecond(流式专用,首个输出 chunk 之后 outputTokens / outputStreamSeconds;generateText 中为 undefined)、inputTokensPerSecond(流式专用,首 chunk 之前 inputTokens / ttftSeconds;generateText 为 undefined)、effectiveTotalTokensPerSecond、stepTimeMs(含模型响应与工具执行总耗时)、responseTimeMs、toolExecutionMs(按 tool call ID 为键 )、timeToFirstOutputMs(流式专用)、timeBetweenOutputChunksMs(≥2 个 chunk 时的间隔统计,含 min/p10/median/avg/p90/max)。
streamText 要点 :result.textStream 同时是 ReadableStream 与 AsyncIterable 。streamText 立即开始流式并抑制错误 (避免服务端崩溃),错误日志用 onError。它使用背压(backpressure),只在被请求时生成 token ------ 必须消费流才能结束 。与 UI/RSC 集成的 helper:createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }) })、pipeUIMessageStreamToResponse({...})、createTextStreamResponse({ stream: toTextStream({ stream: result.stream }) })、pipeTextStreamToResponse({...})。流结束时才 resolve 的一组 promise 与 generateText 字段同构(content/text/finalStep/files/sources/toolCalls/toolResults/finishReason/rawFinishReason/usage/warnings/steps);result.totalUsage 已废弃,改用 result.usage。
onChunk 收到的全部 stream part 类型 (26 种,构成 AI SDK 流协议词汇表):start、start-step、text-start、text-delta、text-end、reasoning-start、reasoning-delta、reasoning-end、custom、source、file、reasoning-file、tool-call、tool-input-start、tool-input-delta、tool-input-end、tool-result、tool-error、tool-output-denied、tool-approval-request、tool-approval-response、finish-step、finish、abort、error、raw。
生命周期回调 :onEnd(稳定,最后一步结束后触发,含 text、usage、finishReason、messages、steps 等);另有标注 experimental 的一组(会随小版本破坏性变更):onStart、onStepStart、onLanguageModelCallStart、onLanguageModelCallEnd、onToolExecutionStart、onToolExecutionEnd、onStepEnd。其中 onLanguageModelCallEnd 在模型响应已归一化解析之后、任何客户端工具执行之前触发,收到模型调用的 content parts、usage、finishReason、provider metadata。
关键差异:core 的 lifecycle 回调比 ToolLoopAgent 多出 onLanguageModelCallStart / onLanguageModelCallEnd (agent 侧只有 6 个)。core 生命周期回调内抛出的错误会被静默捕获,不会打断生成/流式。
流转换 :experimental_transform 选项;转换在回调被调用、promise 被 resolve 之前应用 (例如把文本全转大写的转换,onEnd 收到的就是转换后文本)。内置 smoothStream 平滑 text 与 reasoning 流。自定义转换函数接收模型可用 tools 并返回转换函数。可用 stopStream 提前停止流(如模型护栏被违反);调用 stopStream 时必须手动模拟 finish-step 与 finish 事件 ,否则流不成形、回调不被调用。可提供多个转换,按提供顺序应用。
Sources 与 Citations :Perplexity、Google 等 provider 会返回来源;url 类型 source 含 id、url、title(可选)、providerMetadata。OpenAI Responses 与 Anthropic web search 的 sources 是检索到的引用全集 (可能多于模型实际引用的条数);OpenAI file-search 结果也作为 document sources 暴露;检索数据不可用时,退化为 citation 派生的引用以保持兼容。Citations 是挂在每个 text content part 上的可选数组(Citation 类型从 ai 导出):source(URL 或 document,含可用时的 title,其 ID 标识被引用资源,不一定 与 result.sources 的 ID 对应)、startIndex/endIndex(provider 提供的可选偏移,end 不含 ,各 provider 字符索引惯例不同且 SDK 原样保留 )、citedText(来自 source 的支撑段落,是 source 文本而非生成答案里的偏移)。
用 citations 渲染内联引用,用
result.sources列检索全集。JS 的slice()按 UTF-16 code unit 计数,文本含 emoji 等非 BMP 字符时 provider offset 可能需要换算;offset 缺失或不可靠时把引用与整个文本块一起渲染,不要猜范围。Anthropic 给的是支撑段落与 document 位置而非输出文本偏移 ,细节留在 provider metadata;OpenAI file-search 的 citationindex保留在 provider metadata,不作为输出文本范围解释 。源 URL 的 query 与 fragment 要保留(可能标识特定版本/页/段落);同一 source 可在不同位置被多次引用。streamText下 citations 出现在text-end事件(关联该文本块id)与完成的result.content文本 parts 上,并能在toUIMessageStream后作为TextUIPart.citations存活(即使禁用 source 事件);citation fallback source 事件可能在 provider 流末尾到达。原始 OpenAI annotations 与 Anthropic citations 仍保留在 text 的 provider metadata;其他 provider 可能省略citations,省略不代表其 sources 是完整检索集。
2.2 Generating Structured Data --- Output 家族
定位 :文本生成之外,实际业务更需要结构化数据 (信息抽取、分类、合成数据)。许多模型支持 "JSON modes" / "tools",但你要手工提供 schema 并校验结果,因为 LLM 会产生不正确或不完整 的结构化数据。AI SDK 通过 generateText / streamText 的 output 属性跨 provider 标准化了结构化输出;schema 可用 Zod (zod-schema)、Valibot (valibot-schema)或 JSON Schema (json-schema)。
与工具同请求可组合 :结构化输出属于 generateText/streamText 流程的一部分,可与 tool calling 同时使用。关键规则:生成结构化输出本身算作一步 (多轮执行模型中每次模型调用或工具执行是一步),因此与工具组合时要在 stopWhen 里为工具执行和输出生成都留够步数。
五种 Output 类型:
| 类型 | 用法 | 校验行为 |
|---|---|---|
Output.text() |
生成纯文本 | 不施加任何 schema ,直接返回字符串;不指定 output 时的默认行为 |
Output.object({ schema }) |
按 schema 生成对象 | 结果做类型校验,确保匹配 schema |
Output.array({ element, minItems, maxItems }) |
生成类型化对象数组 | 每个元素须符合 element;边界限制元素数量 |
Output.choice({ options }) |
从给定字符串选项中选一个(分类、固定枚举答案) | 校验结果必须是选项之一,非法则抛错 |
Output.json() |
生成并解析无 schema 的自由 JSON | 只检查是否为合法 JSON ,不校验结构与类型;需要 schema 校验请用 .object / .array |
Output.array 的边界规则:minItems、maxItems 必须是非负整数 ,且 minItems 不得大于 maxItems;两者取相同值即要求精确长度 。边界在 provider 支持时会作为结构化输出 schema 的一部分发送,同时 AI SDK 独立校验最终输出。
流式结构化输出 :结构化数据复杂度带来不可接受的响应时延,streamText + output 可在生成过程中流式返回;客户端用 useObject hook 消费。
- partial 无法校验 :流式过程中的部分输出不能对照 schema 校验,因为不完整数据未必符合期望结构。
elementStream:流式数组时逐个接收已完成并通过 element schema 校验 的元素。与partialOutputStream不同 ------ 后者流的是含未完成元素的整个部分数组 。若模型生成超过maxItems,elementStream会在发出第一个超额元素前报错 ;这不会自动中断 provider 生成 ,而最终的outputpromise 会 reject。- 流中错误 :
streamText立即开始流式,错误成为流的一部分而非抛出异常(防崩溃),用onError处理。
Property Descriptions :给 schema 单个属性加 .describe("...") 可向模型提示该属性用途,提升结构化数据质量与准确率。特别适合:澄清含糊的属性名、指定期望格式或约定、为复杂嵌套结构提供上下文。
name 与 description :可为输出指定可选的 name 与 description,部分 provider 用它做额外引导(例如作为 tool 名或 schema 名)。支持于 Output.object({ name, description, schema })、Output.array({ name, description, element, minItems, maxItems })、Output.choice({ name, description, options })、Output.json({ name, description })。
Accessing Reasoning :结果的 reasoningText 属性提供模型生成该对象时的思考过程字符串(若可用)。
Error Handling(两种方式):
- 模型响应无法解析或校验失败 →
generateText以AI_NoObjectGeneratedErrorreject。 generateText返回了结果但没有 output → 访问result.output抛AI_NoOutputGeneratedError(例如最终一步不是以stop结束,而是以tool-calls结束)。因为output是 getter ,解构它同样触发该访问。
NoObjectGeneratedError 保留便于排障的信息:text(模型生成的文本,按对象生成模式可能是原始文本或 tool call 文本)、response(语言模型响应元数据:响应 id、时间戳、模型)、usage(本次请求 token 用量)、cause(错误成因,如 JSON 解析错误)。
原始响应访问 :response 属性(generateText 结果)可取 provider 完整响应头与 body。
2.3 Settings --- 模型调用与请求选项
定位 :跨 provider 统一的设置入口,分为语言模型调用选项 与请求选项两组。
Language Model Call Options :maxOutputTokens、temperature、topP、topK、presencePenalty、frequencyPenalty、stopSequences、seed、reasoning。另有 providerOptions 用于传递 provider 专属参数(配合其类型,如 OpenAILanguageModelResponsesOptions)。
Request Options :maxRetries(失败重试次数)、abortSignal(AbortSignal,可用 AbortSignal.timeout() 构造)、timeout、headers(附加到请求的 HTTP 头)。
不支持的设置通过 warnings 上报 :provider 返回的警告(如不支持某设置)在 result.warnings 中,跨步骤汇总(见 2.1、2.4)。
这些设置同时是
ToolLoopAgent的顶层设置,并可被prepareStep逐步覆盖(覆盖只作用于当前步,显式假值如temperature: 0会被保留,见 1.4)。
2.4 Prompt Engineering --- 提示词开发与调试
定位 :Core 对提示词工程提供的不是 DSL 而是约定与可观测性 :prompt/messages 结构、工具描述、以及调试时查看真实请求内容的手段。
- Tips 与 Prompts for Tools :为工具写清
description(模型据此决定是否调用),并用 schema 的字段描述约束输入(与 2.2 的.describe()呼应)。 - Tool & Structured Data Schemas:把期望形状放进 schema,而不是塞进自然语言指令。
- Debugging 三条路径:
- Inspecting Warnings --- 检查
result.warnings,发现 provider 忽略了哪些设置。 - Request Messages --- 通过
request.messages(结果中携带的实际发给模型的消息 )核对拼装结果;可在生成函数上启用include: { requestMessages: true }之类选项让 SDK 保留请求消息。 - HTTP Request Bodies --- 通过
finalStep.request.body查看发给 provider 的原始 HTTP 请求体。
- Inspecting Warnings --- 检查
这三层(模型输入消息 → 原始 HTTP body → provider warnings)正好覆盖「我的提示词到底以什么形式进了模型」的排障链路;
ToolLoopAgent的steps也暴露同样的每步信息。
2.5 Reasoning --- 顶层 reasoning 参数
定位 :用一个 provider 无关的顶层 reasoning 参数 统一控制推理模型的思考行为,取代散落在各家 providerOptions 里的写法。
- Basic Usage / Streaming :
generateText与streamText都接受reasoning;流式下推理内容以reasoning-start/reasoning-delta/reasoning-endpart 出现(见 2.1 的 part 列表),并可用reasoningText(见 2.2)取文本。 - Precedence Rules :顶层
reasoning与各 provider 的providerOptions之间存在优先级规则,迁移时需注意覆盖关系。 - Provider Support :并非所有 provider 都支持;文档为不支持 的情况定义了行为(对应
warnings)。 - Migrating from
providerOptions:文档给出三组 before/after 对照 ------ Anthropic 、Google(includeThoughts) 、OpenAI(reasoningSummary) :把原先写在providerOptions.anthropic/providerOptions.google.includeThoughts/providerOptions.openai.reasoningSummary的开关,改为使用统一的顶层reasoning;对较老的 Anthropic 模型另有专门的迁移示例。
2.6 Runtime and Tool Context --- 两种上下文与遥测过滤
定位 :把服务端状态传出给 Agent/工具,同时不把它写进 prompt,并控制它在遥测中的可见性。
Context Types:
- Runtime Context(
runtimeContext) :整个调用的共享运行时状态 (示例中的requestId、region等)。贯穿 loop,可在prepareCall、prepareStep、生命周期回调与最终结果中读取。 - Tool Context(
toolsContext) :按工具名为键 的映射;每个工具用contextSchema声明自己需要的形状,execute只拿到自己那一份已校验的context(示例:customerLookup工具拿自己的凭据/区域配置)。
Telemetry Context Filtering :context 可能含敏感值,因此遥测默认受控;文档提供 telemetry.includeToolsContext 开关来决定工具上下文是否进入遥测数据。
Where Context Is Available :runtimeContext / toolsContext 在 ToolLoopAgent、generateText、streamText 以及 callOptionsSchema + prepareCall(每次调用注入)、prepareStep(逐步更新)、needsApproval(审批判断时也可读取)中可用 ------ 与 1.1/1.2/1.5 的描述一致。
Choosing the Right Context :跨工具共享、描述"这次运行" → runtimeContext;只属于某个工具的凭据/作用域 → toolsContext + contextSchema(最小可见面 + 独立校验)。
2.7 Tool Calling --- 工具调用与多步执行
定位 :工具是可被模型调用以执行特定任务的对象。Function tools 与 dynamic tools 共享四个核心要素:
description--- 可选的工具描述,会影响工具被选中的时机。可以是字符串,也可以是从工具 context 与 experimental sandbox 派生描述的函数。inputSchema--- 定义输入参数的 Zod schema 或 JSON schema ;它既被 LLM 消费,也用于校验 LLM 产生的工具调用。execute--- 可选的 async 函数,以工具调用的输入为参调用,产出泛型RESULT类型。之所以可选,是因为你可能想把工具调用转发给客户端或队列,而不在本进程执行。strict--- 可选布尔,provider 支持时启用严格工具调用。
用 tool() helper 可推断 execute 参数类型。generateText / streamText 的 tools 参数是「工具名为键、工具为值」的对象(ToolSet)。模型使用工具称为 tool call ,工具的输出称为 tool result。工具调用不限于文本生成,也可用于渲染 UI(Generative UI)。
Dynamic Descriptions :描述可以是固定字符串或函数。当发给模型的描述应取决于当前工具 context 或 experimental sandbox(tenant、project、environment、workspace)时用函数。解析时机 :description 函数在每个生成步骤把工具定义发给模型之前 解析;它收到来自 toolsContext 的匹配 context 与当前 experimental_sandbox(若提供)。若 prepareStep 更新了 toolsContext 或 experimental_sandbox,下一步使用更新后的值。
Strict Mode :启用后,支持严格工具调用的 provider 只会产生符合 inputSchema 的工具调用 ,提升可靠性;但并非所有 schema 都被严格模式支持,且支持范围取决于具体 provider。默认关闭 ,可逐工具 设 strict: true。不支持严格模式的 provider/模型会忽略该选项。
Input Examples :为工具提供示例输入以引导模型理解数据结构;当 JSON schema 未能完全表达用法或存在可选值时尤其有用(配合 inputExamples)。只有 Anthropic provider 原生支持工具输入示例,其他 provider 忽略该设置。
Tool Execution Approval :默认带 execute 的工具在模型调用时自动执行;在 generateText、streamText 或 ToolLoopAgent 上用 toolApproval 配置审批。toolApproval 可以是:
- 处理所有工具调用的
GenericToolApprovalFunction; - 逐工具 的状态映射和/或
SingleToolApprovalFunction回调(两者都可返回undefined,效果等同'not-applicable')。
工具定义上较旧的 needsApproval 属性已废弃 ------ 存量代码仍可用,但新代码应把审批逻辑移到 toolApproval(注意:needsApproval 目前仍是 WorkflowAgent 的正式用法 ,见 1.10)。四种状态与 1.7 相同;对象形式可带 reason:自动批准/拒绝的 reason 发在 approval response 上,人工审批的 reason 发在 approval request 上 以便展示给审批人。Generic 函数收到 toolCall、tools、toolsContext、messages、runtimeContext(runtimeContext 的类型是 ToolApprovalConfiguration 的第二个类型参数,默认 Context);逐工具函数收到工具输入 + toolCallId、messages、toolContext(与工具执行的 context 同形,但不含 abortSignal )、runtimeContext。
错误类型 (工具相关):NoSuchToolError(模型调了不存在的工具)、InvalidToolInputError(输入不符合 schema)、ToolChoiceViolationError(违反 toolChoice 约束)、ToolCallRepairError。配合 repairToolCall 可修复不合法的工具调用(如工具名拼错、参数格式偏差)。
Multi-Step Calls(stopWhen) :generateText / streamText 也支持多步执行 ------ 每步是一次模型调用或工具执行;用 stopWhen 决定继续到第几步(与 1.4 同一套停止条件),步详情在 result.steps,含每步 performance,并有 onStepEnd 回调。
Tool call execution concurrency :用 toolCallConcurrency 限制一步内并发执行的工具调用数(1 = 按模型顺序串行),与 1.10 的 workflow 侧同名选项一致。
Response Messages :结果提供 responseMessages (本次生成产生的消息),便于把对话状态推进到下一轮;配合 initialMessages / options.messages 与 pruneMessages 做上下文管理。
Dynamic Tools / dynamicTool :运行时才提供的工具;可做类型安全处理 (Type-Safe Handling),并支持多模态结果(toModelOutput 控制模型看到的输出表示,见 1.9)。
Preliminary Tool Results :execute 可为 async generator,多次 yield 部分结果 ------ 子 agent 流式进度的底层机制(见 1.9)。相关工具输入回调:onInputStart、onInputDelta、onInputAvailable。
Tool Choice :'auto' | 'none' | 'required' | { type: 'tool', toolName },配合 activeTools 收窄工具面。
Experimental Sandbox :experimental_sandbox 提供命令/代码执行环境(类型 Experimental_SandboxSession),暴露 experimental_sandbox.description、run、workingDirectory、env 等;execute 中可通过 options 取用。文档强调传 sandbox 不等于工具被沙箱化 ,工具必须显式委派(见 1.2);telemetry.includeToolsContext 控制工具上下文是否进入遥测(见 2.6)。
与 UI 集成 :toUIMessageStream 把工具 parts 送到前端,客户端用 addToolApprovalResponse 回应审批、addToolOutput 提交客户端工具结果(配合 useChat)。
2.8 MCP 三件套(Tools / Apps / Events)
2.8.1 Model Context Protocol (MCP)
定位:连接 MCP server 并使用其工具/资源/补全/prompt。
- 初始化 :
createMCPClient();transport 四种:HTTP(推荐) 、SSE 、Stdio(本地 server) 、Custom Transport (MCPTransport、StreamableHTTPClientTransport)。初始化细节涉及initialize、initialInitializeResult、initialSessionId、terminateSessionOnClose、onSessionExpired。 - OAuth :
auth/authProvider/authorization凭据流;共享 OAuth 凭据存储 、Authorization Server 校验 (validateAuthorizationServerURL、iss)、Callback Issuer 校验 (callbackIssuer)、动态客户端凭据恢复 (clientMetadata、redirect_uris、application_type)。相关错误类:MCPClientError、MCPClientOAuthError、UnauthorizedError(OAuth 错误码invalid_client、invalid_grant、unauthorized_client、statusCode)。 - 瞬时工具失败重试 :
maxRetries。 - 使用 MCP 工具 :Schema Discovery (发现工具 schema)、
onDiscovery/onDynamicallyRegistered、Tool Annotations 与审批 (metadata.annotations含readOnlyHint、destructiveHint、idempotentHint、openWorldHint,可与toolApproval联动)、Schema Definition 、Typed Tool Outputs (outputSchema、structuredContent、CallToolResult、isError、content)。工具漂移检测:detectToolDrift、fingerprintTools。Provider 侧集成示例:openai.tools.mcp。用户交互请求回调onElicitationRequest(context.arguments、context.tokens)。 - MCP Resources :Listing Resources、Reading Resource Contents、Listing Resource Templates(
uri、title、schemas)。 - MCP Completions :
complete、capabilities.completions。 - MCP Prompts:使用 server 侧 prompt 模板。
2.8.2 MCP Apps --- 交互式工具 UI
定位 :连接 MCP Apps 并渲染可交互的工具 UI。要点:
- Host Flow:宿主(你的应用)承载 App 渲染。
- Connect With MCP Apps Support :用
mcpAppClientCapabilities声明支持(native能力)。 - Expose Only Model-Visible Tools :用
splitMCPAppTools把工具面拆成模型可见 (modelVisible)与仅 App 可见两类,避免把 UI 专用工具暴露给模型。 - Read App Resources :
readMCPAppResource(resourceUri)。 - Proxy App-Visible Tool Calls :App 发起的调用需代理,并用
client.callTool;结果含structuredContent、content。 - Render With React :
experimental_MCPAppRenderer+fallback渲染。 - 另有 Best Practices 与 Reference 小节。
2.8.3 MCP Events --- Webhook 事件契约
定位:理解 MCP webhook 事件契约以及订阅/验签/接收的 AI SDK API。
- Choose who manages subscriptions:由应用或 MCP server 管理订阅。
- 机制 :
client.experimental_events提供事件面;createAdapter适配 webhook;Experimental_MCPEventStore存储事件;接口包含get、getById、set、update、delete、onEvent。 - 可靠性字段 :
cursor、gap.cursor(缺口检测 )、truncated、delivery.secret(验签)、termination.error、ttlMs、refreshBefore、messageId、eventStore。 - 文档提供 Connect the webhook and client 步骤与 Runnable example、API Reference。
2.9 Code Mode --- 用沙箱 JS/TS 编排工具
定位 :让模型以沙箱内的 JavaScript/TypeScript 程序编排 AI SDK 工具 ,而不是逐个发起 tool call ------ 适合需要循环、条件、Promise.all、JSON.parse/JSON.stringify 等组合逻辑的场合。
- 安装 后,在
generateText/streamText/ToolLoopAgent上启用:experimental_runCodeMode(亦见runCodeMode),并配experimental_toolCallers。 - Discovering Tools Through Conversation / Searching Deferred Tools :配合
toolDiscovery与deferLoading(见 2.10),模型可先发现再使用工具;getInventory、getDemand提供工具清单与需求视图。 - Writing Code Mode Programs / Direct Execution :程序以
code_mode方式执行;对无法在代码内完成的调用,可回退为DIRECT_TOOL_CALL。 - Tool Approval :Code Mode 下的工具审批仍走
toolApproval语义。 - Execution Limits (
executionPolicy,全部为可配置上限):timeoutMs、maxBridgeRequests、maxInFlightBridgeRequests、maxResultBytes、maxSourceBytes、maxStackSizeBytes、maxToolInputBytes、maxToolOutputBytes、maxConsoleOutputBytes、memoryLimitBytes,以及experimental_setMaxWorkers(并发 worker 数)。 - Isolation and Tool Access :沙箱内可访问的能力(
fetch、process、module、require、console.log/debug/info/error、Promise.all、eval)与隔离边界由执行策略决定;工具通过execute、inputExamples暴露。
2.10 Tool Search --- 按需发现工具
定位 :toolSearch() 让模型按需找到所需工具,而不必把每个工具定义都塞进初始上下文。
- 用法:把工具注册为
deferLoading: true;搜索匹配工具的 name 与 description ,并让它们在下一个模型步骤可用。 - 适用于
generateText、streamText、ToolLoopAgent、以及@ai-sdk/workflow的WorkflowAgent;模型提供搜索查询,工厂可选接受应用自定义的search回调与maxResults上限。 - 两种模式 :Direct Tool Calling ------ 模型初始只看到
search,搜索后把匹配定义加入 provider 工具列表并由模型直接调用(这会改变工具定义,可能使已缓存的 prompt 前缀失效 );Code Mode ------ 支持保留缓存 的 code mode(见 2.9),WorkflowAgent支持直接工具调用。 - 与
activeTools配合控制每步工具面。
2.11 Language Model Middleware
定位 :在不改变调用方代码 的前提下增强语言模型行为 ------ 包装模型后仍是一个标准 LanguageModelV4。
- 入口 :
wrapLanguageModel({ model, middleware });单个 middleware 可实现transformParams、wrapGenerate、wrapStream(分别拦截参数与doGenerate/doStream调用)。类型名LanguageModelV4Middleware;也可用createToolMiddleware构造工具侧 middleware。 - 多个 middlewares:可组合成链。
- 内置 middleware :
extractReasoningMiddleware({ ... })--- 从文本中抽取推理(选项含startWithReasoning、reasoning)。extractJsonMiddleware()--- 从文本中抽取 JSON。simulateStreamingMiddleware()--- 把非流式模型模拟成流式。defaultSettingsMiddleware({ ... })--- 补默认设置。defaultInstructionsMiddleware({ ... })--- 补默认指令。addToolInputExamplesMiddleware({ ... })--- 为工具补输入示例(与 2.7 的inputExamples呼应)。- Provider 专用工具格式 middleware:
gemmaToolMiddleware、hermesToolMiddleware(把工具调用文本按各家格式解析,配合format、prefix、onVersion)。
- Community Middleware :社区提供的 middleware;文档示例含自定义 tool call parser。
- 实现要点 :
SystemModelMessage的处理与allowSystemInMessages(某些模型不接受 system 消息,需要把 system 折叠进首条消息,配合findSources、getLastUserMessageText之类的辅助逻辑)。 - 典型自建场景 :Logging、Caching、RAG(检索增强)、Guardrails 、以及按请求配置自定义 metadata (
providerOptions)。
2.12 Batch --- 异步批处理
定位 :以 provider 的批量接口异步处理大批请求(成本与时延通常优于逐条调用)。
- Supported providers :OpenAI、Anthropic、Google、xAI 等(不支持时抛
UnsupportedFunctionalityError)。 - 核心 API :
experimental_startBatch(提交批次,含instructions、messages、providerOptions等常规字段,以及requests/requestCounts)、experimental_getBatchStatus/getBatchStatus、experimental_getBatchResults/getBatchResults、experimental_cancelBatch/cancelBatch、experimental_listBatches/listBatches。 - 状态与分页 :状态取值
pending/completed/failed;列表用cursor/nextCursor;每条请求含id、customId、completionWindow、createdAt、expiresAt;provider 原始状态在rawStatus,结果条目含error、response、usage、finishReason/rawFinishReason、providerMetadata;webhook 通知字段webhookUrl。 - Image requests / Batch tools :批量不仅限于文本 ------ 图像请求(
generateImage相关,images、size、aspectRatio)与作为 batch 请求的工具调用 (工具在批处理结果中以execute执行,产出GeneratedFile等)。 - Request controls :单条请求可带
abortSignal、maxRetries、headers、timeout及生成设置(maxOutputTokens、temperature、topP、topK、presencePenalty、frequencyPenalty、stopSequences、seed、reasoning)。 - Retrieving results :结果检索与逐条响应解析(
content、text、files、providerMetadata)。
2.13 Provider & Model Management
定位:多 provider、多模型的统一入口与治理,避免每处调用都手写 provider 实例。
- Custom Providers :
customProvider({ ... })------ 自定义 provider 以适配非标准模型;文档示例四类:custom model settings (按模型名注入设置)、model name alias (别名映射)、limit available models (限制可用模型)、files and skills interfaces(暴露文件/技能能力,见 2.24、2.25)。 - Provider Registry :
createProviderRegistry({ ... }),把多个 provider 注册进一个注册表并用统一字符串选模型 。Setup 支持 Custom Separator (自定义provider/model分隔符)。可按能力取模型:languageModel、embeddingModel(文中示例使用文本 embedding 模型)、imageModel、videoModel、files、skills、decisionModel/decisionModels(见 2.16)。 - Combining Custom Providers, Provider Registry, and Middleware:三者可叠加 ------ 注册表出模型,middleware 包装行为。
- Global Provider Configuration / Customizing the Global Provider :配置全局默认 provider(
fallbackProvider),使模型字符串(如"anthropic/claude-sonnet-5.5")可直接工作;文档含 Experimental decision models 的注册方式。 - Anthropic 专属选项示例类型:
AnthropicLanguageModelOptions。
2.14 Error Handling
定位 :区分常规错误 与流式错误两套处理方式。
- Handling regular errors :
generateText等一次性调用以异常 reject;用 try/catch 并配合maxRetries控制 provider 错误重试。 - Handling streaming errors (simple streams) :简单文本流不含 error part,错误需在
onError中处理。 - Handling streaming errors (streaming with
errorsupport) :完整流协议里error是流的一种 part (见 2.1 的 part 列表),错误成为流的一部分而非抛出,避免服务端崩溃;result.stream/fullStream可观察到error。 - Retrying provider errors after streaming starts :流已开始后重试 provider 错误的能力有限,文档给出
StreamProviderError、isRetryable与streamRetries的语义(配合onLanguageModelCallStart/onLanguageModelCallEnd/onStepStart/steps观察每次尝试)。 - Handling stream aborts :
abortSignal(含AbortSignal.timeout())触发时用onAbort处理;abort也是流的一种 part。
2.15 Testing --- mock providers
定位 :用 AI SDK Core 的mock provider 做无网络的单元测试。
MockLanguageModelV4--- 语言模型 mock;文档示例覆盖generateText、streamText、generateText with Output、streamText with Output、ToolLoopAgent(agent 也可整体 mock)。MockEmbeddingModelV4--- embedding 模型 mock(配embed/embedMany)。- 辅助:
simulateReadableStream(把固定 chunk 列表变成流,驱动streamText)、mockId(固定工具调用/块 id,避免快照抖动)、mockValues(固定随机/时间等值)。 - Simulate UI Message Stream Responses --- 模拟整条 UI 消息流,用于测试前端消费侧。
2.16 Embeddings
定位:把文本/数据转成向量,用于检索、聚类、相似度匹配。
- 核心 API :
embed({ model, value })(单值)、embedMany({ model, values })(批量)、cosineSimilarity({ a, b })(相似度计算)。 - Token Usage :
embedMany返回usage(token 用量);单值同理。 - Settings :provider 无关设置
dimensions(输出维度)、providerOptions(如providerOptions.google.content传 content 类型配置)。 - 工程选项 :
maxParallelCalls(并行请求数)、maxRetries(重试)、abortSignal与timeout(AbortSignal.timeout())、headers(自定义请求头)。 - Response Information :
rawResponse(body)保留 provider 原始响应;providerMetadata保留各家元数据。 - Embedding Middleware :用
wrapEmbeddingModel包装 embedding 模型(类型EmbeddingModelMiddleware),与 2.11 的wrapLanguageModel同构。 - Embedding Providers & Models:各家 embedding 模型通过 provider 工厂获取(也可经 Provider Registry,见 2.13)。
2.17 Reranking
定位 :对候选文档按与查询的相关性重新排序,常用于检索管线第二段。
- 核心 API :
experimental_rerank({ model, query, documents })(文中亦称rerank);结果字段ranking(每项含index、relevanceScore/score、并可用originalIndex回指原数组下标)、query、documents、model、usage(totalTokens)。 - Working with Object Documents :文档可以是字符串,也可以是对象(
document)。 - Understanding the Results :
ranking按相关性降序,index指向传入 documents 的位置。 - Settings :
topN(只返回前 N 条)。 - 工程选项 :
maxRetries、abortSignal、timeout、headers;rawResponse(body)与providerMetadata。 - 与 Embeddings 组合即为典型 RAG 检索:
embedMany→ 相似度召回 →experimental_rerank精排。
2.18 Decisions --- experimental_decide
定位 :让模型对结构化问题 (选择题、打分、布尔判断)基于共享状态 给出答案,并返回概率/置信度 ------ 比自由文本更适合做判定门、分类、评估。
- 核心 API :
experimental_decide({ model, questions, state, options }),返回answers。 - Question types :三类 ------
choice(从选项选一个)、score(打分)、boolean。类型Experimental_DecisionQuestion;supportedQuestionTypes描述模型支持哪些题型。 - Multimodal state :判定可基于多模态状态,状态类型
Experimental_DecisionState/Experimental_DecisionStatePart,复用内容 part(TextPart、FilePart;文档示例含bottom/box/left/right/top等图像定位语义)。 - Probabilities and confidence :返回
probabilities/probability;rounding选项含probabilityDecimals、scoreDecimals控制位数。 - Provider models / Model aliases and registries / Default-provider strings :决策模型可直接实例、走 Provider Registry(
createProviderRegistry、customProvider、decisionModel、decisionModels、自定义separator),或用默认 provider 字符串;AI Gateway 场景(AI_GATEWAY_API_KEY、providerOptions.gateway.models)。 - Errors and cancellation :
InvalidArgumentError、InvalidResponseDataError、NoSuchModelError、NoSuchProviderError、UnsupportedModelVersionError、Experimental_DecisionRefusalError(模型拒绝作答);支持abortSignal、headers。 - Scope and examples :文档给出
typeSafeAi用法与Experimental_DecisionMockModelV4(测试用 mock),以及回调experimental_onDecisionModelCallStart/experimental_onDecisionModelCallEnd(见 2.20)。 - 与 2.2 的
Output.choice()区别:Output.choice是文本生成流程 里的输出模式,experimental_decide是独立 API,带状态、概率与拒绝语义。
2.19 Image Generation
定位:文生图与图像编辑的统一 API。
- 核心 API :
generateImage({ model, prompt }),结果含image(首图)与images(多图);文件形式为GeneratedFile(uint8Array/base64、mediaType)。 - Settings :
size(如 provider 支持的具体尺寸)、aspectRatio、seed(可复现)、n/count(多图)、maxImagesPerCall(每次调用上限)、provider 专属providerOptions。 - Generating Multiple Images / Image-to-Image Editing :文档含多图画与编辑支持检测
supportsFileInputs、supportsMaskInputs(判断模型能否接受输入文件与蒙版)。 - 工程选项 :
maxRetries、abortSignal、timeout、headers、warnings(不支持的设置)、providerMetadata、usage。 - Underlying calls :模型调用底层是
doGenerate/doStream(provider 侧接口)。 - Error Handling :无法产出图像时抛
AI_NoImageGeneratedError(cause、images、usage、warnings)。 - Image Middleware :
wrapImageModel(类型ImageModelV4Middleware)包装图像模型。 - Generating Images with Language Models :也可通过语言模型的工具/多模态输出产生 images(见 2.1 的
files)。
2.20 Realtime --- 实时语音对话
定位 :构建实时(音频双向)对话。
- Setup Endpoint --- 服务端建立 realtime 会话(示例 id 前缀
vcst_)。 - AI Gateway --- 可经 AI Gateway 接入 realtime 模型。
- Client Session --- 客户端会话管理;React 侧 hook
experimental_useRealtime,用useMemo建立 session,api.session暴露会话 API。 - Tool Calling / Server-Backed Tool Endpoint / Client Tool Handler --- realtime 会话内也支持工具调用:服务端提供 tool endpoint,客户端用
onToolCall处理并回写addToolOutput。 - Supported Providers --- 文档列出支持的 realtime provider。
2.21 Transcription / Translation / Speech
Transcription(语音转文本)
- 核心 API :
transcribe({ model, audio }),结果含text;音频输入可为ArrayBuffer、Uint8Array、Buffer、文件、URL(URL)。 - Streaming Transcription :
experimental_streamTranscribe,含fullStream(流 part)与textpromise;相关事件回调experimental_onStreamTranscriptionStart/experimental_onStreamTranscriptionEnd;实时模型示例scribe_v2_realtime。 - Settings :
inputAudioFormat、language、providerOptions(各家参数)。 - Download Size Limits :
createDownload与下载大小限制(超限抛DownloadError)。 - 工程选项 :
maxRetries、abortSignal、timeout、headers、warnings;错误AI_NoTranscriptGeneratedError(cause);onError、telemetry。 - Transcription Models (文中出现):OpenAI
whisper、Deepgramnova/telephony,AssemblyAIuniversal,Googlechirp_2/chirp_3,ElevenLabsscribe_v1/scribe_v1_experimental/scribe_v2,以及wizper、enhanced、full、machine、low_cost等模型变体。
Translation(语音翻译)
- 核心 API :
experimental_transcribe之外的experimental_translate(文中亦简称 translation),结果含translationText与音频输出。 - Stream parts :
experimental_streamTranslate,fullStream支持文本与音频 chunk,可用includeRawChunks保留 provider 原始 chunk(raw)。 - Settings :
sourceLanguage、targetLanguage、inputAudioFormat、outputAudioFormat、providerOptions。 - 工程选项 :
abortSignal、headers、maxRetries;错误AI_NoTranslationGeneratedError(cause、error);response。
Speech(文本转语音)
- 核心 API :
generateSpeech({ model, text }),结果含音频(Uint8Array/base64、mediaType)。 - Telemetry 、
providerOptions(各家音色/稳定性/输出格式)、warnings、headers、maxRetries、abortSignal、timeout。 - Error Handling :
AI_NoSpeechGeneratedError(cause)。 - Speech Models (文中出现):ElevenLabs
eleven_v3、eleven_turbo_v2/eleven_turbo_v2_5、eleven_flash_v2/eleven_flash_v2_5、eleven_multilingual_v2,以及default音色配置。
2.22 Video Generation
定位:文生视频与图生视频。
- 核心 API :
experimental_generateVideo({ model, prompt }),结果含video/videos(GeneratedFile:uint8Array、base64、url)。 - Settings :
aspectRatio、resolution、durationSeconds(时长)、fps(帧率)、generateAudio(是否生成音频)、seed、maxVideosPerCall、providerOptions。 - Image-to-Video Generation / First and Last Frame :用
image、lastFrame、frameImages控制起止帧。 - Reference Inputs :
inputReferences(参考图/素材)。 - Polling(关键机制) :视频生成通常是异步任务 ------
poll选项含poll.delay(intervalMilliseconds)与poll.timeoutMs;也支持createWebhook走 webhook 通知(webhook、received)。 - 工程选项 :
maxRetries、abortSignal、timeout、headers、warnings、providerMetadata、usage;错误AI_NoVideoGeneratedError(cause);body、responses、mediaType。
2.23 File Uploads 与 Skill Uploads
File Uploads(文件上传与 provider 引用)
- 核心 API :
uploadFile({ data, mediaType, name, purpose });结果字段files、id、bytes、byteSize、createdAt、expiresAt、api、providerMetadata。 - Provider References :返回
ProviderReference,可在后续推理调用中引用已上传文件而无需重复上传 ,跨 provider 使用(Multi-Provider Usage );purpose决定文件用途(各家取值不同)。 - Supported File Types / Provider-Specific Options / Streaming Uploads :支持类型、各家选项(
providerOptions)、以及流式上传(避免整体载入内存)。 - 不支持时抛
UnsupportedFunctionalityError;abortSignal、headers可用。
Skill Uploads(技能上传)
- 定位 :把 Agent Skill (
SKILL.md目录包)上传到 provider,之后在推理调用中以引用方式使用。 - 核心 API :
uploadSkill({ skill }),结果类型UploadSkillResult(字段id、name、description、displayTitle、latestVersion、expiresAt、sha256Hash、size、source、path、api、warnings、providerMetadata)。 - Skill Files :技能由文件集合构成(示例用
fs.readFileSync读SKILL.md,内容可为字符串或Uint8Array)。 - Using Skills in Inference Calls :Anthropic 走
providerOptions.anthropic.container.skills;OpenAI 走providerOptions.openai.skills;content中type: 'skill'引用。 - 与 Harnesses 的 Skills(见 3.3)是不同层:这里是把技能上传到 provider 容器 ,那里是给 harness 运行时装配技能。
2.24 Telemetry --- OpenTelemetry 集成
定位:把生成/embedding/rerank/工具调用变成 OTel span,接入现有可观测性栈。
- Enabling telemetry(两步) :Step 1 在 instrumentation 文件(如
instrumentation.ts)里registerTelemetry(...)注册 OpenTelemetry 集成;Step 2 在调用上开启experimental_telemetry: { isEnabled: true }。Opting out ------ 默认关闭,也可逐调用禁用。 - Telemetry Metadata :
functionId(区分同应用内不同调用,写入ai.telemetry.functionId)、metadata(自定义属性)、captureContent(是否记录输入输出内容,默认不记录敏感内容)。 - 上下文可见性 :
telemetry.includeRuntimeContext、telemetry.includeToolsContext(默认不把 context 放进 span,见 2.6)。 - Custom Tracer :可传自定义
tracer(Tracer/TracerProvider)而非全局默认。 - Telemetry Integrations :Registering integrations globally (
registerTelemetry)、Per-call integrations (telemetry.integrations)、Tracing channel(多通道)。 - Building a custom integration :实现集成的 Available lifecycle methods (
onStart、onStepStart、onToolExecutionStart、onToolExecutionEnd、onStepEnd、onEnd、onError、onAbort等),并可enrichSpan;span 类型spanType取值CLIENT/INTERNAL;recordInputs/recordOutputs控制内容记录;工具种类区分FunctionTool、DynamicTool、ProviderDefinedTool、ProviderExecutedTool。 - GenAI Semantic Conventions(新语义约定) :
gen_ai.operation.name、gen_ai.provider.name、gen_ai.request.model、gen_ai.response.model、gen_ai.response.id、gen_ai.response.finish_reasons、gen_ai.usage.input_tokens/gen_ai.usage.output_tokens/gen_ai.usage.characters/gen_ai.usage.seconds、gen_ai.input.messages/gen_ai.output.messages/gen_ai.output.type/gen_ai.system_instructions、gen_ai.tool.name/gen_ai.tool.type/gen_ai.tool.definitions/gen_ai.tool.call.id/gen_ai.tool.call.arguments/gen_ai.tool.call.result、gen_ai.client.operation.duration、gen_ai.execute_tool.duration、gen_ai.agent.name、gen_ai.evaluation.result、gen_ai.system。 - Legacy AI SDK Spans(
LegacyOpenTelemetry) :AI SDK 自有属性命名空间ai.*:ai.operationId、ai.model.id、ai.model.provider、ai.prompt(ai.prompt.messages、ai.prompt.tools、ai.prompt.toolChoice)、ai.request.text、ai.response.id/ai.response.model/ai.response.text/ai.response.object/ai.response.toolCalls/ai.response.usage/ai.response.finishReason/ai.response.providerMetadata/ai.response.timestamp/ai.response.msToFirstChunk/ai.response.msToFinish、ai.stream.firstChunk/ai.stream.finish、ai.settings.maxOutputTokens/ai.settings.maxRetries/ai.settings.output、ai.usage.promptTokens/ai.usage.completionTokens/ai.usage.tokens、ai.value/ai.values、ai.toolCall.id/name/args/result、ai.telemetry.functionId,以及 span 名:ai.generateText、ai.generateText.doGenerate、ai.streamText、ai.streamText.doStream、ai.generateObject、ai.generateObject.doGenerate、ai.streamObject、ai.streamObject.doStream、ai.embed、ai.embed.doEmbed、ai.embedMany、ai.embedMany.doEmbed、ai.embedding、ai.embeddings、ai.generateSpeech、ai.transcribe、ai.streamTranscribe、ai.rerank、ai.reranking、ai.decide。
2.25 DevTools
定位:本地调试与检查 AI SDK 应用 ------ 捕获真实请求/响应/步骤/媒体并在专用 viewer 里回放。
- Installation & Requirements:安装 DevTools 包并满足 Node 版本与 OTel 前提。
- Register the integration :把 DevTools 作为一个 telemetry integration 注册(与 2.24 的
registerTelemetry同一扩展点),因此任何走 telemetry 的调用都能被捕获 ------ 覆盖generateText、streamText、generateObject、streamObject、ToolLoopAgent等。 - Launch the viewer :用
npx启动 viewer(http/https 本地端口);Choose a viewer theme。 - Monorepo usage:monorepo 下的注册与端口共享方式。
- Captured data :一次 run 与其中每个 step (消息、工具调用与结果、usage、finishReason)、Media previews (图片/音频等媒体预览,用
include/media选项控制),并支持toModelOutput的表示形式。 - How it works:靠 telemetry span 上报 → 存储 → viewer 读取。
- Security considerations :DevTools 捕获的是真实输入输出(可能含敏感数据) ,只应在本地/受控环境启用,不要把捕获数据当作生产遥测出口(内容记录由 2.24 的
captureContent、telemetry.includeRuntimeContext/includeToolsContext控制)。
2.26 Lifecycle Callbacks
定位 :官方统一文档,覆盖 generateText、streamText、embed、embedMany、rerank、experimental_decide 六类调用的生命周期事件(ToolLoopAgent 复用同一批 generation 事件类型,见 1.2)。
- Use Cases :Request Logging、Measuring Model Performance (用
performance,含stepTimeMs、responseTimeMs、toolExecutionMs、timeToFirstOutputMs等,见 2.1)、Debugging Multi-Step Tool Calls (steps、stepNumber)、Monitoring Tool Execution(toolCall、toolContext)、Observing Embeddings and Reranking。 - Generation Lifecycle(事件顺序) :
onStart→ 每步 `onStepStart` → `onLanguageModelCallStart` → `onLanguageModelCallEnd` → (每个工具)`onToolExecutionStart` → `onToolExecutionEnd` →onStepEnd→onEnd;流式另有onError、onAbort(streamText的onChunk更细粒度,见 2.1);工具输入侧onInputStart/onInputDelta/onInputAvailable。 generateText与streamText:上表全部回调;streamText特有onChunk、onError。embed与embedMany:onStart/onEnd,事件含value/values、embedding/embeddings、usage(EmbeddingModelUsage)、model、provider、response。rerank:onStart/onEnd,事件含query、documents、ranking、topN、usage。experimental_decide:experimental_onDecideStart/experimental_onDecideEnd(事件类型Experimental_DecideStartEvent/Experimental_DecideEndEvent),并有onQuestion/onAnswer、模型调用级onModelCallStartEvent/onModelCallEndEvent(亦见 2.18 的experimental_onDecisionModelCallStart/End);事件含questions、answers、state、finishReason、usage、callId。- Event Data Reference :各事件的公共数据类型 ------
StepResult、StepResultPerformance、LanguageModelUsage、LanguageModelCallPerformance、LanguageModelRequestMetadata、LanguageModelResponseMetadata、TypedToolCall、FinishReason、ProviderOptions、activeTools、toolChoice、instructions、messages、modelId、providerOptions、maxRetries、headers、timeout、responseMessages、finalStep、warnings、operationId、runtimeContext(RUNTIME_CONTEXT/CONTEXT)、toolOutput判别联合(type、output、error)、toolExecutionMs、stepNumber、steps、toolCalls/toolResults、content、text、finishReason。 - Runtime and Tool Context :回调里可读
runtimeContext与toolContext;结合telemetry.includeRuntimeContext/telemetry.includeToolsContext决定是否进入 span(见 2.6、2.24)。
3. AI SDK Harnesses 板块
定位 :harness 抽象让你通过统一的 AI SDK 界面运行成熟的 agent harness 。Harness = 完整的 agent 运行时 (如 Claude Code、Codex、Pi),它拥有的能力大过一次模型调用 :workspace 访问、内置编码工具、原生 session 状态、compaction(压缩) 、权限流程、以及运行时专属配置。Harness adapter 可以让运行时在 sandbox 中执行,但各 adapter 的执行环境不同 ------ 使用前务必读该 adapter 的运行时位置与安全指引。
与 provider/model 的关系(关键区分) :harness 抽象独立于 provider/model 抽象 ------ provider 向 Core 函数(generateText、streamText)暴露模型;harness 向 HarnessAgent 暴露 agent 运行时 。两者解耦但尽量使用兼容原语 :harness 输出被投影进 AI SDK 的流与响应类型 ,因此消费模型流的地方也能消费 harness 流(例如把 HarnessAgent 的 stream 交给 toUIMessageStream 并用 useChat 渲染)。API 设计力求让 AI SDK 用户熟悉,但 harness 运行时的概念确实与底层语言模型不同:配置在契合处沿用 AI SDK 惯例,在 harness 行为不同处有意分叉。
Harness 包是实验性的 ,早期 API 在版本之间预期会有破坏性变更。
何时用 harness :需要现成 agent 运行时驱动任务时 ------ 能检查和修改沙箱 workspace 的编码 agent;自带内置工具与权限模型的运行时;由运行时自己掌握对话历史 的多轮会话;希望保留 harness 原生行为而不是用 tool loop 重造的工作流。反过来:需要直接控制模型调用、工具循环、模型设置、结构化输出或自定义 agent 架构时,用 provider + model。
四个核心部件:
HarnessAgent------ 应用代码里使用的 AI SDK agent 实现。- Harness adapter ------ 连接具体运行时的包,例如
@ai-sdk/harness-claude-code。 - Sandbox provider ------ harness 运行所在的隔离文件系统与进程环境。
- Session ------ 一次 harness 运行的活动对话与 workspace 状态。
Compatible Streams :HarnessAgent.generate() 返回 AI SDK 的 GenerateTextResult ,HarnessAgent.stream() 返回 StreamTextResult ,因此可以消费熟悉字段:result.text、result.stream、result.steps、result.usage、result.responseMessages。harness 专属事件被翻译成兼容 stream part ------ text、reasoning、tool calls、tool results、usage、finish reasons 尽量用 AI SDK 同形结构;没有一等公民 part 的事件(如 workspace 文件变更、compaction)以 dynamic provider-executed tool parts 的形式呈现(见 3.2 与 3.8)。
Sessions Matter(最关键的差异) :与语言模型调用不同,harness session 拥有状态 ------ 它承载 harness 运行时、sandbox、工作目录、原生对话历史、待处理审批。跑每一轮之前要先创建 session:
ts
const session = await agent.createSession();
try {
const result = await agent.generate({ session, prompt: 'Inspect the repository and summarize the test setup.' });
console.log(result.text);
} finally {
await session.destroy();
}
服务端路由要用稳定的 sessionId ,并持久化 session.detach() 或 session.stop() 返回的 resume 状态。
3.1 HarnessAgent
定位 :Harnesses 板块的主 API ------ 由 harness adapter 支撑的 AI SDK Agent 实现 ,提供 generate() 与 stream(),返回 AI SDK 兼容的结果,而实际推理由预先配置好的 harness 完成。
Installation :core harness 包 + 一个 harness adapter + 一个 sandbox adapter。Bridge-backed harness(Claude Code、Codex 等)必须使用真实网络 sandbox ,如 @ai-sdk/sandbox-vercel;host-runtime harness(如 Pi)也可用 @ai-sdk/sandbox-just-bash,因为它不需要 sandbox-exposed port。并确保环境变量里备好 sandbox 与 harness 凭据。
Create an Agent :在 module scope 构造 agent ------ 它持有配置,不持有 live session ,live state 属于 HarnessAgentSession 。sandbox session 单独创建后传给 agent.createSession() 。model 指定 harness runtime 使用的模型,模型标识符是各 harness 专属的 ;省略则用 harness 默认模型;model 按轮应用 ,因此 prepareCall 可以在轮次之间替换它。
Run a Turn :generate() 排空整轮 并返回 GenerateTextResult;stream() 用于增量输出。
Lifecycle Callbacks :在 HarnessAgent 上配置回调以观察 agent 调用、模型步骤与工具执行 。单次 generate() / stream() 上传入的回调会额外执行,且构造器级回调先跑 ;回调异常会被忽略,不会改变 agent 执行 。harness runtime 在内部执行其内置工具,对这些工具而言 onToolExecutionStart / onToolExecutionEnd 描述的是 runtime 上报结果之后的逻辑工具生命周期,回调仍在工具结果发布到结果流之前送达。
Runtime Context :runtimeContext 让应用上下文对每一轮 可用;用 prepareCall 为新 prompt 轮替换它。准备好的 context 在 generate() / stream() 中可用,并在内存内续跑(continueGenerate() / continueStream())期间保持不变 ;生命周期回调收到完整 context,结果里也有 finalStep.runtimeContext。runtime context 默认被排除在遥测之外 ,用 telemetry.includeRuntimeContext 逐个顶层属性加白(只有设为 true 的属性 才发给遥测集成);由于回调与结果仍拿到完整 context,不要存放这些消费方不该访问的密钥。
Generate Structured Output :构造时设 output,则每一轮都要求同一个类型化输出 ;agent 把输出规格转成 JSON Schema 交给 harness adapter、校验完成的响应、并通过 result.output 返回解析值。stream() 下读 partialOutputStream 拿增量解析值,await result.output 拿校验后的最终值。结构化数据同时仍以 JSON 存在于普通文本与流表面;adapter 不会把它加进 finish part 。Harness 结构化输出要求 schema ------ 无 schema 的 Output.json(),以及无法强制 schema 的 adapter 或运行时配置,都会抛 HarnessCapabilityUnsupportedError。
Messages and History :harness session 拥有自己的原生对话历史 。传 messages 或消息数组形式的 prompt 时,HarnessAgent 只取最新的 user message 作为本轮新输入,不会把既往对话重放进 harness 。但末尾的 tool message 另当别论 :tool approval response 与客户端提供的 tool result 会继续产生对应请求/调用的那个未完成 harness turn 。这与模型调用不同(模型调用通常由应用发送完整历史)------ 聊天路由应持久化并 resume harness session,而不是依赖消息重放。
Reading the Runtime's Own History :runtime 的对话可能在你进程之外增长(例如同一会话在 agent 自己的 CLI 里被交互续写),实时事件流看不到 那些交换。能访问 runtime 存储的 adapter 通过 session.readHistory() 暴露它。历史读取是 adapter 特定的:adapter 未实现 历史读取时抛 HarnessCapabilityUnsupportedError;实现了但当前环境无法触及 runtime 存储(例如存储位于远程 sandbox 内)时抛 HarnessHistoryUnavailableError ;尚无消息的对话不算错误 ,resolve 为空 messages 数组。
Session Lifecycle(每轮之后务必显式收尾):
session.destroy()停止 runtime 并丢弃可续跑性。session.detach()停靠(park)runtime、返回 resume 状态,并让传入的 sandbox 继续运行以便之后 attach ;若轮次未完成,resume 状态包含 continuation 状态。session.stop()先保存 resume 状态再停止 runtime;轮次未完成时同样包含 continuation 状态。session.suspendTurn()面向跨进程边界继续活动轮次的高级场景。session.hasUnfinishedTurn()报告当前轮次是否必须先继续或挂起,session 才能接受新 prompt。
一次性脚本与测试用 destroy();需要多轮连续性的 HTTP 路由用 detach() 或 stop()。
Change Settings Between Turns :用 callOptionsSchema + prepareCall 派生每轮的 model、skills、instructions、tools、runtimeContext (与 ToolLoopAgent 同一套 call-options 模式)。prepareCall 在新 prompt 且其自定义 options 校验完成后运行,其设置随后整轮固定 ;若该轮因工具结果、审批、停止条件或进程交接而暂停,续跑复用同一套设置、不会再次调用 prepareCall (防止轮内设置漂移)。改 model 不会创建新 harness session :每个 adapter 在下一个 prompt 前切换/重配 runtime 并保留 session 的对话历史。但 Codex adapter 在 skills、instructions 或工具目录变化时会启动全新的原生 Codex thread (因为 codex exec resume 保留原始原生 thread bootstrap)------ harness session 仍可用,但既往原生上下文不会跨越这个设置变化边界;设置未变的轮次继续现有原生 thread。abortSignal 直接传给 generate() / stream() (它本就是 per-call 设置,不属于 prepareCall);output 也固定在 agent 上 (响应格式绑定 agent 的 output schema)。把 sandboxSession 传给 agent.createSession() 时调用方保有该 sandbox 的所有权 :session.stop() / session.destroy() 只结束 harness runtime,不会停止或销毁传入的 sandbox session ,此时 agent 构造器无需 sandbox provider。
Resuming :持久化不透明的 resume 状态。示例里 harness sessionId 就是 chatId,sandbox ID 从同一已知 ID 派生;若应用无法派生 sandbox ID,就改为持久化 sandboxSession.id 连同 harness sessionId 与 resume 状态。重新 attach sandbox 之后再让 agent resume 。创建时指定的 sandboxId 命名一个「新的」live sandbox,永不查找已有 ;用同一 ID 复用会在该 sandbox 已存在时失败 ------ 只有 resume 函数会执行查找 。HarnessAgent 在把 resume 状态交给 runtime 之前会校验它出自同一个 harness adapter 。若 resume 状态包含未完成轮次,先调用 continueStream() / continueGenerate() 再发新 prompt 。Vercel 的 resume 函数在 sandbox detach 后仍在运行、或被停止但留有可恢复快照时都能重新 attach;sandboxSession.destroy() 删除之后该 ID 无法再 resume。
Continue a Suspended Turn :需要跨进程边界交接活动轮次时,先挂起轮次并持久化 continuation 状态。只有来自 suspendTurn() 的原始 continuation 状态时,用 continueFrom resume,然后不发新 prompt 地继续该轮 :continueStream() 取增量输出,continueGenerate() 排空续跑的轮次并返回 GenerateTextResult。toolsContext 与 runtimeContext 有意不写进 continuation 状态 (它们可能含凭据或不可序列化的宿主对象);若被挂起的轮次使用了 prepareCall 派生的 context,把同样的值传给 createSession 以在续跑进程中重新绑定 ;未重新绑定的进程 resume 会回落到 agent 构造器级的 runtimeContext 与 toolsContext。
Stop After a Harness Step :用 stopWhen 进入语义步骤边界。谓词在真实的 harness 工具步骤之后 运行(这些步骤还能继续进入下一个模型步骤),并收到当前调用已完成的 steps 。谓词命中时,返回的 result 结束,而底层轮次仍未完成 ;相反,终结性的纯文本步骤 会消费该轮的 finish 事件并自然收尾。stopWhen 没有默认值 :省略时 HarnessAgent 持续运行到轮次自然结束或停下等待宿主输入,保留无步骤控制时的 agent 行为。传一个谓词或数组,任一命中即结束当前 result slice ;被停止的轮次用 createSession({ continueFrom }) + continueStream() / continueGenerate() 恢复。
Prepare the Sandbox(sandboxConfig):在 harness 启动之前准备 sandbox。
sandboxConfig.onBootstrap在 sandbox 模板创建期间 运行,时机在 harness adapter 自身 bootstrap 之后、支持快照的 provider 发布快照之前;用于应被未来 session 复用的昂贵设置 。提供onBootstrap就必须同时提供bootstrapHash,并在 bootstrap 产物应当使可复用快照失效时改变 hash。sandboxConfig.onSession在每个 sandbox session 被获取且其工作目录就绪之后运行(包括被 resume 的 session);用于 per-session 文件或轻量配置。workDir可选 :提供时必须相对于 sandbox 的默认工作目录 ,并用作 session 工作目录;设为'.'即直接使用 sandbox 默认工作目录本身。省略时普通 session 使用默认的<harnessId>-<sessionId>目录,而onBootstrap收到的是 sandbox 的默认工作目录。
Prepare Reusable Sandboxes :用 agent.getSandboxTemplate() 在创建 sandbox 之前解析某个 harness 的 bootstrap recipe(配合 sandboxConfig.onBootstrap);模板身份在 sandbox 创建前即已知,Vercel 会持久化准备好的快照并由它创建 live sandbox,相同的调用复用该快照 。多个 harness 共享同一个调用方 bootstrap 钩子时,可从所有 adapters 构建一个 模板:重复的 harnessId 以最后一个为准,且 recipe 身份在哈希前排序 ;onSession 不属于模板 ,仍会在每个获取的 session 上单独执行。派生模板的 cache key 含源快照 ID ,因此同 source + 同 template 的重复调用会复用准备好的快照 ------ 依赖缓存模板时要固定可变的 Git revision、镜像 tag 与源 URL 。sandboxId 命名的是 live sandbox,不是其可复用模板 ;原有的原生 name 选项同样命名 live sandbox,两者都提供时其值必须一致。
Settings(HarnessAgent 主要设置项) :harness(adapter 实例)、model(可选,harness 专属标识符)、id (可选的稳定 agent 标识符)、instructions(支持时追加到 runtime 的 system/developer prompt ,否则前置到 user prompt )、headers(构造期固定 ;不允许 authorization、x-api-key、user-agent、x-client-app )、callOptionsSchema + prepareCall、output、stopWhen、tools(harness 调用时由宿主执行的 AI SDK 工具)、runtimeContext、activeTools / inactiveTools、skills、permissionMode、toolApproval、sandboxConfig、以及 telemetry / debug / onLog(可观测性与诊断;用 telemetry.includeRuntimeContext 给 runtime context 属性加白)。遥测报告每轮解析出的 model、instructions 与 active 的宿主定义工具;skills 属于 adapter 上下文,没有对应的 AI SDK 遥测字段,因此不包含在标准遥测事件中 。adapter 专属设置放在 adapter 工厂上 ,例如 createCodex({ reasoningEffort: 'high' })。
Custom Sandbox Orchestration :应用自己创建与管理 sandbox 时,先准备网络 sandbox session,再把同一个 session 传给 agent.createSession();agent 既不创建 sandbox,也不会停止或销毁调用方拥有的 sandbox 。Basic Sandbox Sessions Without Network Control :只暴露文件系统与进程 API 的受限 basic session 只在项目无法暴露完整网络 session 时才用 (官方强烈建议传完整网络 session);agent 仍把 sandbox 生命周期留给调用者,且对 bridge-backed harness 必须在 adapter 上配置 bridge 端口及其外部可达 endpoint,因为 basic session 无法解析它们。
错误类型 :HarnessCapabilityUnsupportedError (adapter/运行时不支持该能力:结构化输出缺 schema、历史读取未实现、审批模式不受支持)、HarnessHistoryUnavailableError(实现了历史读取但当前环境无法访问 runtime 存储)。
3.2 Harness Tools
定位 :harness 有三类工具面 ------ ① 底层 harness runtime 暴露的 built-in tools(文件读写、shell、web search 等);② 你通过 tools 设置传给 HarnessAgent 的 AI SDK 工具;③ 通过 harness adapter 的 mcpServers 设置接入的外部 MCP 工具 。本页只讲 harness 特有行为,通用工具概念见 Core(2.7)。逐节细节 (内置工具的 providerExecuted: true 与跨 harness 通用名、宿主工具 toolsContext 的类型推导与校验、客户端工具的挂起/续跑、activeTools 与 inactiveTools 的运行时差异、受限 sandbox、permissionMode 与 toolApproval 两条通道、fileChange / compaction 投影)见 3.8。
- Built-in Tools ------ harness 自带的运行时工具:文档列举
bash、read、edit、write、glob、grep、webSearch等;permissionMode控制范围:allow-all、allow-edits、allow-reads。 - Host-Executed Tools ------ 由宿主(AI SDK)执行的工具,用
agent.tools/tools传入 AI SDKtool()定义,execute、contextSchema、toolsContext沿用 Core 语义(见 2.7)。 - Client-Side Tools ------ 省略
execute即表示由浏览器/用户交互/外部进程提供结果,客户端用addToolOutput回写(配合useChat,见 3.6);此时 result slice 在 tool-call 步骤处结束,session.hasUnfinishedTurn()保持true。 - Tool Filtering ------
activeTools(允许列表)/inactiveTools(禁止列表)按名筛选合并工具集;两者只能传其一。 - MCP Tools ------ 外部 MCP 工具通过 adapter 的
mcpServers设置接入(不是 Core 的createMCPClient路径)。 - Sandbox in Tool Execution ------ 宿主工具通过
experimental_sandbox收到 session 的 sandbox(受限 sandbox session) :能读写文件、执行命令,但无法停止网络沙箱或修改其网络策略。 - Tool Approvals(两条互不相通的通道) ------ harness 区分 内置工具的权限 与宿主工具的审批 :内置用
permissionMode,宿主用toolApproval(状态not-applicable/approved/denied/user-approval,见 1.7),需要审批时流在tool-approval-request之后暂停 。宿主工具的审批由HarnessAgent负责因而跨 adapter 可用;内置审批则由 adapter 决定,不支持的 adapter 会在指定该模式时报错(详见 3.8)。 - File Changes and Compaction ------ workspace 文件变更与 compaction 没有一等公民 part ,因此以 dynamic provider-executed tool parts (
part.dynamic)投影到流中。
3.3 Harness Skills
定位 :Skills (agentskills.io/)是可复用的指令包 ,用于项目约定、工作流指引、领域特定流程等「应当被底层 harness 运行时发现」的指令。可以为 HarnessAgent 配置 skills,也可以在已完成的轮次之间替换它们。
- Define Skills :通过
skills设置传入。每个 skill 有四项:name(稳定标识符)、description(面向模型的简短摘要)、content(完整指令内容)、files(可选的、随 skill 打包的附加文本文件 )。附加文件使用相对 skill 根的 POSIX 路径 ,例如reference.md、references/codes.md、templates/config.json;当希望 agent 去读它们时,在content里引用这些路径。 - When to Use Skills(与 instructions 的分界) :skills 用于按需可用 的可复用指令,而不是像常规
instructions那样始终加载进 agent 上下文 ;instructions用于宽泛的 agent 行为与当前会话优先级。 - 可在已完成的轮次之间 更换 skills,通过
callOptionsSchema+prepareCall实现(见 3.1 的 Change Settings Between Turns)。 - 与 Core 的 Skill Uploads(2.23)不同:这里面向 harness 运行时的技能装配,那里是把技能上传给 provider 容器。
3.4 Harness Adapters
定位 :harness adapter 把 HarnessAgent 连接到具体 agent 运行时 ------ 它们是 AI SDK model provider 在 harness 世界的对应物 :每个 adapter 包装一个运行时,并把它的 sessions、stream 事件、工具、usage、生命周期状态与配置归一化进 harness 契约。
已提供的 adapter(10 个) :Claude Code(@ai-sdk/harness-claude-code)、Cline(@ai-sdk/harness-cline)、Codex(@ai-sdk/harness-codex)、Cursor(@ai-sdk/harness-cursor)、Deep Agents(@ai-sdk/harness-deepagents)、fx(@ai-sdk/harness-fx)、GitHub Copilot(@ai-sdk/harness-github-copilot)、Grok Build(@ai-sdk/harness-grok-build)、OpenCode(@ai-sdk/harness-opencode)、Pi(@ai-sdk/harness-pi)。 Coming Soon :Amp(@ai-sdk/harness-amp)、Goose(@ai-sdk/harness-goose)、Mastra(@ai-sdk/harness-mastra)。
Adapter Capabilities(官方能力矩阵,选型时逐项核对):
| Adapter | Runtime location | Custom tools | Custom skills | Structured output | Built-in tool approval | Built-in tool filtering | History access |
|---|---|---|---|---|---|---|---|
| Claude Code | Sandbox bridge | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| Cline | Host process | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| Codex | Sandbox bridge | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| Cursor | Sandbox via ACP | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| Deep Agents | Sandbox bridge | ✓ | ✓ | ✓ | ✓ | ✓(via auto-rejection) | ✗ |
| fx | Host process | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| GitHub Copilot | Sandbox via ACP | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| Grok Build | Sandbox via ACP | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| OpenCode | Sandbox bridge | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| Pi | Host process | ✓ | ✓ | ✗ | ✓ | ✓ | ✗ |
读表要点:所有已发布 adapter 都不支持 History access (session.readHistory() 目前无一可用);Structured output 在 Cursor、GitHub Copilot、Pi 上不可用 (要求 schema 的 output 会抛 HarnessCapabilityUnsupportedError);Built-in tool approval 与 filtering 只有 Claude Code / Cline / Deep Agents / fx / OpenCode 支持 (Deep Agents 的过滤通过 auto-rejection 实现)------ 因此 permissionMode 非默认值与内置工具过滤在不支持的 adapter 上会报错;Runtime location 分三类 :Sandbox bridge(Claude Code、Codex、Deep Agents、OpenCode)、Sandbox via ACP(Cursor、GitHub Copilot、Grok Build)、Host process(Cline、fx、Pi)------ 执行位置决定安全边界,用前必须读该 adapter 的运行时位置与安全指引(Overview 明确警告)。
3.5 Workflow Utilities --- 把 harness 轮次跑成持久 workflow
定位 :@ai-sdk/workflow-harness 提供在 workflow 内运行 HarnessAgent 轮次的 helper ------ 包内提供可序列化的状态机 ,以及 time-sliced 与 semantic agent step 两种轮次的 runner;你从自己的 'use workflow' / 'use step' 函数里调用相应 runner 。核心 harness 与 workflow 文件是框架无关的,示例中的 HTTP handler 只是以 Next.js 为例(用 Next.js 需先按 Workflow SDK 文档配置项目)。安装时除 workflow 专用包外,还需 core harness 包、一个 harness adapter 与一个 sandbox adapter。
Configuring the Harness Agent(两种模式的关键差异) :agent 大体可按常规配置;使用 semantic agent steps 时把 stopWhen 设为 isStepCount(1),使一次 stream() 恰好完成一个 agent step ;使用 time slices 时省略 stopWhen。
Using Semantic Agent Steps:在每个 agent step 之后持久化 harness 轮次。
- Defining the Agent Step :把 Workflow step 放在自己的模块 里,并在 step body 内动态 import agent ------ 这样 agent、sandbox adapter 及其它 Node.js 依赖不会进入 workflow bundle。从 Workflow step 调用
runHarnessAgentStep()。 - Defining the Semantic Agent Step Workflow :创建 workflow state,只要 agent 还有工作就持续调度
agentStep()。每个ready_for_next_step结果都携带continueFrom,让下一个 Workflow step 继续同一个未完成轮次;轮次完成时finalizeHarnessWorkflow()返回其结果,workflow 失败时抛出。 - Starting the Semantic Agent Step Workflow :从服务端代码启动。传转换后的消息,才能让
HarnessAgent区分「新的 user turn」与 tool approval / tool result 续跑 。workflow state 的sessionId标识 harness session;step 在首次创建 sandbox 之前从中派生sandboxId,并在后续 steps 用同一 ID reattach ------ state 不序列化 live sandbox 。把agent.ts、agent-step.ts、workflow.ts与 route 保持在分离模块中。 - 该示例只覆盖 workflow 执行基础;多轮对话必须在多次 workflow run 之间持久化 harness session 的
resumeFrom状态。
Using Time Slices :按 wall-clock 边界持久化长时间运行的 harness 轮次(适合单步很长的编码任务)。
- 省略 shared agent 上的
stopWhen,从 Workflow step 调用runHarnessAgentTimeSlice();默认使用 750 秒预算 ,传timeSliceSeconds选择不同预算。 - Defining the Time Slice Step:与 semantic agent step 相同 ------ step 独立成模块、body 内动态 import。
- Defining the Time-Sliced Workflow :同样创建 workflow state 并持续调度
timeSliceStep();ready_for_next_step携带continueFrom,结束时由finalizeHarnessWorkflow()返回结果或抛错。 - 销毁时机(重要) :
destroyOnFinish销毁 harness session,但永不销毁 supplied sandbox ;调用方可以在没有后续 step 需要 reattach 时显式sandboxSession.destroy();绝不要在后续 step 必须 resume 的时间片边界销毁它 。若不从sessionId派生sandboxId,就必须单独持久化sandboxSession.id才能跨 steps reattach。
Resume Persistence :workflow 会自动持久化每个 step 返回的 HarnessWorkflowState(含 continueFrom),作用域是当前这次 workflow run ;要跨多次 user-turn workflow run 继续原生 harness session,需按 sessionId 持久化不透明的 resumeFrom 状态 。存储实现对两种 workflow 方式完全相同 ;示例把文件读写放在 Workflow step 里,因为文件系统访问必须留在 workflow 函数之外 ;生产环境改用持久存储而非本地文件。接入点:在创建 workflow state 之前 load 上一次 resumeFrom,在执行循环之后 persist 更新后的值。
3.6 Harness UI(useChat 路由)
定位 :harness 流与 AI SDK UI message streams 兼容 ------ 客户端用 useChat(),服务端路由流式输出 HarnessAgent 的结果。与基于模型的聊天路由最重要的差异是 session 管理 :harness 拥有自己的对话状态,因此路由应按 chat id 去 resume 或创建 HarnessAgentSession,而不是把整段 UI 消息历史重放进模型。
- Client / Agent :客户端照常
useChat();HarnessAgent定义在服务器上。 - Session Store :持久化
session.detach()返回的不透明 resume 状态 ;若该轮因审批暂停或被其它方式打断,这个 resume 状态内部就携带了 continuation 状态 。chat id 可以直接当 harnesssessionId;示例从已知的 chat id 派生稳定的sandboxId,若不派生则必须单独持久化返回的sandboxSession.id。生产环境用持久存储 而不是内存 map。creator 总是创建新 sandbox,并在sandboxId冲突时失败;只有 resume 函数会 reattach 已存在的那个(与 3.1 一致)。 - Route :三步 ------ 把 UI messages 转成 model messages、运行 harness 轮次、再把结果流转回 UI message stream。在获取 session 之前先创建 UI message stream ,这样 sandbox、bootstrap 与 harness 启动失败会作为 UI error parts 发出,而不是变成通用 HTTP 错误 。
getHarnessErrorMessage保留已审阅的、客户端安全的 harness 消息,并掩盖未知服务端错误 。⚠️ 不要把createAgentUIStreamResponse直接用在HarnessAgent上 ,除非你包装 agent 以注入所需 session ------HarnessAgent.stream()每次调用都要求session。 - Detach or Stop :想把 harness runtime 停靠并让 sandbox 保持温暖 以供下个请求时用
detach()(bridge-backed adapters 通常能高效 reattach 或 replay;轮次未完成时detach()的 resume 状态含 turn continuation 状态)。stop()保存 resume 状态并停止 harness runtime,但不会停止 supplied sandbox ------ 该 network session 归调用方所有,应在聊天结束时调用它的destroy(),而不是在后续请求还需要 reattach 时 ;跨进程保留所选sandboxId。 - Rendering Harness Parts :harness 输出使用与 AI SDK model streams 相同的 UI message part 形状 ------
text与reasoningparts;类型化 tool parts(tool-bash、tool-read,或宿主工具tool-weather);dynamic-toolparts 承载fileChange、compaction等动态事件。类型化 harness 内置工具按渲染普通 AI SDK tool parts 的方式渲染 ,并检查part.state的input-streaming/input-available/output-available。 - Type-Safe Tool Parts :在
HarnessAgent的 session options 进入基础Agent调用参数之前,从agent.tools推断 UI tools ,然后客户端用useChat<HarnessMessage>()。
3.7 Harness Terminal UI
定位 :@ai-sdk/tui 可以在终端渲染 harness streams、tool calls、reasoning sections 与 approval prompts 。关键约束:因为 HarnessAgent 的 generate 与 stream 都要求 session,所以要用一个小的 AgentTUIAgent adapter 包装它,为终端 UI 的整个生命周期注入同一个 session。
- 终端持续运行直到用户用
Esc或Ctrl+C退出(与 1.11 一致)。 - 每次终端运行使用一个 session ;若使用长生命周期的终端工具且之后需要 resume,持久化
session.detach()或session.stop()返回的状态。 - 相关:Agents 板块的 Terminal UI(1.11,面向
ToolLoopAgent)、runAgentTUIAPI Reference、HarnessAgent(3.1)。
3.8 Harness Tools 逐节细节(对 3.2 的展开,同一篇官方文档)
Built-in Tools :每个 adapter 声明自己的 runtime 可原生调用 的内置工具;HarnessAgent 把它们与你的宿主工具合并 ,合并后的工具集通过 agent.tools 暴露。内置调用由 harness runtime 执行,不在你的应用进程内 ,因此流 parts 在 runtime 已执行时带 providerExecuted: true 。adapter 尽量使用跨 harness 通用名 :read、write、edit、bash、grep、glob、webSearch;没有通用名的原生工具按原生名出现。
Host-Executed Tools :像给 ToolLoopAgent 传工具一样传给 HarnessAgent;harness 调用 weather 时,由 HarnessAgent 在宿主进程执行 ,再把结果提交回 harness runtime 。宿主工具可声明 contextSchema 并通过 toolsContext 接收轮次作用域(turn-scoped)的上下文;用 prepareCall 在依赖自定义 call options 时替换 toolsContext。 toolsContext 的类型由工具集推导 :没有任何工具声明 context schema 时拒绝传入 ;有工具要求 context 对象时必填 ;所有 context 对象都可选时可选 。执行前 HarnessAgent 会逐个按该工具的 contextSchema 校验 ,并把配置好的 map 暴露在 step 结果与生命周期回调里。工具 context 仅存在于宿主侧,不会被序列化进挂起轮次的状态 ------ 为未完成的轮次重建 session 时必须显式重新绑定 。缺失或非法 context 会在宿主工具执行之前 校验失败;返回给 harness runtime 的校验错误被刻意做成通用信息,以免把宿主侧 context 值与 schema 细节泄露给模型。
Client-Side Tools :省略 execute 表示由浏览器、用户交互或其他外部进程提供结果。harness 调用没有 execute 的工具时,返回的 result slice 在 tool-call 步骤处结束 ,而底层轮次等待结果;session.hasUnfinishedTurn() 保持 true ,session.suspendTurn() 会把 pending 工具调用包含进可序列化的续跑状态 。UI 流程中,把 addToolOutput 之后产生的模型消息传给下一次 stream() / generate(),HarnessAgent 会提取末尾的 tool result 并自动继续暂停的轮次 。直接调用 agent 时,把原始结果传给 continueStream() / continueGenerate() ;外部工具失败时设 isError: true 。要跨进程继续:suspendTurn() → 用 continueFrom 重建 session → 把结果交给 continueStream() / continueGenerate()。
Tool Filtering :activeTools 是允许列表,inactiveTools 是禁止列表,两者都接受合并工具集 里的名字(adapter 声明的内置 + tools 传入的 AI SDK 工具)。二者只能传其一 :TypeScript 设置类型禁止同时出现,运行时也会抛错。对宿主工具 ,inactive 的不会传给底层 harness runtime ;若 runtime 仍尝试调用,HarnessAgent 返回execution-denied 结果。对内置工具 ,是否支持取决于 adapter :有的可原生过滤;有的通过其内置工具审批机制在执行前拒绝 inactive 调用且不发审批 request/response parts ;两者都不支持的 adapter 在你对内置工具做过滤时抛错。
Sandbox in Tool Execution :宿主工具通过与其它 AI SDK 工具相同的 experimental_sandbox 执行选项收到 session 的 sandbox ;该值是受限的 sandbox session ------ 工具可读写文件、执行命令,但无法停掉网络沙箱或修改其网络策略。
Tool Approvals(两条独立通道) :harness 区分内置工具的权限 与宿主工具的审批。
- 内置工具用
permissionMode:allow-all(允许读、编辑、shell 命令,默认 )、allow-edits(允许读与编辑,adapter 支持内置审批时对 shell 命令请求审批 )、allow-reads(只允许读,adapter 支持时对编辑与 shell 命令请求审批)。 - 宿主工具用
toolApproval,接受与 AI SDK 状态对象相同的取值:not-applicable、approved、user-approval、denied。 - 需要审批时流在
tool-approval-request之后暂停 ;继续同一 session 的方式是发送 tool approval response 消息 ------ UI 流程里useChat在你添加审批结果时自动代发 ;直接调用时把审批响应作为下一次stream()/generate()的messages。
Built-in Approval Support :多数 adapter 可暂停内置工具调用等待审批;不支持的 adapter 在指定了不受支持的审批模式时会报错 。宿主工具的审批由 HarnessAgent 负责,因此跨 adapter 都可用。
File Changes and Compaction :部分 harness 事件不是普通工具调用 ;为兼容 UI,HarnessAgent 把它们投影为 dynamic、provider-executed 的 tool parts :fileChange (不透明的 workspace 文件变更)、compaction (runtime 压缩上下文)。先检查 part.dynamic 再假定某个 tool part 属于你的类型化工具集。
4. 选型速查
| 需求 | 选择 |
|---|---|
| 一次模型调用(文本/结构化/工具) | Core:generateText / streamText + Output.* + tool() |
| 自主循环、多次工具调用、可复用 agent | ToolLoopAgent (默认 stopWhen: isStepCount(20)) |
| 循环需要跨进程持久化、失败重试、审批跨挂起存活 | WorkflowAgent (@ai-sdk/workflow,needsApproval) |
| 要跑成熟编码运行时(Claude Code/Codex/Pi),保留其原生行为 | HarnessAgent + adapter + sandbox + session |
| 需要确定性、可重复的多段流程 | core 函数 + Workflow Patterns(链/路由/并行/编排-worker/评估-优化) |
| 敏感动作需要人工放行 | toolApproval(+ 策略化用 @ai-sdk/policy-opa;服务端信任用 experimental_toolApprovalSecret) |
| 上下文会被大量探索污染 | Subagents + toModelOutput |
| 工具太多、prompt 缓存吃紧 | toolSearch() + deferLoading,或 Code Mode |
| 前端聊天 | useChat + createAgentUIStreamResponse / toUIMessageStream + ChatTransport(HarnessAgent 例外 :stream() 每次调用都要求 session,直接套用 createAgentUIStreamResponse 需先包装 agent 注入 session,见 3.6) |
| 本地快速验证 | @ai-sdk/tui(runAgentTUI) |
贯穿全篇的几条硬规则:
- 服务端状态走
runtimeContext(共享)/toolsContext+contextSchema(按工具),不要塞进 prompt ;Workflow 场景下这些值必须可序列化。 ToolLoopAgent默认stopWhen: isStepCount(20),被该默认限制截断时 SDK 会记录 warning ;WorkflowAgent的generate()默认最多 20 步、stream()无上限 (除非显式设置);HarnessAgent的stopWhen没有默认值 ------ 省略时一直跑到轮次自然结束或停下等待宿主输入。- 审批只在 AI SDK 执行 的工具上生效,provider-executed 工具例外;
useChat模式下消息历史是客户端可控输入,敏感工具必须签名字段。 prepareStep的改写只作用于当前步 (messages覆盖除外,它会持久成为后续基础)。prepareCall返回对象替换 调用设置 ------ 必须先展开...settings。- 生成结构化输出也算一步 ,与工具同用时给
stopWhen留够步数。 - 生命周期回调里的异常被吞;遥测默认不记录 context 与内容,需显式开关。
experimental_*前缀的接口(sandbox、MCP events、batch、rerank、code mode、decide、realtime、transcribe/translate、generateVideo、toolApprovalSecret、transform、MCPAppRenderer)随时可能破坏性变更;Harnesses 整块处于实验期。
来源 :AI SDK v7 官方文档 Agents(11 篇)、AI SDK Core(32 篇)、AI SDK Harnesses(8 篇)三个板块的全部 51 个子主题页面 ,抓取于 ai-sdk.dev/docs(任意页面 URL 加
.md后缀可直接取纯 Markdown 版本;全站索引见 ai-sdk.dev/llms.txt)。精度说明 :第 0、1 章(Agents 11 篇)与第 3 章(Harnesses 8 篇)已按原文逐篇精读并校订 ;Core 板块 2.9--2.26 以各页官方小节标题与 API 标识清单为依据整理 ------ 命名与取值均出自原文,但未逐条复核每个可选参数的默认值。若某个 API 细节对你的实现关键,请按「本文小节 → 对应文档页面」回原文确认(各节标题即官方页面标题)。