ls、read_file、write_file、edit_file、glob、grep 等工具向智能体暴露文件系统接口。这些工具基于可插拔的后端运行。
本页将介绍如何选择后端、将不同路径路由到不同后端、实现自定义虚拟文件系统(例如 S3 或 Postgres)、添加策略钩子以及遵循后端协议。
快速入门
以下是几种可直接用于深度智能体的预构建文件系统后端:| 内置后端 | 说明 |
|---|---|
| 默认 | agent = create_deep_agent() 在状态中短暂存储。默认文件系统后端存储于 langgraph 状态,仅在单个线程内持久。 |
| 本地文件系统持久化 | agent = create_deep_agent(backend=FilesystemBackend(root_dir="/Users/nh/Desktop/")) 让深度智能体访问本地机器文件系统。可以指定智能体可访问的根目录,必须使用绝对路径。 |
| 持久 Store(LangGraph Store) | agent = create_deep_agent(backend=lambda rt: StoreBackend(rt)) 为智能体提供跨线程持久化的存储,非常适合保存长期记忆或多次执行都需要的指令。 |
| 组合后端 | 默认短暂存储,/memories/ 路径持久化。Composite 后端灵活性最高,可以为不同路径配置不同后端。下文提供可直接复制的路由示例。 |
内置后端
StateBackend(短暂存储)
- 将文件存储在当前线程的 LangGraph 智能体状态中。
- 通过检查点跨同一线程的多次调用持久化。
- 作为智能体的草稿空间,用于写入中间结果。
- 自动驱逐体积较大的工具输出,智能体可按需逐段读取。
FilesystemBackend(本地磁盘)
- 在指定的
root_dir下读取/写入真实文件。 root_dir必须是绝对路径。- 可选
virtual_mode=True,在root_dir内进行沙箱隔离和路径规范化。 - 使用安全的路径解析,尽可能阻止危险的符号链接遍历;支持使用 ripgrep 加速
grep。
- 本地项目开发
- CI 沙箱环境
- 挂载的持久卷
StoreBackend(LangGraph Store)
- 将文件存储在运行时提供的 LangGraph
BaseStore中,实现跨线程的持久化。
- 已经配置 LangGraph Store 的环境(例如 Redis、Postgres 或基于
BaseStore的云实现)。 - 使用 LangSmith Deployments 部署智能体(平台会自动为智能体提供 Store)。
CompositeBackend(路由器)
- 根据路径前缀将文件操作路由到不同后端。
- 在列表与搜索结果中保留原始路径前缀。
- 同时提供短暂存储与跨线程持久存储,例如将 StateBackend 与 StoreBackend 结合。
- 当需要将多个信息源以统一文件系统形式提供给智能体时。
- 例如
/memories/下使用 Store 保存长期记忆,同时/docs/下使用自定义后端提供文档。
- 例如
指定后端
- 通过
create_deep_agent(backend=...)传入后端,文件系统中间件会使用该后端提供所有工具。 - 可传入以下任意一种:
- 实现
BackendProtocol的实例(如FilesystemBackend(root_dir="."))。 - 工厂函数
BackendFactory = Callable[[ToolRuntime], BackendProtocol](适用于需要运行时的后端,如StateBackend或StoreBackend)。
- 实现
- 如果未指定,默认使用
lambda rt: StateBackend(rt)。
路由到不同的后端
可以将命名空间的不同部分路由到不同后端,常见做法是让/memories/* 持久化,而其他路径保持短暂。
/workspace/plan.md→ 使用 StateBackend(短暂存储)/memories/agent.md→ 使用 FilesystemBackend,在/deepagents/myagent下持久化ls、glob、grep会聚合结果并保留原始路径前缀
- 更长的前缀优先匹配(例如
"/memories/projects/"会覆盖"/memories/")。 - 如果路由到 StoreBackend,请确保运行时提供了
store(即runtime.store)。
使用虚拟文件系统
可构建自定义后端,将远程存储或数据库(如 S3、Postgres)映射为工具可访问的文件系统。 设计指南:- 路径均为绝对路径(如
/x/y.txt)。需要决定如何映射到存储键或数据库行。 - 高效实现
ls_info与glob_info(优先使用服务端列表;若不可行,则本地过滤)。 - 对缺失文件或非法正则表达式返回用户可读的错误字符串。
- 若为外部持久化存储,请在结果中返回
files_update=None;仅状态内后端应返回files_update字典。
- 建表:
files(path text primary key, content text, created_at timestamptz, modified_at timestamptz) - 将工具操作映射到 SQL:
ls_info使用WHERE path LIKE $1 || '%'glob_info可在 SQL 中过滤或先查询再本地 globgrep_raw可以按扩展名或修改时间筛选候选行,再逐行扫描
添加策略钩子
通过继承或包装后端,可以实现企业级策略管控。 禁止特定前缀写入/编辑(继承方式):协议参考
所有后端都必须实现BackendProtocol。
必选接口:
ls_info(path: str) -> list[FileInfo]- 返回的条目至少包含
path。如有可能,补充is_dir、size、modified_at。建议按path排序,保证输出确定性。
- 返回的条目至少包含
read(file_path: str, offset: int = 0, limit: int = 2000) -> str- 返回带行号的内容。若文件不存在,返回字符串:
"Error: File '/x' not found"。
- 返回带行号的内容。若文件不存在,返回字符串:
grep_raw(pattern: str, path: Optional[str] = None, glob: Optional[str] = None) -> list[GrepMatch] | str- 返回结构化匹配结果。若正则无效,返回类似
"Invalid regex pattern: ..."的字符串(不要抛异常)。
- 返回结构化匹配结果。若正则无效,返回类似
glob_info(pattern: str, path: str = "/") -> list[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- 默认要求
old_string仅出现一次;若设置replace_all=True则替换全部匹配。未找到时返回错误。成功时包含occurrences。
- 默认要求
WriteResult(error, path, files_update)EditResult(error, path, files_update, occurrences)FileInfo字段:必填path,可选is_dir、size、modified_atGrepMatch字段:path、line、text