TL;DR
- AI 聊多了会跑题,忘记最初的任务目标
- Deep Agents 用三种压缩技术解决记忆问题
- 文件系统是当前方案,轻量多模数据库可能是未来
什么是 Deep Agents?
Deep Agents SDK 是 LangChain 推出的开源 Agent Harness(智能体套件)框架,基于 LangChain 新版 API 构建,是一个开箱即用的深度智能体开发框架,帮助 AI Agent 处理长任务时更好地管理上下文。
Agent Harness 是什么?
简单理解:
| 概念 | 说明 |
|---|---|
| LLM | 基础模型,像大脑 |
| Agent | 能自主规划、调用工具的智能体(如基于 LangChain、LangGraph 构建) |
| Agent Harness | 套在 Agent 外面的装备袋,提供文件系统、上下文管理、监控等能力 |
Deep Agents 作为 Harness,让你的 Agent 具备:
- 文件系统抽象(读写、搜索、执行)
- 上下文压缩管理(本文重点)
- 子 Agent 派生能力
- 开发调试工具链
[!NOTE] Deep Agents = LangChain 构建的 Agent 套件 核心价值:让 Agent 能处理更长任务,并在上下文接近上限时不容易“失忆”
你的 AI 也这样吗?
你让 AI 帮你完成一个多步骤任务:先分析代码,然后找出 bug,最后修复并测试。
结果呢?它确实在分析代码,也在找 bug,但完全忘记了你的最终目标是要修复并测试。
或者更常见——任务做到一半,它开始做些你没要求的事情,遗漏了关键步骤。
这不是 AI 故意跟你作对。它只是忘了。
就像人的短期记忆有限一样,AI 的“工作记忆”也有容量上限。对话变长、上下文接近或超过上限时,系统往往会截断部分历史信息,任务目标逐渐模糊。
这个问题叫上下文腐烂(Context Rot),是长任务 AI Agent 需要面对的常见障碍。
今天我们来看看 LangChain 的 Deep Agents SDK 是怎么解决这个问题的。
先说人话:什么是上下文窗口?
每一轮 AI 对话——你的输入、AI 的输出、工具调用的结果——都会占用上下文空间。这个空间的容量叫上下文窗口(Context Window)。
不同模型的容量不同:
| 模型 | 上下文窗口 | 备注 |
|---|---|---|
| Claude 4.5 Sonnet | 200K tokens | 部分托管平台可能更高 |
| Gemini 2.5 Pro | 1M tokens | 上限会随版本调整 |
| GPT-5.2 | 400K tokens | 以官方文档为准 |
[!NOTE] 上下文窗口上限会随模型版本、接入渠道与产品策略变化;上表用于理解量级,具体以官方文档为准。
但不管多大,总是有限的。
超过容量会发生什么?一般有两种情况:
- 硬性上限:请求直接失败(例如 API 返回“上下文长度超限”),模型无法运行。
- 被迫截断:为了让请求能跑起来,系统/框架会截断最早的消息或部分内容;结果是关键目标、约束、历史细节被“挤出”当前输入,智能体表现得像“失忆”。
即使还没超限,接近上限也常见两类“软性退化”:
- 注意力稀释:信息太多,模型更难把权重放在最关键的目标/约束上
- 目标漂移:摘要或多轮交互后,容易偏离最初任务、漏步骤、误判完成
Deep Agents 的解决方案:三层压缩术
LangChain 的 Deep Agents SDK 采用了分层压缩策略,按不同触发频率执行三种压缩技术:
- 大型工具结果卸载:实时触发
- 大型工具输入卸载:例如达到 85% 上下文使用率时触发
- 摘要压缩:前两者不足以释放空间时触发
[!NOTE] 这些阈值可根据模型和任务特点灵活配置
实现机制:Middleware 拦截
这三种压缩技术都利用了 LangChain V1 的 Middleware 机制,在模型调用前进行拦截和处理:
用户请求
↓
Middleware 拦截 ← 关键拦截点
↓
检查上下文占用
↓
触发相应压缩策略
↓
压缩后传递给模型
为什么选择 Middleware 拦截?
- 时机准确:在模型调用前最后一次检查,能获取最新的上下文状态
- 无侵入性:不需要修改 Agent 核心逻辑,通过中间件层统一处理
- 可组合性:多个 Middleware 可以链式组合,各自负责不同职责
下面展示了压缩前后的变化。注意:数字仅为演示目的,实际 token 消耗取决于代码复杂度和模型计算方式。
技巧一:大型工具结果卸载
触发条件
例如工具返回内容超过 20K tokens 时触发(阈值可配置)。
压缩前后对比
压缩前:完整的文件内容保留在上下文中
Messages:
├── User: 请分析 src/auth/login.js 文件
├── Assistant: (调用 read_file)
├── Tool: [完整的 login.js 内容]
│ import { useState } from 'react';
│ import { useNavigate } from 'react-router-dom';
│ // ... 共 5,000+ 行代码(含大量配置/生成代码)
│ export default LoginForm;
├── User: 这个文件里有没有安全问题?
├── Assistant: (正在分析...)
│
Token 使用: 约 40K / 200K(示意)
压缩后:内容被写入文件系统,上下文中只保留引用
Messages:
├── User: 请分析 src/auth/login.js 文件
├── Assistant: (调用 read_file)
├── Tool: [内容已卸载到 /workspace/.cache/tool_results/login_abc123.txt]
│ 预览前 10 行:
│ import { useState } from 'react';
│ import { useNavigate } from 'react-router-dom';
│ ...
│ (共 5,080 行,可通过 read_file 查看完整内容)
├── User: 这个文件里有没有安全问题?
├── Assistant: (调用 read_file 重新读取后分析)
│
Token 使用: 约 3K / 200K(示意)
[!NOTE] 实际节省的 token 数量取决于代码内容和模型的 tokenization 方式。JavaScript 代码的 token 数通常远少于字符数,但当文件达到数千行(尤其包含生成/配置代码)时,很容易超过 20K tokens,例如 5,000 行可能在 30-50K tokens 区间。
关键点
- 原始内容完整保存在文件系统中
- AI 需要时可以重新读取
- 节省的空间取决于代码长度,通常可达 数 K 到数十 K tokens
[!TIP] 触发阈值和压缩策略都是可配置的。根据你的任务特点,可以调高或调低
技巧二:大型工具输入卸载
触发条件
例如上下文使用率达到 85% 时触发(阈值可配置)。
压缩前后对比
压缩前:write/edit 工具调用可能带上大段文件内容
Messages:
├── ... (前面已有对话)
├── Assistant: (调用 write_file 创建新文件)
├── Tool: {
│ file: src/components/Button.jsx
│ content: (完整代码)
│ }
├── Assistant: (调用 edit_file 修改文件)
├── Tool: {
│ file: src/components/Button.jsx
│ old_content: (完整旧内容)
│ new_content: (完整新内容)
│ }
│
Token 使用: 约 180K / 200K (90%,示意)
压缩后:旧的工具调用被截断,只保留文件路径引用
Messages:
├── ... (前面已有对话)
├── Assistant: (调用 write_file)
├── Tool: [已卸载] 文件已写入: src/components/Button.jsx
├── Assistant: (调用 edit_file)
├── Tool: [已卸载] 文件已修改: src/components/Button.jsx
│
Token 使用: 约 90K / 200K (45%,示意)
关键点
- 文件已经持久化到磁盘,保留完整内容是冗余的
- 卸载后节省的空间取决于被截断的工具调用数量
- 累积可节省 数十 K 到上百 K tokens
[!NOTE] 上面从 180K → 90K 的变化只是为了直观展示"截断旧工具调用"会显著释放上下文,并不表示两者存在固定的计算关系。实际释放量取决于:历史中 write/edit 调用的次数、每次调用携带的内容大小、以及框架对工具消息的序列化方式。
技巧三:摘要压缩
触发条件
前两种方法都无法释放足够空间时触发。
压缩前后对比
压缩前:完整的对话历史
Messages: 180K / 200K (接近上限,示意)
├── User: 帮我搭建一个 React 登录页面
├── Assistant: 好的,我来帮你...
├── User: 加上表单验证
├── Assistant: 我来添加验证逻辑...
├── User: 需要记住登录状态
├── Assistant: 使用 localStorage...
├── User: 还要支持忘记密码功能
├── Assistant: 我来设计...
├── User: 样式改成 Material Design 风格
├── Assistant: 正在调整样式...
├── ... (30+ 轮对话,包含所有历史细节)
└── Assistant: 请确认是否符合要求
压缩后:结构化摘要 + 完整对话归档
Messages: 8K / 200K(示意)
├── Summary:
│ 会话目标: 搭建 React 登录页面(表单验证 + 状态存储 + 忘记密码 + Material Design)
│ 已创建文件:
│ - src/pages/Login.jsx
│ - src/components/LoginForm.jsx
│ - src/utils/auth.js
│ - src/components/ResetPassword.jsx
│ 下一步: 等待用户确认当前实现
│
├── File Reference: 完整对话已归档至 /workspace/.cache/session_history/session_abc123.json(示意)
└── Assistant: 请确认是否符合要求
完整对话历史被保存到文件系统:
/workspace/.cache/session_history/session_abc123.json
{
"original_messages": [
{"role": "user", "content": "帮我搭建一个 React 登录页面"},
{"role": "assistant", "content": "好的,我来帮你..."},
... (完整的 30+ 轮对话)
]
}
关键点
- 摘要建议包含:会话目标、已创建内容、下一步行动
- 完整对话可以归档到文件系统,后续可检索恢复(取决于你的实现)
- 可节省 数十到上百 K tokens
[!IMPORTANT] 摘要的关键是保留目标感
如果只压缩对话但不保留我在做什么,AI 就会迷失方向
真实效果:Token 断崖式下跌
Deep Agents 团队在 terminal-bench 上做了测试,为了产生更多压缩事件(便于观察),会把触发阈值例如设置为 25%(而非示意中的 85%)。
下面用一个不按比例的示意时间线表示 token 的“攀升 → 触发压缩 → 下降”的循环:
轮次: 0 ───────── 20 ───────── 40 ───────── 60
事件: 摘要压缩 工具输入卸载 再次摘要
tokens: 100K → 40K 90K → 50K 100K → 35K
[!NOTE] 上面的 token 数字同样是示意,重点是展示“压缩触发后,token 使用量会阶段性回落”的趋势。
- 第 20 轮:摘要压缩触发,约 100K → 40K tokens
- 第 40 轮:工具输入被卸载,约 90K → 50K tokens
- 第 60 轮:再次摘要,约 100K → 35K tokens
任务继续进行,智能体更不容易忘记目标。
上下文腐烂被明显缓解了。
但这还不够:文件系统的局限
Deep Agents 的方案很聪明,但文件系统不是终极答案。
随着任务变复杂,文件系统里的内容会越来越多:
- 成百上千个缓存文件
- 文件名相似,内容重复
- 想找某个具体信息,只能靠关键字搜索
真正的问题
| 问题 | 文件系统 | 数据库 |
|---|---|---|
| 检索效率 | 线性搜索,越慢 | 索引加速,快 |
| 关联查询 | 不支持 | SQL/JOIN |
| 语义搜索 | 不支持 | 向量检索 |
| 去重 | 需要手动 | 内置支持 |
下一代方案:轻量多模数据库
未来的 AI Agent 记忆系统,需要的不是更大的文件系统,而是更强的检索和关联能力。
什么样的数据库?
特征一:轻量级
- 例如 2 核 2G 的容器也能跑起来(取决于数据规模)
- 不需要专门运维团队
- 边缘设备也能部署
特征二:多模检索能力
| 检索类型 | 用途 | 典型场景 |
|---|---|---|
| 关系型 | 用户 A 修改了文件 B | 谁在什么时候改了什么 |
| 向量检索 | 找到跟登录功能相关的所有内容 | 语义关联查询 |
| 全文搜索 | 找到包含 JWT token 的讨论 | 精确关键词匹配 |
| GIS/时空 | 10 分钟前在哪个目录做了什么 | 时序追溯 |
特征三:AI 原生
- 支持自然语言查询(可由上层 AI 转译)
- 可自动/半自动建立内容关联
- 可进行去重与归档(规则 + 向量/全文检索)
为什么需要这些?
AI 不仅是存储信息,还在思考信息。
思考需要:关联、类比、推理。
这些能力,单靠文件系统做不到。
[!TIP] 但别急着上重型数据库,PostgreSQL + pgvector + 全文插件,可能已经够用了。
国内也有不错的选择:OceanBase seekdb 是开源的 AI 数据库,支持 MySQL 接口、向量检索、GIS 和全文检索,一套方案满足多种需求。
过度工程化是技术项目的常见陷阱。
给开发者的启示
如果你在构建 AI Agent
- 不要忽视上下文管理:再聪明的模型,记忆满了也会变傻
- 分层压缩是正道:先卸载大结果,再卸载大输入,最后摘要
- 保留目标感:无论如何压缩,都要让 AI 知道我在做什么
如果你在评估技术方案
- 文件系统是起点:简单可靠,适合早期阶段
- 提前考虑数据库:当任务复杂度上升,你会需要它
- 轻量是关键:能用 2C2G 搞定,就不要上集群
写在最后
AI 的记忆问题,本质上是信息管理与计算效率的平衡。
Deep Agents 的三层压缩术,用文件系统解决了大部分问题。这是务实的工程选择。
但未来的 Agent 记忆系统,需要更强的智能检索和关联能力。
轻量多模数据库,可能是下一个方向。
AI 要变得真正聪明,首先得有个好记性。
关注我们
欢迎同时关注小红书账号 沧海九粟 的 漫说智能体 系列,我会通过一组图片来介绍智能体的前沿资讯和技术要点。