ls、read_file、write_file、edit_file、glob 和 grep 等工具向代理暴露文件系统接口。这些工具通过一个可插拔的后端运行。read_file 工具在所有后端中都原生支持图像文件(.png、.jpg、.jpeg、.gif、.webp),并将其作为多模态内容块返回。
沙箱和 LocalShellBackend 还提供了一个 execute 工具。
本页说明如何:
- 选择后端,
- 将不同路径路由到不同后端,
- 实现您自己的虚拟文件系统(例如,S3 或 Postgres),
- 设置文件系统访问权限,
- 遵守后端协议,
快速入门
以下是几个预构建的文件系统后端,您可以快速将其与您的 deep agent 一起使用:| 内置后端 | 描述 |
|---|---|
| 默认 | agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview") 临时存储在状态中。代理的默认文件系统后端存储在 langgraph 状态中。请注意,此文件系统仅在_单个线程_内持久化。 |
| 本地文件系统持久化 | agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=FilesystemBackend(root_dir="/Users/nh/Desktop/")) 这使 deep agent 可以访问您本地机器的文件系统。您可以指定代理有权访问的根目录。请注意,任何提供的 root_dir 必须是绝对路径。 |
| 持久化存储(LangGraph 存储) | agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=StoreBackend()) 这使代理可以访问_跨线程持久化_的长期存储。这对于存储长期记忆或适用于代理多次执行的指令非常有用。 |
| 沙箱 | agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=sandbox) 在隔离环境中执行代码。沙箱提供文件系统工具以及用于运行 shell 命令的 execute 工具。可从 Modal、Daytona、Deno 或本地 VFS 中选择。 |
| 本地 shell | agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview", backend=LocalShellBackend(root_dir=".", env={"PATH": "/usr/bin:/bin"})) 直接在主机上进行文件系统和 shell 执行。无隔离——仅在受控开发环境中使用。请参阅下面的安全注意事项。 |
| 组合 | 默认为临时存储,/memories/ 持久化。组合后端具有最大的灵活性。您可以指定文件系统中的不同路由指向不同的后端。有关可直接粘贴的示例,请参阅下面的组合路由。 |
内置后端
StateBackend(临时)
- 通过
StateBackend将文件存储在当前线程的 LangGraph 代理状态中。 - 通过检查点在同一线程的多个代理轮次中持久化。
- 代理用于编写中间结果的临时记事本。
- 自动清除大型工具输出,然后代理可以逐块读回。
FilesystemBackend(本地磁盘)
FilesystemBackend 在可配置的根目录下读写真实文件。
- 在可配置的
root_dir下读写真实文件。 - 您可以选择设置
virtual_mode=True以在root_dir下沙箱化并规范化路径。 - 使用安全的路径解析,尽可能防止不安全的符号链接遍历,可以使用 ripgrep 进行快速
grep。
- 您机器上的本地项目
- CI 沙箱
- 挂载的持久卷
LocalShellBackend(本地 shell)
- 扩展
FilesystemBackend,添加了用于在主机上运行 shell 命令的execute工具。 - 命令直接在您的机器上使用
subprocess.run(shell=True)运行,无沙箱化。 - 支持
timeout(默认 120 秒)、max_output_bytes(默认 100,000)、env和inherit_env用于环境变量。 - Shell 命令使用
root_dir作为工作目录,但可以访问系统上的任何路径。
- 本地编码助手和开发工具
- 在您信任代理时进行快速开发迭代
StoreBackend(LangGraph 存储)
部署到 LangSmith Deployment 时,请省略
store 参数。平台会自动为您的智能体配置存储。StoreBackend将文件存储在运行时提供的 LangGraphBaseStore中,实现跨线程的持久化存储。
- 当您已经使用配置好的 LangGraph 存储运行时(例如,Redis、Postgres 或
BaseStore背后的云实现)。 - 当您通过 LangSmith Deployment 部署代理时(会自动为您的代理配置存储)。
命名空间工厂
命名空间工厂控制StoreBackend 读写数据的位置。它接收一个 LangGraph Runtime 并返回一个字符串元组,用作存储命名空间。使用命名空间工厂在用户、租户或助手之间隔离数据。
在构造 StoreBackend 时将命名空间工厂传递给 namespace 参数:
Runtime 提供:
rt.context— 通过 LangGraph 的上下文模式传递的用户提供的上下文(例如,user_id)rt.server_info— 在 LangGraph Server 上运行时的服务器特定元数据(助手 ID、图 ID、已认证用户)rt.execution_info— 执行身份信息(线程 ID、运行 ID、检查点 ID)
Runtime 参数在 deepagents>=0.5.2 中可用。早期的 0.5.x 版本传递的是 BackendContext — 请参阅下面的从 BackendContext 迁移。rt.server_info 和 rt.execution_info 需要 deepagents>=0.5.0。(user_id, thread_id) 用于按用户按对话隔离,或附加后缀如 "filesystem" 以在相同范围使用多个存储命名空间时消除歧义。
命名空间组件只能包含字母数字字符、连字符、下划线、点、@、+、冒号和波浪号。通配符(*、?)会被拒绝以防止 glob 注入。
CompositeBackend(路由器)
CompositeBackend根据路径前缀将文件操作路由到不同的后端。- 在列表和搜索结果中保留原始路径前缀。
- 当您想为代理提供临时和跨线程存储时,
CompositeBackend允许您同时提供StateBackend和StoreBackend - 当您有多个信息源希望作为单个文件系统的一部分提供给代理时。
- 例如,您在一个存储中将长期记忆存储在
/memories/下,并且还有一个自定义后端,其文档可在 /docs/ 访问。
- 例如,您在一个存储中将长期记忆存储在
指定后端
- 将后端实例传递给
create_deep_agent(model=..., backend=...)。文件系统中间件将其用于所有工具。 - 后端必须实现
BackendProtocol(例如,StateBackend()、FilesystemBackend(root_dir=".")、StoreBackend())。 - 如果省略,默认为
StateBackend()。
路由到不同后端
将命名空间的不同部分路由到不同的后端。通常用于持久化/memories/* 并保持其他所有内容为临时存储。
/workspace/plan.md→StateBackend(临时)/memories/agent.md→FilesystemBackend在/deepagents/myagent下ls、glob、grep聚合结果并显示原始路径前缀。
- 更长的前缀优先(例如,路由
"/memories/projects/"可以覆盖"/memories/")。 - 对于 StoreBackend 路由,请确保通过
create_deep_agent(model=..., store=...)提供存储或由平台配置。
使用虚拟文件系统
构建自定义后端以将远程或数据库文件系统(例如,S3 或 Postgres)投影到工具命名空间中。 设计指南:-
路径是绝对的(
/x/y.txt)。决定如何将它们映射到您的存储键/行。 -
高效实现
ls和glob(尽可能进行服务器端过滤,否则进行本地过滤)。 -
对于外部持久化(S3、Postgres 等),在写入/编辑结果中返回
files_update=None(Python)或省略filesUpdate(JS)——只有内存状态后端需要返回文件更新字典。 -
使用
ls和glob作为方法名。 -
返回带有
error字段的结构化结果类型,用于缺失文件或无效模式(不要引发异常)。
- 表
files(path text primary key, content text, created_at timestamptz, modified_at timestamptz) - 将工具操作映射到 SQL:
ls使用WHERE path LIKE $1 || '%'glob在 SQL 中过滤或获取后在 Python 中应用 globgrep可以按扩展名或最后修改时间获取候选行,然后扫描行
权限
使用权限来声明式地控制代理可以读取或写入哪些文件和目录。权限适用于内置的文件系统工具,并在调用后端之前进行评估。添加策略钩子
对于超出基于路径的允许/拒绝规则(速率限制、审计日志、内容检查)的自定义验证逻辑,通过子类化或包装后端来强制执行企业规则。 阻止在选定前缀下的写入/编辑(子类化):从后端工厂迁移
以前,像StateBackend 和 StoreBackend 这样的后端需要一个接收运行时对象的工厂函数,因为它们需要运行时上下文(状态、存储)才能运行。现在后端通过 LangGraph 的 get_config()、get_store() 和 get_runtime() 辅助函数内部解析此上下文,因此您可以直接传递实例。
变更内容
| 之前(已弃用) | 之后 |
|---|---|
backend=lambda rt: StateBackend(rt) | backend=StateBackend() |
backend=lambda rt: StoreBackend(rt) | backend=StoreBackend() |
backend=lambda rt: CompositeBackend(default=StateBackend(rt), ...) | backend=CompositeBackend(default=StateBackend(), ...) |
backend: (config) => new StateBackend(config) | backend: new StateBackend() |
backend: (config) => new StoreBackend(config) | backend: new StoreBackend() |
已弃用的 API
| 已弃用 | 替代方案 |
|---|---|
将可调用对象传递给 create_deep_agent 中的 backend= | 直接传递后端实例 |
StateBackend(runtime) 上的 runtime 构造函数参数 | StateBackend()(无需参数) |
StoreBackend(runtime) 上的 runtime 构造函数参数 | StoreBackend() 或 StoreBackend(namespace=..., store=...) |
WriteResult 和 EditResult 上的 files_update 字段 | 状态写入现在由后端内部处理 |
中间件写入/编辑工具中的 Command 包装 | 工具返回普通字符串;不需要 Command(update=...) |
工厂模式在运行时仍然有效,但会发出弃用警告。请在下一个主要版本之前更新您的代码以使用直接实例。
迁移示例
从 BackendContext 迁移
在 deepagents>=0.5.2(Python)和 deepagents>=1.9.1(TypeScript)中,命名空间工厂直接接收 LangGraph Runtime,而不是 BackendContext 包装器。旧的 BackendContext 形式仍然通过向后兼容的 .runtime 和 .state 访问器工作,但这些访问器会发出弃用警告,并将在 deepagents>=0.7 中移除。
变更内容:
- 工厂参数现在是
Runtime,而不是BackendContext。 - 删除
.runtime访问器——例如,ctx.runtime.context.user_id变为rt.server_info.user.identity。 ctx.state没有直接替代方案。命名空间信息应该是只读的,并且在运行生命周期内保持稳定,而状态是可变的,并且会逐步变化——从中派生命名空间可能导致数据最终位于不一致的键下。如果您有需要读取代理状态的用例,请提交 issue。
协议参考
后端必须实现BackendProtocol。
必需的方法:
ls(path: str) -> LsResult- 返回至少包含
path的条目。在可用时包含is_dir、size、modified_at。按path排序以获得确定性输出。
- 返回至少包含
read(file_path: str, offset: int = 0, limit: int = 2000) -> ReadResult- 成功时返回文件数据。文件缺失时,返回
ReadResult(error="Error: File '/x' not found")。
- 成功时返回文件数据。文件缺失时,返回
grep(pattern: str, path: Optional[str] = None, glob: Optional[str] = None) -> GrepResult- 返回结构化匹配项。出错时,返回
GrepResult(error="...")(不要引发异常)。
- 返回结构化匹配项。出错时,返回
glob(pattern: str, path: str = "/") -> GlobResult- 将匹配的文件作为
FileInfo条目返回(如果没有则为空列表)。
- 将匹配的文件作为
write(file_path: str, content: str) -> WriteResult- 仅创建。冲突时,返回
WriteResult(error=...)。成功时,设置path,对于状态后端设置files_update={...};外部后端应使用files_update=None。
- 仅创建。冲突时,返回
edit(file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult- 除非
replace_all=True,否则强制old_string的唯一性。如果未找到,返回错误。成功时包含occurrences。
- 除非
LsResult(error, entries)— 成功时entries是list[FileInfo],失败时为None。ReadResult(error, file_data)— 成功时file_data是FileData字典,失败时为None。GrepResult(error, matches)— 成功时matches是list[GrepMatch],失败时为None。GlobResult(error, matches)— 成功时matches是list[FileInfo],失败时为None。WriteResult(error, path, files_update)EditResult(error, path, files_update, occurrences)FileInfo字段:path(必需),可选is_dir、size、modified_at。GrepMatch字段:path、line、text。FileData字段:content(str)、encoding("utf-8"或"base64")、created_at、modified_at。 :::
将这些文档连接到 Claude、VSCode 等,通过 MCP 获取实时答案。

