
Hindsight × Vercel AI SDK用五个 Memory Tools 为 TypeScript Agent 注入跨会话持久记忆【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight本篇技术指南聚焦于 Hindsight 官方 Vercel AI SDK 集成包vectorize-io/hindsight-ai-sdk它通过createHindsightTools一次性注册retain、recall、reflect、getMentalModel、getDocument五个标准 AI SDK 工具为generateText、streamText与ToolLoopAgent补上无状态调用所缺失的长期记忆能力。读完本文你将掌握从零安装、最小集成、多用户隔离到生产级参数调优的完整实战路径并能从源码层面理解语义输入归 Agent、基础设施归应用这一设计的落地细节。TL;DRVercel AI SDK 本身没有持久记忆每一次generateText/streamText调用都是无状态的请求结束记忆即清零。vectorize-io/hindsight-ai-sdk以五个 AI SDK 工具的形式提供记忆能力retain、recall、reflect、getMentalModel、getDocument。一行代码完成接线createHindsightTools({ client, bankId })再把返回值传给tools字段即可。设计上做了清晰的职责切分Agent只控制语义输入记什么、搜什么应用锁定基础设施bank、成本预算、标签、异步模式。模型无法篡改 bank ID也不可能意外打爆 token 预算。兼容generateText、streamText与ToolLoopAgent且由于完全构建在工具层之上对 OpenAI、Anthropic、Google 等任何 AI SDK 支持的模型供应商都有效。后端可以选择 Hindsight Cloud 托管服务免运维也可以本地一条命令自托管uvx hindsight-embedlatest -p myapp daemon start。为什么 AI SDK 需要记忆AI SDK 提供的是一个干净的请求抽象消息进、文本或流出中间穿插工具调用。这种无状态设计恰恰是它能在 Serverless 与边缘运行时上轻松部署的原因但同时也意味着记忆问题被甩给了应用开发者。只要你的功能会对同一个用户运行不止一次缺口就会立刻暴露客服助手每个会话都重新询问账号细节编程助手每次重载都要重新学习项目约定个人助手忘记用户昨天告诉它的偏好。常规做法是把前几轮对话塞进 prompt但这最多只能撑到上下文窗口的上限而且会话一结束就归零。要么自己搭一套记忆层数据存储、Embedding、检索、去重要么就交付一个失忆的助手。Hindsight 正是这层记忆基础设施它以 AI SDK 本身就能驱动的工具形式暴露出来。记忆即工具语义输入与基础设施的硬边界AI SDK 本质上是工具调用框架。要给模型新能力最自然的方式就是交给它一个工具——模型自己决定何时使用记忆就像它决定何时调用天气 API 或执行计算一样。工具化记忆的陷阱在于如果把太多旋钮交给模型模型就会在每次调用时自行决定 bank ID、成本预算和打标签策略等于把基础设施决策交给了一个语言模型而它大概率会做错。Hindsight 的集成通过给两类输入划出硬边界来规避这个问题源码实现见 hindsight-integrations/ai-sdk/src/tools/index.ts语义输入归 Agent记什么content、搜什么query、反思什么问题query。这些是语言决策正是模型擅长的事。基础设施归应用写入哪个 bank、花多少延迟、打什么标签、是否 fire-and-forget。这些在创建工具时一次性固定模型永远看不到。落到实现上bankId在构造时被闭包捕获五个工具的execute内部一律使用createHindsightTools传入的bankId调用客户端方法模型的输入 schema 中根本不包含 bank 字段见 createHindsightTools 实现。结果是可以信赖的多用户隔离以及模型无法意外超支的 token 预算。对应的单元测试也明确验证了这一点——should always use the bankId from constructor options见 hindsight-integrations/ai-sdk/src/tools/index.test.ts。五个工具职责一览createHindsightTools会注册五个工具。中间一列是模型每次调用时填写的参数右边一列是你在构造时锁定的参数。工具Agent 提供应用控制retaincontent、documentId、timestamp、contextasync、tags、metadatarecallquery、queryTimestampbudget、types、maxTokens、includeEntities、includeChunksreflectquery、contextbudget、maxTokensgetMentalModelmentalModelId—getDocumentdocumentId—前三个构成核心循环retain把值得记住的内容存入长期记忆用户偏好、事实、经历、重要上下文。recall在记忆中检索与查询相关的事实返回结果列表。reflect不是简单返回匹配项而是基于记忆进行推理、综合出答案。后两个用于精确检索getMentalModel拉取经过整合、预先综合好的心智模型摘要比搜索原始记忆更便宜getDocument按 ID 取回存储的原始文档适合需要精确原文的场景。从源码类型定义可以进一步看清各工具的返回结构hindsight-integrations/ai-sdk/src/tools/index.tsretain返回{ success, bank_id, items_count, async }工具层精简为{ success, itemsCount }recall返回RecallResponse含resultsRecallResult[]、可选的entities实体及其观察、chunks原始分块reflect返回ReflectResponse含综合出的text与可选的based_on引用的 memories、mental_models、directives实现溯源getMentalModel返回心智模型的name、content与updated_atgetDocument返回文档的original_text、id与时间戳文档不存在时返回null。环境准备与安装安装需要三个包AI SDK 本体、Hindsight 集成包与 TypeScript 客户端npm install vectorize-io/hindsight-ai-sdk vectorize-io/hindsight-client ai从 hindsight-integrations/ai-sdk/package.json 可以看到版本约束vectorize-io/hindsight-ai-sdk的 peer 依赖为ai ^6.0.0与zod ^3.0.0 || ^4.0.0Node 要求22。后端推荐使用Hindsight Cloud托管服务注册账号、创建 API key然后把客户端指向它。自托管流程完全一致——本地一条命令启动 API把 baseUrl 换成本地地址即可uvx hindsight-embedlatest -p myapp daemon start # API available at http://localhost:8000对应的嵌入式实现位于仓库的 hindsight-embed 目录完整快速上手示例见 hindsight-integrations/ai-sdk/README.md。最小集成给一次生成加记忆整个集成就是三步创建客户端 → 用bankId创建工具 → 传给任意 AI SDK 调用。下面这段来自官方示例hindsight-docs/examples/integrations/ai-sdk.tsimport { HindsightClient } from vectorize-io/hindsight-client; import { createHindsightTools } from vectorize-io/hindsight-ai-sdk; import { generateText } from ai; import { openai } from ai-sdk/openai; const client new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL! }); const tools createHindsightTools({ client, bankId: user-123, }); const { text } await generateText({ model: openai(gpt-4o), tools, maxSteps: 5, system: You are a helpful assistant with long-term memory., prompt: Remember that I prefer dark mode and large fonts., });在稍后的另一次调用中即使是从一次全新的 Serverless 冷启动开始模型也会调用recall并取回偏好const { text } await generateText({ model: openai(gpt-4o), tools, maxSteps: 5, system: You are a helpful assistant with long-term memory., prompt: What are my display preferences?, }); // - answers with dark mode and large fonts请求处理器里除了加一个tools什么都没改。这里的关键是maxSteps或stopWhen条件它允许模型在一次回合内先调用记忆工具、再基于结果作答。官方集成文档对每个入口的用法有完整示例hindsight-docs/docs-integrations/ai-sdk.mdx。流式与 Agent 循环同一套工具直接复用因为记忆只是工具它可以原样注入 AI SDK 的每一个入口。用streamText时工具行为完全一致模型在生成中途调用记忆时 token 照常流式输出import { streamText } from ai; const result streamText({ model: openai(gpt-4o), tools, maxSteps: 5, system: You are a helpful assistant with long-term memory., prompt: What are my display preferences?, }); for await (const chunk of result.textStream) { process.stdout.write(chunk); }用ToolLoopAgent时把同一套工具交给自驱型 Agent 循环import { ToolLoopAgent, stepCountIs } from ai; const agent new ToolLoopAgent({ model: openai(gpt-4o), tools: createHindsightTools({ client, bankId: user-123 }), stopWhen: stepCountIs(10), system: You are a helpful assistant with long-term memory., }); const result await agent.generate({ prompt: Remember that my favorite editor is Neovim, });多用户隔离Next.js 路由中的逐请求 bankIdbankId是记忆的路由键Hindsight 的 bank 本质就是一个命名空间最常见的模式是每用户一个 bank。由于 bank 在构造时固定服务端正确的做法是在请求处理器内部创建工具闭包捕获当前用户的 ID// app/api/chat/route.ts import { streamText } from ai; import { openai } from ai-sdk/openai; import { HindsightClient } from vectorize-io/hindsight-client; import { createHindsightTools } from vectorize-io/hindsight-ai-sdk; const hindsightClient new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL!, }); export async function POST(req: Request) { const { messages, userId } await req.json(); // Tools are created per request, closing over the current users bankId const tools createHindsightTools({ client: hindsightClient, bankId: userId, }); return streamText({ model: openai(gpt-4o), tools, maxSteps: 5, system: You are a helpful assistant with long-term memory., messages, }).toDataStreamResponse(); }每个请求拿到的工具都只作用于当前用户的那份记忆。这里没有共享的可变状态一个用户的请求也不可能读写另一个用户的 bank——因为模型根本不掌握自己在跟哪个 bank 对话这一信息。不触碰 Agent 循环的调优构造参数详解所有基础设施关切都是createHindsightTools上的选项按所属工具分组设置一次、模型永不可见const tools createHindsightTools({ client, bankId: userId, retain: { async: true, // fire-and-forget (default: false) tags: [env:prod, app:support], // attached to every retained memory metadata: { version: 2.0 }, }, recall: { budget: high, // low | mid | high (default: mid) types: [experience, world], // restrict fact types (default: all) maxTokens: 2048, // cap the token budget includeEntities: true, // include entity observations }, reflect: { budget: mid, }, });官方文档对每个选项的默认值有完整表格hindsight-docs/docs-integrations/ai-sdk.mdx源码中的HindsightToolsOptions类型也与之一一对应hindsight-integrations/ai-sdk/src/tools/index.ts组选项类型默认值说明retainasyncbooleanfalseFire-and-forget不等摄入完成retaintagsstring[]—附加到每条被保留记忆上的标签retainmetadataRecordstring, string—附加到每条被保留记忆上的元数据retaindescriptionstring内置覆盖展示给模型的工具描述recallbudgetlow \| mid \| highmid控制检索深度与延迟recalltypes(world \| experience \| observation)[]全部把结果限制为指定事实类型recallmaxTokensnumberAPI 默认限制返回的总 token 数recallincludeEntitiesbooleanfalse结果中是否包含实体观察recallincludeChunksbooleanfalse结果中是否包含原始源分块recalldescriptionstring内置覆盖工具描述reflectbudgetlow \| mid \| highmid控制综合深度与延迟reflectmaxTokensnumberAPI 默认响应的最大 token 数reflectdescriptionstring内置覆盖工具描述生产环境最值得关注的几个选项retain.async: true写入变为 fire-and-forgetretain调用不再给用户这一轮增加摄入延迟。recall.budget在延迟与深度之间做权衡——low适合快速查询high适合完整性优先于速度的场景。recall.types当只需要某一种事实时把召回范围限制为world、experience或observation之一。retain.tags给来自该接入面的每条记忆盖上标签方便在多个应用共享一个 bank 时维持组织性。另外你还可以覆盖任意工具的description来引导模型何时调用它而无需改动 system prompt。源码中每个工具的描述都是可选的构造参数未提供时使用内置文案hindsight-integrations/ai-sdk/src/tools/index.ts单元测试对默认描述与自定义描述两种分支均有覆盖hindsight-integrations/ai-sdk/src/tools/index.test.ts。这个设计为什么撑得住生产AI SDK 默认接入 Hindsight跨调用记忆无有按 bank 持久化接入方式n/acreateHindsightTools传给tools实现机制n/a五个 AI SDK 工具模型供应商任意任意工具与供应商无关谁控制 bank IDn/a应用构造时固定谁控制成本/延迟n/a应用而非模型多用户隔离n/a逐请求bankId语义输入与基础设施输入的切分是哪怕你打算自建记忆工具也值得照抄的部分让模型决定记什么、查什么但绝不让它决定记忆存在哪、要花多少钱。这正是能跑在生产环境的记忆层与演示到模型选错 bank 就翻车之间的区别。源码层面的实现印证这套设计的每个关键承诺都能在仓库源码中找到对应实现工具注册与 Zod 输入约束createHindsightTools用五个 Zod schema 分别约束各工具的参数——retain只暴露content/documentId/timestamp/contextrecall只暴露query/queryTimestampreflect只暴露query/contexthindsight-integrations/ai-sdk/src/tools/index.ts。基础设施参数tags、metadata、budget、types等根本不在 schema 里。预算枚举BudgetSchema z.enum([low, mid, high])、FactTypeSchema z.enum([world, experience, observation])在 index.ts 顶部定义。默认值语义recall与reflect的budget默认mid、includeEntities与includeChunks默认false、retain.async默认false均有对应的单元测试断言hindsight-integrations/ai-sdk/src/tools/index.test.ts。bankId 强制无论模型传什么所有客户端调用都使用构造时的bankIdhindsight-integrations/ai-sdk/src/tools/index.test.ts。客户端接口工具层只依赖一个定义了retain/recall/reflect/getMentalModel/getDocument五个方法的轻量客户端接口hindsight-integrations/ai-sdk/src/tools/index.ts官方 TypeScript 客户端源码位于 hindsight-clients/typescript也可按需自实现 HTTP 客户端。下一步完整集成文档与选项表hindsight-docs/docs-integrations/ai-sdk.mdx可运行示例generateText / streamText / ToolLoopAgent / Next.js 路由 / 构造参数hindsight-docs/examples/integrations/ai-sdk.ts集成包源码与类型定义hindsight-integrations/ai-sdk/src/tools/index.ts单元测试默认值、描述覆盖、参数透传、bankId 强制hindsight-integrations/ai-sdk/src/tools/index.test.ts快速上手 READMEhindsight-integrations/ai-sdk/README.md【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考