ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

我们如何构建 Agent Builder 的记忆系统:用 TaoToken 统一 Key 打通 LangSmith 与 Deep Agents

我们如何构建 Agent Builder 的记忆系统:用 TaoToken 统一 Key 打通 LangSmith 与 Deep Agents 1. 从一次“失忆”事故说起Agent Builder 记忆系统到底解决什么问题你可能遇到过这种场景花了一下午调教好的 Agent第二天打开它像换了个人。昨天刚说过的“摘要用项目符号、行动项单独列在末尾”今天又变回一大段文字。这不是模型变笨了而是它根本没有把上一次的经验留下来。LangSmith Agent Builder 的记忆系统本质上就是给 Agent 装一个“可读写的笔记本”。它把记忆表示成一组文件让模型用自己最擅长的方式——读写文件系统——来管理记忆。这个选择很关键模型不需要学习一套专用工具只要给它文件访问权限它就能自己读、自己改。这套记忆系统适合谁三类人最值得关注。第一类是正在做垂直任务 Agent 的开发者比如邮件助手、文档助手、招聘筛选助手这些任务会反复执行经验能跨会话复用。第二类是想把 Agent 从“一次性对话”升级成“长期协作伙伴”的团队。第三类是已经在用 Deep Agents 或类似 harness、想搞清楚上下文工程怎么落地的人。它和通用 Agent 的记忆有什么不同ChatGPT、Claude 这类通用助手你这次让它写代码、下次让它查资料两次会话可能毫无关系学到的经验迁移率很低。但 Agent Builder 面向的是特定任务Agent 一遍又一遍做同一件事一次会话里的教训有很高概率在下次用得上。没有记忆用户就得反复重复自己体验会非常糟。LangSmith 团队借用了 COALA 论文对记忆的分类程序性记忆规则集决定 Agent 行为、语义性记忆关于世界的事实、情景性记忆过去行为的序列。在 Agent Builder 里程序性记忆对应AGENTS.md和tools.json语义性记忆对应 agent skills 和其他知识文件情景性记忆暂时没做他们认为对这类任务型 Agent 来说前两类更重要。真正让这套系统跑起来的是底层 Deep Agents harness 对上下文工程的抽象——摘要、工具调用卸载、规划这些复杂逻辑都被封装了你只需要用相对简单的配置去引导 Agent。而要把这套链路真正跑通、并且能追踪每一次记忆读写你需要一个稳定的模型调用通道。这就是 TaoToken 出场的地方统一 Key 和 API 通道把 LangSmith 的追踪和 Deep Agents 的模型调用串成一条线。下面我会从环境准备开始一步步给出可复制的配置片段再走一遍记忆召回链路的验证最后把常见的报错对照着排一遍。目标很明确让你能复现从写入到检索的完整闭环。2. TaoToken 前置准备统一 Key 与 Base URL 的接入配置在动手配记忆系统之前先把模型调用通道理顺。LangSmith 负责追踪记忆读写链路Deep Agents 负责组织AGENTS.md上下文但这两者最终都要调用模型。如果每个组件各配一套 Key、各写一个 Base URL排查问题时你会分不清是记忆逻辑错了还是调用通道断了。用 TaoToken 统一 Key 和 API 通道能把变量收敛到一个地方。先明确三个核心件后面所有配置都围绕它们展开配置项值说明Base URLhttps://taotoken.net/api所有模型调用的统一入口不加 UTMAPI Key在控制台创建形如sk-...只存环境变量别写进代码Model ID按需选择例如claude-sonnet-4-5、gpt-4o等以控制台可用列表为准第一步去控制台创建 Key。打开https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keys登录后新建一个 Key复制出来。这个 Key 就是你后面所有组件的通行证。第二步把它写进环境变量。我习惯用.env文件管理避免污染全局 shell。在项目根目录建一个.env# .env TAOTOKEN_API_KEYsk-你的真实key TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_MODELclaude-sonnet-4-5 # LangSmith 追踪 LANGCHAIN_TRACING_V2true LANGCHAIN_API_KEYlsv2_你的langsmith_key LANGCHAIN_PROJECTagent-builder-memory # Deep Agents 相关 AGENTS_MD_PATH./agents/AGENTS.md注意TAOTOKEN_BASE_URL结尾不要带斜杠很多 SDK 拼接路径时会因此产生双斜杠导致 404。这是我自己踩过的坑排查了半天才发现是 URL 末尾多了个/。第三步如果你用的是 Claude Code 这类工具配置方式略有不同。Claude Code 读取的是settings.json路径通常在~/.claude/settings.json。把模型通道指向 TaoToken{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的真实key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }这里有个容易混淆的点Claude Code 用的是ANTHROPIC_*前缀的环境变量而通用 SDK 用的是OPENAI_*或自定义前缀。别把两套混用否则会出现“Key 明明对但一直 401”的情况。第四步如果你用 Cline 或带 MCP 的编辑器配置里同样要写全三件套。以 Cline 的 MCP 配置为例在cline_mcp_settings.json里{ mcpServers: { taotoken-gateway: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-你的真实key, TAOTOKEN_MODEL: claude-sonnet-4-5 } } } }Base URL、Key、Model ID 三件套一个都不能少。少 Base URL 会走默认官方地址少 Model ID 会报模型不存在少 Key 直接 401。第五步验证通道是否通。写一个最小脚本import os from openai import OpenAI client OpenAI( base_urlos.environ[TAOTOKEN_BASE_URL], api_keyos.environ[TAOTOKEN_API_KEY], ) resp client.chat.completions.create( modelos.environ[TAOTOKEN_MODEL], messages[{role: user, content: 只回复两个字通了}], ) print(resp.choices[0].message.content)跑通会打印“通了”。如果这一步就失败先别往下走记忆系统把通道问题解决掉。通道是地基地基不稳后面 LangSmith 追踪出来的链路全是断的。关于接入文档完整的环境变量说明和 SDK 用法在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc遇到参数不确定时对着查。3. 可复制配置用 AGENTS.md 与 Deep Agents 组织记忆文件通道通了接下来搭记忆系统的骨架。核心思路是把记忆表示成文件用AGENTS.md定义核心指令用 skills 提供任务级专用指令用tools.json定义 MCP 工具访问。这些文件在物理上存在 Postgres 里但以文件系统的形状暴露给 Agent——DeepAgents 原生支持这种“虚拟文件系统”而且完全可插拔换成 S3、MySQL 都行。先看目录结构。一个典型的 Agent 记忆文件夹长这样agents/ linkedin_recruiter/ AGENTS.md tools.json subagents/ linkedin_search_worker.md skills/ candidate_screening.md knowledge/ jd_backend.md jd_frontend.mdAGENTS.md是程序性记忆的核心定义 Agent 的行为规则。一个初始版本可以很简单# 会议总结助手 ## 任务 总结会议记录输出结构化摘要。 ## 格式 - 使用项目符号而不是段落 - 在末尾单独提取行动项目 - 对决策使用过去时 - 在顶部包含时间戳这个文件不是一次性写死的而是随着使用被 Agent 自己编辑。第 1 周你纠正它“用项目符号”它就把这条写进AGENTS.md第 2 周你要求“末尾单独提取行动项目”它再追加一条。三个月后这个文件会积累出格式偏好、领域术语、参会人员角色、会议类型处理等大量细节而用户从未手动改过它。tools.json定义 MCP 工具访问。LangSmith 没用标准的mcp.json而是自定义了tools.json原因是想允许用户只给 Agent 一个 MCP 服务器里工具的子集避免上下文溢出{ mcpServers: { linkedin: { command: npx, args: [-y, linkedin/mcp-server], allowedTools: [search_people, get_profile] } } }注意allowedTools这个字段它就是这个自定义格式的价值所在。标准mcp.json会把整个服务器的工具都暴露出来上下文很快被撑爆。subagents/目录放子 Agent 定义。LangSmith 用了类似 Claude Code 的格式当时没有子 Agent 标准# linkedin_search_worker ## 角色 在主 Agent 校准搜索条件后启动本 Agent 寻找约 50 名候选人。 ## 输入 - 搜索关键词 - 地点限制 - 经验年限 ## 输出 候选人列表每人包含姓名、当前职位、匹配理由。skills/目录放任务级专用指令对应语义性记忆。每个 skill 文件需要遵守特定格式通常带前言frontmatter--- name: candidate_screening description: 根据 JD 筛选候选人 --- ## 筛选标准 1. 技能匹配度优先于年限 2. 有相关行业经验加分 3. 跳槽频率过高需标注knowledge/目录放任意知识文件Agent 运行时可以参考也会在工作时“在热路径中”编辑它们。比如几个 JD 文件随着搜索推进被 Agent 更新维护。把这些文件接进 Deep Agents配置大致如下from deepagents import create_deep_agent agent create_deep_agent( agents_md_path./agents/linkedin_recruiter/AGENTS.md, tools_json_path./agents/linkedin_recruiter/tools.json, subagents_dir./agents/linkedin_recruiter/subagents, skills_dir./agents/linkedin_recruiter/skills, knowledge_dir./agents/linkedin_recruiter/knowledge, modelclaude-sonnet-4-5, base_urlhttps://taotoken.net/api, api_keyos.environ[TAOTOKEN_API_KEY], )这里base_url和api_key直接复用前面配好的 TaoToken 通道模型调用和记忆读写走同一条链路LangSmith 追踪时才能把两者关联起来。有一个关键设计要强调所有记忆编辑都是人在回路Human-in-the-loop的更新前需要人工批准。这主要是为了减少提示注入的攻击面。LangSmith 也提供了关闭这个功能的选项他们内部叫“yolo 模式”但在生产环境我不建议关。记忆文件是 Agent 能自己写的如果被恶意输入诱导写入危险指令下次会话就会执行这个风险不值得省那点确认成本。文件类型需要显式验证。tools.json必须是合法的 MCP 服务器配置skills 必须有正确的前言。LangSmith 发现 Agent 有时会忘记这些约束生成无效文件所以他们加了一步显式验证验证失败就把错误抛回给 LLM而不是提交文件。这个模式值得抄你可以在自己的 harness 里加一个 schema 校验层。4. 验证记忆召回链路从写入到检索的完整闭环配置搭好了现在走一遍完整闭环确认记忆真的能写入、能召回。这一步是整个系统能不能用的分水岭——很多人的 Agent 看起来有记忆实际上只是把历史对话塞进上下文根本没做持久化和检索。先准备一个最小可复现的场景。用会议总结助手初始AGENTS.md只有一行总结会议记录。第一次运行给一段会议记录观察 Agent 输出。它大概率会生成段落式摘要。这时你纠正它“使用项目符号而不是段落。”关键来了Agent 应该把这条偏好写进AGENTS.md而不是只记在当前会话里。验证写入是否发生。检查AGENTS.md内容应该变成# 格式偏好 用户更喜欢项目符号而不是段落来写摘要。如果文件没变说明记忆写入链路断了。常见原因是 Agent 没有文件系统写权限或者人在回路审批被跳过但没落盘。回到 Deep Agents 配置检查knowledge_dir和AGENTS.md的路径是否正确挂载。第二次运行换一段完全不同的会议记录不提任何格式要求。观察 Agent 是否自动使用项目符号。如果用了说明召回成功——它读取了AGENTS.md把上次的偏好应用到了新会话。再叠加一层。这次要求“在末尾单独提取行动项目。”AGENTS.md应该追加# 格式偏好 用户更喜欢项目符号而不是段落来写摘要。 在末尾单独提取行动项目。第三次运行两种模式都应该自动应用。到这里从写入到检索的闭环就通了。现在打开 LangSmith看追踪链路。在LANGCHAIN_PROJECTagent-builder-memory这个项目下你应该能看到每次运行的 trace。重点看两个 span一个是读取AGENTS.md的步骤一个是模型调用。读取步骤的输入输出能让你确认 Agent 到底读到了什么内容模型调用的 prompt 里应该包含AGENTS.md的内容。如果 trace 里看不到文件读取说明记忆没有真正进入上下文只是被写进了存储但没被召回。一个更严格的验证方法手动改AGENTS.md加一条新规则比如“短会议少于 10 分钟只列出要点”然后不重启 Agent直接发一段短会议记录。如果 Agent 应用了新规则说明它每次运行都实时读取记忆文件而不是缓存在内存里。这个特性对多会话场景很重要。验证召回质量时注意一个陷阱Agent 可能“记住”了但没“泛化”。LangSmith 团队发现他们的邮件助手曾经开始列出所有应该忽略的冷接触供应商而不是更新自己“忽略所有冷接触”。这是典型的记住了具体案例但没抽象出规则。解决办法是显式提示 Agent 压缩记忆把具体案例归纳成通用规则。你可以在验证时故意制造这种情况看 Agent 会不会掉进去再决定要不要加压缩步骤。如果你想在验证阶段直接和模型对话、快速试 prompt可以用模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chat。把AGENTS.md的内容贴进去手动模拟召回能更快定位是 prompt 问题还是链路问题。验证通过的标准很简单新会话不提要求Agent 自动应用旧偏好LangSmith trace 里能看到记忆文件被读取并进入 prompt手动改记忆文件后不重启也能生效。三条都满足闭环就成了。5. 常见报错排查401、local proxy failed 与 reading choices 对照链路跑起来之前报错是常态。这一节把最常见的几类错误对照着排一遍每个都给出真实报错文本和定位思路。401 Unauthorized。报错通常长这样openai.AuthenticationError: Error code: 401 - {error: {message: Invalid API key, type: invalid_request_error}}先查 Key 有没有正确加载。最常见的原因是.env没被读取或者环境变量名拼错。用echo $TAOTOKEN_API_KEY确认。如果 Key 是对的检查 Base URL 是不是https://taotoken.net/api末尾别带斜杠。还有一种情况Claude Code 用了ANTHROPIC_API_KEY但你在.env里只写了TAOTOKEN_API_KEY两套变量没对上。Claude Code 场景下要确保settings.json里的env块写的是ANTHROPIC_API_KEY。local proxy failed。报错类似Error: local proxy failed to connect: dial tcp 127.0.0.1:7890: connect: connection refused这个错误说明某个组件在尝试走本地代理端口但那个端口没有服务在监听。检查你的 shell 里有没有残留的HTTP_PROXY、HTTPS_PROXY、ALL_PROXY环境变量。用env | grep -i proxy看一眼。如果有unset掉再重试。很多 SDK 会默认读取这些变量即使你没主动配。reading choices。报错长这样TypeError: Cannot read properties of undefined (reading choices)这通常意味着 API 返回的结构和 SDK 预期的不一致。可能原因有三个一是 Base URL 配错了请求打到了非兼容端点返回了 HTML 或错误 JSON二是 Model ID 写错了服务端返回错误对象而不是正常的 completion 结构三是流式和非流式模式混用。先确认TAOTOKEN_BASE_URL是https://taotoken.net/api再确认 Model ID 在控制台可用列表里。打印完整响应体print(resp)能看到真实返回比猜快得多。OAuth 相关报错。如果你用的是 Codex 或带 OAuth 的工具可能遇到Error: OAuth token expired or invalid这类工具通常有自己的认证流程和 API Key 是两套。检查~/.codex/auth.json是否存在且格式正确{ base_url: https://taotoken.net/api, api_key: sk-你的真实key, model: claude-sonnet-4-5 }Base URL、Key、Model ID 三件套写全。如果工具同时支持 OAuth 和 API Key优先用 API Key链路更短、排查更简单。记忆文件写入失败。报错可能是PermissionError: [Errno 13] Permission denied: ./agents/AGENTS.md检查文件路径是否存在、进程是否有写权限。如果用的是虚拟文件系统Postgres 存储检查数据库连接和表结构。DeepAgents 的虚拟文件系统是可插拔的存储层配置错了也会报类似错误。LangSmith trace 里看不到记忆读取。这不是报错但比报错更隐蔽。表现是运行正常但 trace 里只有模型调用没有文件读取 span。原因通常是记忆文件路径没挂载对或者 Agent 根本没触发读取逻辑。检查agents_md_path等配置是否指向真实存在的文件再确认 Deep Agents 版本支持你用的文件约定。排查顺序建议固定下来先验通道最小脚本调通再验配置三件套写全再验文件路径和权限最后验追踪LangSmith 能看到完整链路。按这个顺序走大部分问题能在前三步定位。接入相关的完整文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc报错信息拿去搜通常能找到对应说明。6. 长期编码与 Agent 场景把记忆系统用起来记忆系统跑通之后真正的价值在于长期使用。LangSmith 团队的经验里有一条特别值得记Agent 擅长向文件添加内容但不擅长压缩。他们的邮件助手曾经开始列出所有应该忽略的冷接触供应商而不是更新自己“忽略所有冷接触”。这是典型的记住了具体案例但没泛化。解决办法有两个。一是显式提示 Agent 压缩记忆比如在会话结束时说“反思这次对话把学到的通用规则更新到记忆里具体案例归纳成规则”。二是加一个后台记忆进程用 cron 每天跑一次反思所有对话并更新记忆。LangSmith 计划做这个你如果自建系统可以提前实现。另一个实用技巧是/remember命令。LangSmith 想暴露一个显式的/remember让用户主动提示 Agent 反思对话并更新记忆。在自建系统里你可以用一个简单的触发词实现类似效果比如用户输入“记住这次的经验”时强制走一遍记忆写入流程。对于长期编码和 Agent 场景记忆系统的可移植性很重要。因为记忆是 markdown 和 json 文件你可以把在 Agent Builder 里构建的 Agent 移植到 Deep Agents CLI甚至其他 harness只要文件约定一致。LangSmith 特意用了尽可能多的标准约定就是为了这个。你在设计自己的记忆系统时也尽量用AGENTS.md、skills 这类通用格式别自创一套 DSL——DSL 不能很好地随复杂度扩展这是无代码构建器的通病。如果你要跑长期的编码 Agent建议用 Coding Plan 这类按周期计费的方式比按 token 计费更可控https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding_plan。记忆系统会让 Agent 的上下文越来越长调用量会上去提前规划好计费方式能避免月底账单惊吓。最后说一个我自己的做法每次给 Agent 加新能力时先手动在AGENTS.md里写一条规则跑一次验证它能被召回再让 Agent 自己维护。这样能确保记忆链路始终是通的而不是等到积累了几十条规则后才发现某一条从来没生效过。记忆系统的可靠性靠的是一次次小验证堆出来的。
返回列表