主题
05. 后端类型详解:五种存储策略
选择最适合你场景的存储后端
引言
在上一篇文章中,我们了解了 DeepAgents 虚拟文件系统的设计理念。本文将深入探讨五种内置后端类型,帮助你根据场景选择最合适的存储策略。
后端类型速查表
| 后端类型 | 持久化 | 跨线程 | 代码执行 | 适用场景 |
|---|---|---|---|---|
| StateBackend | ❌ | ❌ | ❌ | 单次会话、临时任务 |
| FilesystemBackend | ✅ | - | ❌ | 本地开发、文件操作 |
| StoreBackend | ✅ | ✅ | ❌ | 长期记忆、知识库 |
| LocalShellBackend | ✅ | - | ✅ | 本地开发(需谨慎) |
| 沙盒后端 | ✅ | - | ✅ | 安全代码执行 |

1. StateBackend - 临时状态存储
概念
StateBackend 是 DeepAgents 的默认后端,将文件存储在 LangGraph 的状态中。
生活类比:就像会议白板上的笔记——会议结束后就擦掉了。
特点
✅ 优点:
- 无需额外配置,开箱即用
- 适合临时任务和草稿
- 同一线程内自动通过 checkpoint 持久化
❌ 限制:
- 线程结束后数据丢失
- 不同线程之间不共享
- 不适合长期存储
使用方式
typescript
import { createDeepAgent } from "deepagents";
import { StateBackend } from "deepagents/backends";
// 方式一:默认就是 StateBackend
const agent1 = createDeepAgent();
// 方式二:显式指定
const agent2 = createDeepAgent({
backend: (rt) => new StateBackend(rt)
});数据生命周期
线程 1 线程 2
┌─────────────────────┐ ┌─────────────────────┐
│ write_file("/a.md") │ │ read_file("/a.md") │
│ ✅ 成功 │ │ ❌ 找不到 │
└─────────────────────┘ └─────────────────────┘
│ │
▼ ▼
State 1 State 2
(独立的) (独立的)
适用场景
- 🎯 单次问答任务
- 🎯 临时计算和分析
- 🎯 原型开发和测试
- 🎯 上下文卸载(大内容临时存储)
2. FilesystemBackend - 本地磁盘
概念
FilesystemBackend 直接读写本地磁盘文件,让代理可以操作真实的文件系统。
生活类比:代理可以直接访问你电脑上的文件夹。
⚠️ 安全警告
┌────────────────────────────────────────────────────────────┐
│ ⚠️ 重要安全提示 │
│ │
│ FilesystemBackend 会赋予代理对本地文件的读写权限! │
│ │
│ 风险: │
│ • 代理可能读取敏感文件(密钥、凭据、.env) │
│ • 文件修改是永久且不可逆的 │
│ • 结合网络工具可能导致数据泄露 │
│ │
│ 建议: │
│ • 仅在开发环境使用 │
│ • 启用 virtual_mode: true │
│ • 配合人机协作审批敏感操作 │
└────────────────────────────────────────────────────────────┘使用方式
typescript
import { createDeepAgent } from "deepagents";
import { FilesystemBackend } from "deepagents/backends";
const agent = createDeepAgent({
backend: new FilesystemBackend({
rootDir: "/Users/me/projects/my-app",
virtualMode: true // 强烈建议开启!
})
});配置选项
| 选项 | 类型 | 说明 |
|---|---|---|
rootDir | string | 根目录(必须是绝对路径) |
virtualMode | boolean | 是否启用路径限制(默认 false) |
virtualMode 的作用
typescript
// virtualMode: false(不安全!)
// 代理可以访问:
// - /Users/me/projects/my-app/src/
// - /Users/me/.ssh/id_rsa ← 危险!
// - /etc/passwd ← 危险!
// virtualMode: true(推荐)
// 代理只能访问 rootDir 内的路径
// - /Users/me/projects/my-app/src/ ✅
// - /Users/me/.ssh/id_rsa ❌ 被阻止
// - ../../../etc/passwd ❌ 被阻止
适用场景
- 🎯 本地开发 CLI 工具
- 🎯 编码助手(操作项目文件)
- 🎯 CI/CD 流水线(需做好安全配置)
不适用场景
- ❌ Web 服务器或 API
- ❌ 多租户系统
- ❌ 处理不受信任的用户输入
3. StoreBackend - 跨线程持久化
概念
StoreBackend 使用 LangGraph 的 BaseStore 实现跨线程的持久化存储。
生活类比:像一个云端笔记本,无论什么时候打开,之前的笔记都还在。
核心优势
线程 1 线程 2
┌─────────────────────────┐ ┌─────────────────────────┐
│ write_file("/pref.md") │ │ read_file("/pref.md") │
│ ✅ 成功 │ │ ✅ 成功 │
└───────────┬─────────────┘ └───────────┬─────────────┘
│ │
▼ ▼
┌─────────────────────────────────────┐
│ LangGraph Store │
│ (跨线程持久化,数据共享) │
└─────────────────────────────────────┘
使用方式
typescript
import { createDeepAgent } from "deepagents";
import { StoreBackend } from "deepagents/backends";
import { InMemoryStore } from "@langchain/langgraph";
// 开发环境使用 InMemoryStore
const store = new InMemoryStore();
const agent = createDeepAgent({
backend: (rt) => new StoreBackend(rt),
store: store
});Store 实现选择
| Store 类型 | 场景 | 特点 |
|---|---|---|
InMemoryStore | 开发测试 | 重启后数据丢失 |
PostgresStore | 生产环境 | 真正的持久化 |
| LangSmith 自动配置 | 云部署 | 无需手动配置 |
typescript
// 生产环境使用 PostgresStore
import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres";
const store = new PostgresStore({
connectionString: process.env.DATABASE_URL
});
const agent = createDeepAgent({
backend: (rt) => new StoreBackend(rt),
store: store
});适用场景
- 🎯 长期记忆(用户偏好、学习到的知识)
- 🎯 跨会话的研究项目
- 🎯 知识库积累
- 🎯 部署到 LangSmith
4. LocalShellBackend - 本地 Shell
概念
LocalShellBackend 在 FilesystemBackend 基础上增加了 execute 工具,允许代理执行 Shell 命令。
生活类比:不仅能看你的文件,还能帮你运行命令。
⚠️⚠️⚠️ 严重安全警告
┌────────────────────────────────────────────────────────────┐
│ 🚨 极度危险 - 请务必理解风险 │
│ │
│ LocalShellBackend 允许代理执行任意 Shell 命令! │
│ │
│ 代理可以: │
│ • 以你的用户权限执行任何命令 │
│ • 读取任何可访问文件 │
│ • 修改或删除文件 │
│ • 安装软件、发起网络请求 │
│ • 消耗无限 CPU、内存、磁盘 │
│ │
│ 仅在以下情况使用: │
│ ✅ 本地开发环境 │
│ ✅ 你完全信任代理的行为 │
│ ✅ 配合人机协作审批 │
│ │
│ 绝对不要用于: │
│ ❌ 生产环境 │
│ ❌ Web 服务器或 API │
│ ❌ 处理不受信任的用户输入 │
└────────────────────────────────────────────────────────────┘
使用方式
typescript
import { createDeepAgent } from "deepagents";
import { LocalShellBackend } from "deepagents/backends";
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const agent = createDeepAgent({
backend: new LocalShellBackend({
rootDir: ".",
env: { PATH: "/usr/bin:/bin" },
timeout: 120, // 命令超时(秒)
maxOutputBytes: 100000 // 输出限制
}),
interruptOn: {
execute: true // 强烈建议:所有命令执行前需人工审批
},
checkpointer
});配置选项
| 选项 | 默认值 | 说明 |
|---|---|---|
rootDir | 必填 | 工作目录 |
env | {} | 环境变量 |
inheritEnv | false | 是否继承系统环境变量 |
timeout | 120 | 命令超时(秒) |
maxOutputBytes | 100000 | 输出大小限制 |
execute 工具
typescript
// 代理可以这样调用
execute("npm install")
execute("npm run build")
execute("git status")
// 返回结果
{
stdout: "...",
stderr: "...",
exitCode: 0
}适用场景
- 🎯 本地编码助手
- 🎯 开发过程中的快速迭代
- 🎯 仅限你完全信任代理的场景
5. 沙盒后端 - 安全代码执行
概念
沙盒后端在隔离的环境中执行代码,保护宿主系统不受影响。
生活类比:给代理一个独立的虚拟机,让它在里面自由操作。
可用的沙盒提供商
| 提供商 | 特点 | 适用场景 |
|---|---|---|
| Modal | 云端容器,按需计费 | 生产环境 |
| Daytona | 开发环境管理 | 团队协作 |
| Deno | 轻量级 JS/TS 沙盒 | 快速原型 |
| Node VFS | 本地虚拟文件系统 | 开发测试 |
使用示例(Deno)
typescript
import { createDeepAgent } from "deepagents";
import { DenoSandbox } from "@langchain/deno";
const sandbox = await DenoSandbox.create({
memoryMb: 1024,
lifetime: "10m"
});
try {
const agent = createDeepAgent({
backend: sandbox,
systemPrompt: "你是一个 JavaScript 编码助手,可以在沙盒中执行代码。"
});
const result = await agent.invoke({
messages: [{
role: "user",
content: "创建一个 HTTP 服务器并测试它"
}]
});
} finally {
await sandbox.close();
}沙盒 vs LocalShellBackend
| 特性 | LocalShellBackend | 沙盒后端 |
|---|---|---|
| 执行环境 | 宿主机 | 隔离容器 |
| 安全性 | ⚠️ 危险 | ✅ 安全 |
| 性能 | 快 | 稍慢 |
| 适用场景 | 本地开发 | 生产环境 |

