尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

AI SDK Agent 记忆功能怎么实现:provider 工具、memory provider 与自定义工具怎么选

发布时间:2026/9/13 12:23:31

资讯中心
01
ARTICLE

AI SDK Agent 记忆功能怎么实现:provider 工具、memory provider 与自定义工具怎么选

AI SDK Agent 记忆功能怎么实现:provider 工具、memory provider 与自定义工具怎么选
AI SDK Agent 记忆功能怎么实现provider 工具、memory provider 与自定义工具怎么选【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai给 Agent 加上记忆就是让它在一次对话里存入信息、在之后的对话里再取回来。没有记忆时每次对话都从零开始有了记忆Agent 可以逐步积累上下文、回忆之前的交互并适应用户。AI SDK 官方文档 Memory 给出了三条实现路径provider-defined tools、memory providers、自定义工具。本文基于该文档及其引用的各 provider 文档、Build a Custom Memory Tool 配方梳理每条路径的实际写法和适用条件最后给出一份可对照的选择依据。三种方案的工作方式与代价对比官方文档的对比表如下这是选择方案的总依据方案实现工作量灵活性Provider 锁定Provider-Defined Tools低中是Memory Providers低低取决于所用 memory providerCustom Tool高高无三者的本质区别Provider-Defined Tools工具本身inputSchema和description由模型厂商定义模型已经针对这些工具做过训练你只提供execute函数把工具调用映射到自己的存储后端。文档指出这相比自定义工具可能带来更好的表现代价是与特定厂商绑定。Memory Providers外部记忆服务通过标准 AI SDK 接口接入记忆的存储、检索、注入全部在 provider 侧透明完成你不需要自己定义任何工具。代价是记忆行为由 provider 控制你对存了什么、怎么取回可见度更低并且依赖一个外部服务。Custom Tool自己定义工具接口、存储格式和检索逻辑。前期工作量最大但完全自主无 provider 锁定、无外部依赖。方案一Provider-Defined Tools以 Anthropic Memory Tool 为例Anthropic 的 Memory Tool 给 Claude 一个管理/memories目录的结构化接口Claude 在任务开始前读取自己的记忆工作时创建和更新文件并在后续对话中引用它们。前提是你已经在用 Anthropic 模型——文档明确说明该工具只在 Claude 上可用。工具接收结构化命令view、create、str_replace、insert、delete、rename每条命令带一个限定在/memories下的path。你的execute函数负责把这些命令映射到存储后端文件系统、数据库或其他持久层并把结果作为字符串返回import { anthropic } from ai-sdk/anthropic; import { ToolLoopAgent } from ai; const memory anthropic.tools.memory_20250818({ execute: async action { // action contains command, path, and other fields // depending on the command (view, create, str_replace, // insert, delete, rename). // Implement your storage backend here. // Return the result as a string. }, }); const agent new ToolLoopAgent({ model: anthropic/claude-haiku-4.5, tools: { memory }, }); const result await agent.generate({ prompt: Remember that my favorite editor is Neovim, });这段代码来自 Memory 文档。execute函数体是留给你实现的存储逻辑模型、包名和工具名按原文保留即可直接使用。如何验证记忆写入是否生效取决于你的execute实现。以文件系统为例发一条记住我的编辑器是 Neovim之类的 prompt 后检查存储后端中是否出现对应记忆文件如/memories下的文件及其内容在后续对话里再提问确认模型能通过view等命令读回该信息。文档中下次运行时该事实出现在 system prompt / 对话中这类行为描述需要你在自己的存储实现上实际跑一遍才能确认。适用判断文档给出的条件是想以最小实现工作量获得记忆且已在用 Anthropic 模型。如果你同时需要跨多家模型供应商这条路径直接出局。方案二Memory ProvidersLetta、Mem0、Supermemory、Hindsight这一类 provider 把外部记忆服务包装成标准接口。官方 Memory 文档列出了四个代表Letta、Mem0、Supermemory、Hindsight分别覆盖托管 Agent 运行时记忆、通用记忆层、语义搜索自动存取、可自托管的五工具记忆库。下面按最小接入 验证的粒度过一遍。Letta记忆由 Letta agent 运行时托管Letta 提供持久长期记忆。你在 Letta 平台cloud 或 self-hosted创建 Agent 并在那里配置其记忆AI SDK 的 provider 负责与它交互记忆管理core memory、archival memory、recall由 Letta 的 agent 运行时处理。安装pnpm add letta-ai/vercel-ai-sdk-provider在.env中配置 API key从 Letta dashboard 获取# .env LETTA_API_KEYyour-letta-api-keyyour-letta-api-key替换为你自己的 Letta API key。最简用法import { lettaCloud } from letta-ai/vercel-ai-sdk-provider; import { ToolLoopAgent } from ai; const agent new ToolLoopAgent({ model: lettaCloud(), providerOptions: { letta: { agent: { id: your-agent-id }, }, }, }); const result await agent.generate({ prompt: Remember that my favorite editor is Neovim, });your-agent-id替换为你在 Letta 平台创建的 Agent 的 ID。注意lettaCloud()只是 provider 实例模型配置LLM、temperature 等由你的 Letta Agent 管理见 Letta provider 文档。自托管用户导入lettaLocal代替lettaCloud或用createLetta({ baseUrl, token })创建自定义实例。如果需要在你的自定义工具之外显式使用 Letta 内置的记忆工具可以这样声明这些工具的执行由 Letta 完成import { lettaCloud } from letta-ai/vercel-ai-sdk-provider; import { ToolLoopAgent } from ai; const agent new ToolLoopAgent({ model: lettaCloud(), tools: { core_memory_append: lettaCloud.tool(core_memory_append), memory_insert: lettaCloud.tool(memory_insert), memory_replace: lettaCloud.tool(memory_replace), }, providerOptions: { letta: { agent: { id: your-agent-id }, }, }, }); const stream agent.stream({ prompt: What do you remember about me?, });如何验证先让 Agent 记住一条事实再问What do you remember about me?这类问题让 Letta 侧的回忆能力作答。此外 provider 继承了letta-ai/letta-client可以通过lettaCloud.client如lettaCloud.client.agents.list()直接调用 Letta API 核对 Agent 与记忆配置。Mem0加在任意受支持 LLM provider 之上的记忆层Mem0 自动从对话中提取记忆、存储并在后续 prompt 中检索相关记忆。安装pnpm add mem0/vercel-ai-provider初始化 provider 实例。provider指定底层 LLM文档支持openai、anthropic、google、groq、cohere五种配置值两个 key 建议用环境变量MEM0_API_KEY从 Mem0 dashboard 获取import { createMem0 } from mem0/vercel-ai-provider; import { ToolLoopAgent } from ai; const mem0 createMem0({ provider: openai, mem0ApiKey: process.env.MEM0_API_KEY, apiKey: process.env.OPENAI_API_KEY, }); const agent new ToolLoopAgent({ model: mem0(gpt-4.1, { user_id: user-123 }), }); const { text } await agent.generate({ prompt: Remember that my favorite editor is Neovim, });user_id用来标识记忆归属文档的最佳实践是用唯一的user_id保证记忆检索的一致性把它替换为你的用户标识。不经过模型、直接管理记忆的函数import { addMemories, retrieveMemories } from mem0/vercel-ai-provider; await addMemories(messages, { user_id: user-123 }); const context await retrieveMemories(prompt, { user_id: user-123 });Mem0 文档还给出了两个细节getMemories返回原始记忆对象数组retrieveMemories返回已注入检索记忆的 system prompt 字符串格式生成响应时可以解构出sources查看记忆来源const { text, sources } await generateText({ model: mem0(gpt-4.1), prompt: Suggest me a good car to buy!, }); console.log(sources);如何验证调用addMemories写入对话后用getMemories拿到数组确认记忆确实被存入用retrieveMemories确认返回的上下文中包含该事实生成回答时检查sources是否命中对应记忆。这些函数单独调用时MEM0_API_KEY必须通过环境变量或函数参数提供。Supermemory语义搜索驱动的自动存取Supermemory 通过语义搜索自动保存和检索记忆工具暴露addMemory与searchMemories两个操作可搭配任意 AI SDK provider 使用。安装pnpm add supermemory/toolsimport { generateText } from ai; import { createOpenAI } from ai-sdk/openai; import { supermemoryTools } from supermemory/tools/ai-sdk; const openai createOpenAI({ apiKey: YOUR_OPENAI_KEY, }); const { text } await generateText({ model: openai(gpt-5-mini), prompt: Remember that my name is Alice, tools: supermemoryTools(YOUR_SUPERMEMORY_KEY), }); console.log(text);代码来自 Supermemory 文档。YOUR_OPENAI_KEY、YOUR_SUPERMEMORY_KEY是占位符分别替换为你的 OpenAI API key 和 Supermemory API keySupermemory 提供免费的 API key。该文档还展示了另一种可选接法——Memory Router把 provider 的baseUrl换成 Supermemory 的代理地址并通过x-supermemory-api-key、x-sm-conversation-id头传递身份不写工具、让路由层处理记忆它和上面的工具方式是两条并列路径本文主线采用工具方式。如何验证文档示例指出模型会自动调用searchMemories({ informationToGet: ... })或addMemory({ memory: ... })。因此验证方式是发送记住我叫 Alice后再次询问我叫什么同时观察工具调用日志里是否出现了addMemory/searchMemories的调用。Hindsight五工具记忆库可 Docker 自托管Hindsight 通过retain、recall、reflect、getMentalModel、getDocument五个工具提供持久记忆可 Docker 自托管或用作云服务支持generateText、streamText和ToolLoopAgent。自托管说明副作用下面的docker run会启动一个容器占用本机8888API和9999UI两个端口并把持久卷挂载到$HOME/.hindsight-docker需要 Docker 环境和一个用于其内部 LLM 调用的OPENAI_API_KEYexport OPENAI_API_KEYyour-key docker run --rm -it -p 8888:8888 -p 9999:9999 \ -e HINDSIGHT_API_LLM_API_KEY$OPENAI_API_KEY \ -v $HOME/.hindsight-docker:/home/hindsight/.pg0 \ ghcr.io/vectorize-io/hindsight:latestyour-key替换为你自己的 OpenAI key。启动后 API 在http://localhost:8888UI 在http://localhost:9999。用云服务则从 Hindsight dashboard 拿到 API URL 写入HINDSIGHT_API_URL环境变量即可。安装并创建工具pnpm add vectorize-io/hindsight-ai-sdk vectorize-io/hindsight-clientimport { HindsightClient } from vectorize-io/hindsight-client; import { createHindsightTools } from vectorize-io/hindsight-ai-sdk; import { generateText, isStepCount } 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, stopWhen: isStepCount(5), system: You are a helpful assistant with long-term memory., prompt: Remember that I prefer dark mode and large fonts., });bankId标识记忆库通常是用户 ID。多用户应用里要在请求处理器内调用createHindsightTools让每个请求用上当前用户的bankId——HindsightClient在模块级创建一次共享工具按请求创建。基础设施类选项retain的async/tags/metadatarecall的budget/types/maxTokens等在创建工具时配置语义层面的决定记什么、搜什么留给模型详见 Hindsight 文档。如何验证自托管场景下先访问http://localhost:9999的 UI 确认服务已起来然后让 Agent 记住一条偏好再发一个需要回忆的问题如我偏好什么界面设置确认回答命中之前存入的事实。这一类的适用判断直接来自官方文档当你不想自建存储基础设施时memory providers 是合适的代价是 provider 控制记忆行为可见度更低且引入外部服务依赖。方案三自定义工具Custom Tool如果存储格式、接口和检索逻辑都要自己掌握就走自定义工具。官方配方 Build a Custom Memory Tool 给出了一条完整可跑的路径在一个共享的.memory目录上建一个记忆工具再用prepareCall把核心记忆注入每次模型调用。该配方定义了三种记忆类型术语取自 Letta 的定义Core Memory每轮都注入的信息直接写进 system prompt不需要工具调用Archival Memory模型按需通过记忆工具读写的笔记文件Recall Memory完整的逐轮对话历史持久化后可搜索。记忆目录布局.memory/ ├── core.md # Core memory, injected every turn ├── notes.md # Archival memory, timestamped notes └── conversations.jsonl # Recall memory, full turn history (JSONL)准备依赖两条路线共用的安装命令pnpm add ai just-bash zod如果只用结构化动作路线Route A可以跳过just-bash。存储底座启动时引导文件系统一次性初始化目录不存在就创建文件不存在就写入初始内容并把.memory加入.gitignore保持记忆本地私有import { access, appendFile, mkdir, readFile, writeFile, } from node:fs/promises; import { join, resolve } from node:path; const MEMORY_DIR .memory; const MEMORY_ROOT resolve(process.cwd(), MEMORY_DIR); const CORE_MEMORY_PATH join(MEMORY_ROOT, core.md); const NOTES_PATH join(MEMORY_ROOT, notes.md); const CONVERSATIONS_PATH join(MEMORY_ROOT, conversations.jsonl); const DEFAULT_CORE_MEMORY # Core Memory - Keep this short. - Put stable user facts here. ; const DEFAULT_NOTES # Notes Use this file for detailed memories and timestamped notes. ; async function ensureFile(path: string, content: string): Promisevoid { try { await access(path); } catch { await writeFile(path, content, utf8); } } async function ensureMemoryFilesystem(): Promisevoid { await mkdir(MEMORY_ROOT, { recursive: true }); await ensureFile(CORE_MEMORY_PATH, DEFAULT_CORE_MEMORY); await ensureFile(NOTES_PATH, DEFAULT_NOTES); await ensureFile(CONVERSATIONS_PATH, ); }配套的读取与追加辅助函数读 core 记忆用于注入、把对话追加为 JSONL方便grep和jq处理async function readCoreMemory(): Promisestring { try { return await readFile(CORE_MEMORY_PATH, utf8); } catch { return ; } } async function appendConversation(entry: { role: user | assistant; content: string; timestamp: string; }): Promisevoid { await appendFile(CONVERSATIONS_PATH, ${JSON.stringify(entry)}\n, utf8); }工具接口两条路线二选一Route A结构化动作。定义显式动作view、create、update、search所有请求都经过你自己的 handler每个操作都受你控制天然安全但前期实现更多、模型只能调用你建好的动作import { tool } from ai; import { z } from zod; const memoryInputSchema z.object({ command: z .enum([view, create, update, search]) .describe( Memory action: view to read, create to write new content, update to change existing content, search to find relevant lines., ), path: z .string() .optional() .describe( Memory path under /memories, such as /memories/core.md or /memories/notes.md. Required for view, create, and update., ), content: z .string() .optional() .describe(Text to write for create or update commands.), mode: z .enum([append, overwrite]) .optional() .describe( Write mode for update: append adds to existing content, overwrite replaces it. Defaults to overwrite., ), query: z .string() .optional() .describe( Search keywords for the search command. Prefer short focused terms., ), }); const memoryTool tool({ description: Use this tool to read and maintain long-term memory under /memories. Rules: - If the user prompt might depend on preferences, history, constraints, or goals, search first, then reply. - If the prompt is fully self-contained or general knowledge, reply directly. - Keep searches short and focused (1-4 words). - Store durable user facts in /memories/core.md and detailed notes in /memories/notes.md. - Keep memory operations invisible in user-facing replies., inputSchema: memoryInputSchema, execute: async input { try { const output await runMemoryCommand(input); return { output }; } catch (error) { return { output: Memory action failed: ${(error as Error).message} }; } }, });runMemoryCommand的实现要点把路径解析到 memory 根目录下只允许core.md、notes.md、conversations.jsonl这几个已知文件然后按动作执行——view读文件create/update按append或overwrite写入search按关键词逐行匹配并返回文件:行号:内容形式。完整实现见配方的 Appendix: Structured Actions Handler。Route BBash 支撑。给模型一个沙箱化的 bash 环境去组合cat、grep、sed、echo等命令灵活性更高但必须做命令校验防注入。配方用 just-bash一个 JavaScript 实现的 bash不启动真实 shell 进程执行命令配合 AST 层命令守卫import { tool } from ai; import { Bash, ReadWriteFs } from just-bash; import { z } from zod; const fs new ReadWriteFs({ root: process.cwd() }); const bash new Bash({ fs, cwd: / }); const memoryTool tool({ description: Run bash commands only for memory-related tasks. ..., inputSchema: z.object({ command: z.string().describe(The bash command to execute.), }), execute: async ({ command }) { const unapprovedCommand findUnapprovedCommand(command); if (unapprovedCommand) { return { stdout: , stderr: Blocked unapproved command: ${unapprovedCommand}\n, exitCode: 1, }; } const result await bash.exec(command); return { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode, }; }, });上面的description在配方中是一大段路径规则与示例命令限定只操作/.memory下的文件、用追加、perl -pi -e原地编辑等这里为紧凑做了省略完整工具描述与findUnapprovedCommand的 AST 守卫实现含cat、echo、grep、jq、ls、mkdir、perl、sed、tail的命令白名单见 Appendix: Command Guard。注意just-bash的解释器是 JS 实现但文件系统是真实的——命令真的读写磁盘文件这就是为什么命令守卫是这一路线的关键安全层。组装 Agent 并运行两条路线共用 Agent 接线方式prepareCall钩子在每次 LLM 调用前重新读取 core 记忆并注入 system promptimport { ToolLoopAgent } from ai; const today new Date().toISOString().slice(0, 10); const memoryAgent new ToolLoopAgent({ model: anthropic/claude-haiku-4.5, tools: { memory: memoryTool }, prepareCall: async settings { // user-defined function fetches the contents of /.memory/core.md on every turn const coreMemory await readCoreMemory(); return { ...settings, instructions: Todays date is ${today}. Core memory: ${coreMemory} You can save and recall important information using the memory tool., }; }, });因为prepareCall在工具循环的每次 generate 调用前都会执行system prompt 始终反映core.md的最新状态模型在对话中更新了 core 记忆下一轮循环立即可见。运行const prompt Remember that my favorite editor is Neovim; // Record the user message await appendConversation({ role: user, content: prompt, timestamp: new Date().toISOString(), }); // Run the agent (loops automatically on tool calls) const result await memoryAgent.generate({ prompt }); // Record the assistant response await appendConversation({ role: assistant, content: result.text, timestamp: new Date().toISOString(), }); console.log(result.text);如何验证配方给出了典型交互序列——用户说记住我最喜欢的编辑器是 Neovim模型调用memory工具如echo - Favorite editor: Neovim /.memory/core.md工具执行并返回结果模型确认后下次运行时prepareCall读到该事实并注入 system prompt。据此可以核对三点grep Neovim .memory/core.md或notes.md能查到刚写入的事实新开一轮对话提问如我偏好什么编辑器回答能命中该事实——这验证 core 记忆注入链路conversations.jsonl中按轮次累积了 user/assistant 记录grep -niE pricing|budget .memory/conversations.jsonl这类检索可验证 recall 记忆。怎么选按官方文档给出的条件对照把三份文档中的条件收敛成判断路径已在用 Anthropic 模型且想以最少代码获得记忆→ Provider-Defined Tools。实现只有一份execute函数行为表现有厂商训练背书但要接受仅 Claude 可用。不想自建任何存储接受外部服务依赖→ Memory Providers。再按约束细分想让记忆随 Agent 运行时一起托管选 Letta想要套在任何 LLM provider 上的记忆层、并能用addMemories/retrieveMemories显式管理选 Mem0想要自动的语义搜索存取选 Supermemory想自托管Docker并要五个显式记忆工具含reflect综合、getDocument取文档选 Hindsight。共同代价provider 控制记忆行为可见度低。要完全掌握存储格式、接口和检索逻辑且能承担前期实现成本→ Custom Tool。安全面注入防护、路径白名单由你自己负责Route A 动作少而可控Route B 灵活但必须上命令守卫。两条硬边界也要记住Provider-Defined Tools 与 Claude 绑定属于文档明确声明的锁定点MongoDB memorymongodb-developer/vercel-ai-memory提供 Session/Semantic/Procedural/Episodic/Scratchpad 五级记忆在官方文档中标注面向 AI SDK v6依赖ai: ^6.0.0等 v6 API如果你的项目不是 v6 就不能直接用选择前先核对版本。局限与后续三条路径共同的验证逻辑是一样的写入一条可识别的事实跨对话取回并检查存储侧文件、provider 控制台或显式检索函数确实留下了记录。Provider-Defined Tools 的execute与 Custom Tool 的存储层都是需要你自己实现的空缺本文保留的是文档给出的完整接口与可直接执行的部分Custom Tool 路线的完整参考实现文件系统引导、结构化动作 handler、AST 命令守卫集中在 07-custom-memory-tool.mdx 的附录中可整体照搬。各 memory provider 的完整配置项如 Letta 的maxSteps、timeoutInSecondsHindsight 的budget参数表见各自文档链接接入时再展开即可。【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。