安全最佳实践
┌─────────────────────────────────────────────────────────────┐
│ 🔒 沙盒安全原则 │
│ │
│ 1. 永远不要把密钥放入沙盒 │
│ 2. 限制沙盒的网络访问 │
│ 3. 设置资源限制(内存、CPU、时间) │
│ 4. 定期清理沙盒环境 │
│ 5. 记录和审计沙盒内的操作 │
└─────────────────────────────────────────────────────────────┘后端选择决策树
开始
│
├─ 需要执行代码?
│ │
│ ├─ 是 ─────┬─ 生产环境?─── 是 ──→ 沙盒后端
│ │ │
│ │ └─ 本地开发?─── 是 ──→ LocalShellBackend
│ │ (配合 interruptOn)
│ │
│ └─ 否 ────→ 需要跨线程持久化?
│ │
│ ├─ 是 ──→ StoreBackend
│ │
│ └─ 否 ─→ 需要操作本地文件?
│ │
│ ├─ 是 ──→ FilesystemBackend
│ │
│ └─ 否 ──→ StateBackend (默认)
│
└─ 需要混合存储?─── 是 ──→ CompositeBackend (下篇详解)
实践示例:选择合适的后端
场景一:简单问答机器人
typescript
// 使用默认的 StateBackend 即可
const chatBot = createDeepAgent({
systemPrompt: "你是一个友好的聊天助手"
});场景二:本地编码助手
typescript
import { FilesystemBackend } from "deepagents/backends";
const codingAssistant = createDeepAgent({
backend: new FilesystemBackend({
rootDir: process.cwd(),
virtualMode: true
}),
systemPrompt: "你是一个编码助手,可以读取和修改项目文件"
});场景三:带记忆的个人助理
typescript
import { StoreBackend } from "deepagents/backends";
import { InMemoryStore } from "@langchain/langgraph";
const personalAssistant = createDeepAgent({
backend: (rt) => new StoreBackend(rt),
store: new InMemoryStore(),
systemPrompt: `你是一个个人助理。
记住用户的偏好,保存到 /preferences.md
记住重要事项,保存到 /notes/`
});场景四:安全的代码执行平台
typescript
import { DenoSandbox } from "@langchain/deno";
const sandbox = await DenoSandbox.create({ memoryMb: 512 });
const codeRunner = createDeepAgent({
backend: sandbox,
systemPrompt: "你可以执行用户提供的代码,在安全的沙盒环境中运行"
});小结
本文介绍了 DeepAgents 的五种后端类型:
| 后端 | 一句话总结 | 关键场景 |
|---|---|---|
| StateBackend | 临时存储,线程内有效 | 单次任务、默认选择 |
| FilesystemBackend | 本地磁盘读写 | 编码助手、本地开发 |
| StoreBackend | 跨线程持久化 | 长期记忆、知识库 |
| LocalShellBackend | 本地执行命令 | 开发工具(需谨慎) |
| 沙盒后端 | 安全代码执行 | 生产环境代码运行 |
选择原则:
- 🔒 安全第一:生产环境使用沙盒
- 💾 按需持久化:长期数据用 StoreBackend
- ⚡ 简单优先:默认 StateBackend 够用就不换
下一步
在下一篇文章中,我们将学习 CompositeBackend——如何组合多个后端,实现灵活的路由策略。
实践任务
- 创建一个使用 FilesystemBackend 的代理,让它能读写你项目中的文件
- 使用 StoreBackend 实现一个能"记住"用户偏好的助手
- 如果有条件,尝试配置一个沙盒后端