Deep Agents 通过 ls、read_file、write_file、edit_file、glob 和 grep 等工具向代理暴露文件系统接口。这些工具通过一个可插拔的后端运行。read_file 工具原生支持二进制文件(图像、PDF、音频、视频),并在所有后端中返回一个包含类型化 content 和 mimeType 的 ReadResult。 沙盒和 LocalShellBackend 还提供了一个 execute 工具。 本页将解释如何:
当您在 LangSmith 部署 上部署时,系统会自动配置一个存储。使用 LangSmith 追踪来调试文件路径、权限拒绝和跨线程存储问题。请按照 可观测性快速入门指南 进行设置。我们建议您同时设置 LangSmith 引擎,它可以监控您的追踪、检测问题并提出修复建议。

快速入门

这里有一些预构建的文件系统后端,您可以快速地将其与您的深度代理一起使用:

内置后端

StateBackend

工作原理:
  • 通过 StateBackend 将文件存储在当前线程的 LangGraph 代理状态中。
  • 通过检查点在同一线程的多个代理轮次中持久化。文件不跨线程共享。
设计为在图内使用。在图运行之外调用后端方法(例如 state_backend.upload_files(...))将不会生效,直到图执行为止。
最适合:
  • 用于代理写入中间结果的草稿本。
  • 自动淘汰大型工具输出,代理随后可以分块读回。
请注意,此后端在主管代理和子代理之间共享,子代理写入的任何文件即使在该子代理执行完成后仍将保留在 LangGraph 代理状态中。这些文件将继续可供主管代理和其他子代理使用。

FilesystemBackend(本地磁盘)

FilesystemBackend 在可配置的根目录下读写真实文件。
此授权代理具有直接的文件系统读/写访问权限。 请谨慎使用,并仅在适当的环境中使用。适用用例:
  • 本地开发 CLI(编码助手、开发工具)
  • CI/CD 管道(请参阅下面的安全注意事项)
不适用用例:
  • Web 服务器或 HTTP API - 请改用 StateBackend、StoreBackend 或沙盒后端
安全风险:
  • 代理可以读取任何可访问的文件,包括密钥(API 密钥、凭据、.env 文件)
  • 结合网络工具,密钥可能通过 SSRF 攻击被泄露
  • 文件修改是永久且不可逆的
推荐的保护措施:
  1. 启用人机协作 (HITL) 中间件以审查敏感操作。
  2. 将密钥排除在可访问的文件系统路径之外(尤其是在 CI/CD 中)。
  3. 对于需要文件系统交互的生产环境,请使用沙盒后端。
  4. 务必在设置 root_dir 时使用 virtual_mode=True,以启用基于路径的访问限制(阻止 ..、~ 以及根目录外的绝对路径)。 请注意,默认值(virtual_mode=False)即使设置了 root_dir 也不提供安全性。
工作原理:
  • 在可配置的 root_dir 下读写真实文件。
  • 您可以选择性地设置 virtual_mode=True 以在 root_dir 下沙盒化和规范化路径。
  • 使用安全的路径解析,尽可能防止不安全的符号链接遍历,可以使用 ripgrep 进行快速 grep。
最适合:
  • 您机器上的本地项目
  • CI 沙盒
  • 挂载的持久卷
对于大多数用例,请将 FilesystemBackend 包装在 CompositeBackend 中。Deep Agents 会自动将内部数据写入后端,包括卸载的大型工具结果(位于 /large_tool_results/ 下)和对话历史记录(位于 /conversation_history/ 下)。当您单独使用 FilesystemBackend 时,这些内部文件将写入 root_dir 下的真实磁盘,将代理工件与您的项目文件混合。使用 CompositeBackend 将您的项目目录路由到 FilesystemBackend,同时将内部路径保留在临时的 StateBackend 存储中:
通过这种方式,代理在 /workspace/ 下的读写操作会指向真实磁盘,而卸载的工具结果和其他内部数据则保留在临时状态中。有关更多路由模式,请参阅路由到不同的后端。

LocalShellBackend(本地 Shell)

此授权代理具有直接的文件系统读/写访问权限以及在您的宿主机上不受限制的 Shell 执行能力。 请极其谨慎使用,并仅在适当的环境中使用。适用用例:
  • 本地开发 CLI(编码助手、开发工具)
  • 您信任代理代码的个人开发环境
  • 具有适当密钥管理的 CI/CD 管道
不适用用例:
  • 生产环境(如 Web 服务器、API、多租户系统)
  • 处理不受信任的用户输入或执行不受信任的代码
安全风险:
  • 代理可以使用您的用户权限执行任意 Shell 命令
  • 代理可以读取任何可访问的文件,包括密钥(API 密钥、凭据、.env 文件)
  • 密钥可能暴露
  • 文件修改和命令执行是永久且不可逆的
  • 命令直接在您的宿主系统上运行
  • 命令可以消耗无限的 CPU、内存、磁盘资源
推荐的保护措施:
  1. 启用人机协作 (HITL) 中间件在执行前审查并批准操作。这是强烈推荐的。
  2. 仅在专用开发环境中运行。切勿在共享或生产系统上使用。
  3. 对于需要 Shell 执行的生产环境,请使用沙盒后端。
注意: 当启用 Shell 访问时,virtual_mode=True 不提供安全性,因为命令可以访问系统上的任何路径。
工作原理:
  • 扩展 FilesystemBackend,增加了用于在宿主机上运行 Shell 命令的 execute 工具。
  • 使用 subprocess.run(shell=True) 直接在您的机器上运行命令,没有沙盒化。
  • 支持 timeout(默认 120 秒)、max_output_bytes(默认 100,000)、env 和 inherit_env 用于环境变量。
  • Shell 命令使用 root_dir 作为工作目录,但可以访问系统上的任何路径。
最适合:
  • 本地编码助手和开发工具
  • 当您信任代理时,在开发过程中快速迭代

StoreBackend(LangGraph 存储)

部署到 LangSmith 部署 时,请省略 store 参数。平台会自动为您的代理配置一个存储。
namespace 参数控制数据隔离。对于多用户部署,始终设置一个命名空间工厂以按用户或租户隔离数据。
工作原理:
  • StoreBackend 将文件存储在运行时提供的 LangGraph BaseStore 中,从而实现跨线程的持久存储。
最适合:
  • 当您已经在使用配置好的 LangGraph 存储运行时(例如,Redis、Postgres 或 BaseStore 背后的云实现)。
  • 当您通过 LangSmith 部署 部署代理时(系统会自动为您的代理配置一个存储)。

命名空间工厂

命名空间工厂控制 StoreBackend 读写数据的位置。它接收一个 LangGraph Runtime 并返回一个用作存储命名空间的字符串元组。使用命名空间工厂可以在用户、租户或助手之间隔离数据。 在构造 StoreBackend 时,将命名空间工厂传递给 namespace 参数:
Runtime 提供:
  • rt.context — 用户通过 LangGraph 的上下文模式 传递的上下文(例如,user_id)
  • rt.serverInfo — 在 LangGraph Server 上运行时的服务器特定元数据(助手 ID、图 ID、认证用户)
  • rt.executionInfo — 执行标识信息(线程 ID、运行 ID、检查点 ID)
Runtime 参数在 deepagents>=1.9.1 中可用。早期的 1.9.x 版本传递的是 BackendContext — 请参阅下面的从 BackendContext 迁移。rt.serverInfo 和 rt.executionInfo 需要 deepagents>=1.9.0。
常见的命名空间模式:
您可以组合多个组件来创建更具体的范围 — 例如,(user_id, thread_id) 用于按用户按对话隔离,或者添加后缀如 "filesystem" 以在同一范围使用多个存储命名空间时进行区分。 命名空间组件必须仅包含字母数字字符、连字符、下划线、点、@、+、冒号和波浪号。为防止 glob 注入,拒绝使用通配符(*、?)。
namespace 参数在 v1.9.0 中将是必需的。对于新代码,请始终显式设置它。
当未提供命名空间工厂时,旧的默认行为使用来自 LangGraph 配置元数据的 assistant_id。这意味着同一助手的所有用户共享相同的存储。对于多用户准备生产环境,始终提供一个命名空间工厂。

ContextHubBackend

开始之前: ContextHubBackend 需要在 LangSmith 中设置一个上下文中心仓库。如果您不熟悉代理仓库和技能仓库,请先阅读上下文中心概念页面。
ContextHubBackend 将您的代理文件系统存储在 LangSmith 上下文中心仓库中。它可以使用独立仓库或链接到技能仓库的代理仓库。 仓库结构: 在上下文中心,一个_代理仓库_保存代理的顶层指令和配置(例如,AGENTS.md、tools.json)。它可以链接到一个或多个_技能仓库_,每个技能仓库打包为一个可重用的能力(例如,包含电子邮件格式化或代码审查指令的 SKILL.md)。当您传递 ContextHubBackend("my-agent") 时,后端将代理仓库挂载到文件系统根目录;链接的技能仓库显示为 /skills/ 下的子目录。 这意味着您代理的上下文故意分布在多个仓库中:每个代理一个仓库,每个技能单独的仓库。这种分离使得技能可以独立于多个代理进行版本控制、共享和重用。如果这感觉过于分散,请参阅链接仓库了解其原理。 使用 owner/name 或 name 格式的仓库标识符构造它。
使用 ContextHubBackend 前请设置 LANGSMITH_API_KEY。
工作原理:
  • 首次使用时延迟拉取中心仓库树,然后从内存缓存提供读取服务。
  • 将写入和编辑作为中心提交进行持久化,并在成功提交后更新缓存。
  • 使用乐观父提交写入(parent_commit):每次推送都针对已知的最新提交哈希。
行为和限制:
  • 如果仓库不存在,首次拉取视为空;第一次成功写入可以创建仓库。
  • 如果另一个写入者先推进了仓库,您过期的父提交写入可能会失败。在冲突时重新拉取并重试。
  • upload_files() 接受 UTF-8 文本。非 UTF-8 文件按路径以 invalid_path 拒绝。
最适合:
  • LangSmith 原生的持久文件系统持久化,无需单独连接 LangGraph BaseStore。
  • 受益于中心提交历史记录的文件系统更改的工作流。

CompositeBackend(路由器)

工作原理:
  • CompositeBackend 根据路径前缀将文件操作路由到不同的后端。
  • 在列表和搜索结果中保留原始路径前缀。
最适合:
  • 当您希望为代理同时提供线程作用域和跨线程存储时,CompositeBackend 允许您同时提供 StateBackend 和 StoreBackend
  • 当您有多个信息源想要作为单个文件系统的一部分提供给代理时。
    • 例如,您将长期记忆存储在一个存储中的 /memories/ 下,并且您还有一个自定义后端,其中包含可通过 /docs/ 访问的文档。

指定一个后端

  • 将后端实例传递给 createDeepAgent({ backend: ... })。文件系统中间件将其用于所有工具操作。
  • 后端必须实现 AnyBackendProtocol(BackendProtocolV1 或 BackendProtocolV2)— 例如,new StateBackend()、new FilesystemBackend({ rootDir: "." })、new StoreBackend()。
  • 如果省略,默认为 new StateBackend()。
在 1.9.0 版本之前,只支持 BackendProtocol,现在称为 BackendProtocolV1。V1 后端在运行时通过 adaptBackendProtocol() 自动适配到 V2。要继续使用现有的 V1 后端,无需更改代码。要更新到 v2,请参阅将现有后端更新到 v2。

路由到不同的后端

将命名空间的各个部分路由到不同的后端。通常用于跨线程持久化 /memories/*,并保持其他所有内容为线程作用域。
行为:
  • /workspace/plan.md → StateBackend(线程作用域)
  • /memories/agent.md → /deepagents/myagent 下的 FilesystemBackend
  • ls、glob、grep 聚合结果并显示原始路径前缀。
注意:
  • 更长的前缀优先(例如,路由 "/memories/projects/" 可以覆盖 "/memories/")。
  • 对于 StoreBackend 路由,请确保存储已通过 create_deep_agent(model=..., store=...) 提供或由平台配置。
  • Deep Agents 将内部数据(卸载的工具结果、对话历史记录)写入默认后端。使用 StateBackend 作为默认后端,以保持这些工件临时性,避免将它们写入磁盘或持久存储。有关完整示例,请参阅 FilesystemBackend 提示。

自定义后端

实现自定义后端以将 Deep Agents 连接到数据库、对象存储和远程文件系统等存储系统。有关示例,请参阅社区构建的后端。

实现后端协议

实现 BackendProtocol(BackendProtocolV2)并提供以下方法: 要同时支持 execute 工具(运行 Shell 命令),请实现 SandboxBackendProtocol,它用 execute 方法扩展了 BackendProtocolV2。 所有方法必须返回带有可选 error 字段的结构化 Result 对象 — 不要在文件缺失或模式无效时抛出异常。
此骨架将文件系统路径映射到对象键。用您的存储客户端的列表、读取、搜索、上传和读-修改-写操作填充每个方法。

权限

使用权限声明式地控制代理可以读取或写入哪些文件和目录。权限适用于内置的文件系统工具,并在调用后端之前进行评估。 有关完整的选项集,包括规则排序、子代理权限和组合后端交互,请参阅权限指南。

添加策略钩子

对于基于路径的允许/拒绝规则之外的自定义验证逻辑(速率限制、审计日志、内容检查),通过子类化或包装后端来强制执行企业规则。 阻止对选定前缀下的写入/编辑(子类化):
通用包装器(适用于任何后端):

多模态和二进制文件

多模态文件支持(PDF、音频、视频)需要 deepagents>=1.9.0。
V2 后端原生支持二进制文件。当 read() 遇到二进制文件(根据文件扩展名确定 MIME 类型)时,它返回一个包含 Uint8Array 内容和相应 mimeType 的 ReadResult。文本文件返回 string 内容。

支持的 MIME 类型

读取二进制文件

FileData 格式

FileData 是用于在状态和存储后端中存储文件内容的类型。
后端在从状态或存储读取时可能会遇到任一格式。框架会透明地处理这两种格式。新写入默认为 v2 格式。在需要旧格式读取器的滚动部署期间,请将 fileFormat: "v1" 传递给后端构造函数(例如,new StoreBackend({ fileFormat: "v1" }))。

从后端工厂迁移

后端工厂模式自 deepagents 1.9.0 起已弃用。请直接传递预构造的后端实例,而不是工厂函数。
以前,StateBackend 和 StoreBackend 等后端需要一个接收运行时对象的工厂函数,因为它们需要运行时上下文(状态、存储)才能运行。后端现在通过 LangGraph 的 get_config()、get_store() 和 get_runtime() 辅助函数在内部解析此上下文,因此您可以直接传递实例。

发生了什么变化

已弃用的 API

工厂模式在运行时仍然有效,并会发出弃用警告。在下一个主要版本之前更新您的代码以使用直接实例。

迁移示例

从 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 没有直接替代。命名空间信息在运行期间应是只读且稳定的,而状态是可变的且逐步变化的 — 从状态派生命名空间有风险,导致数据最终位于不一致的键下。如果您有一个需要读取代理状态的用例,请提交问题。

协议参考

后端必须实现 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: Optional[str] = None) -> 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。 :::
后端实现 BackendProtocolV2。所有查询方法都返回带有 { error?: string, ...data } 的结构化 Result 对象。

必需方法

  • ls(path: string) → LsResult
    • 列出指定目录中的文件和目录(非递归)。目录在其路径末尾有 /,并且 is_dir=true。可用时包括 is_dir、size、modified_at。
  • read(filePath: string, offset?: number, limit?: number) → ReadResult
    • 读取文件内容。对于文本文件,内容按行偏移/限制分页(默认偏移 0,限制 500)。对于二进制文件,返回完整的原始 Uint8Array 内容,并设置 mimeType 字段。文件缺失时,返回 { error: "File '/x' not found" }。
  • readRaw(filePath: string) → ReadRawResult
    • 以原始 FileData 形式读取文件内容。返回包含时间戳的完整文件数据。
  • grep(pattern: string, path?: string | null, glob?: string | null) → GrepResult
    • 在文件内容中搜索字面文本模式。二进制文件(根据 MIME 类型确定)被跳过。失败时,返回 { error: "..." }。
  • glob(pattern: string, path?: string) → GlobResult
    • 返回匹配 glob 模式的文件作为 FileInfo 条目。
  • write(filePath: string, content: string) → WriteResult
    • 仅创建语义。冲突时,返回 { error: "..." }。成功时,设置 path,对于状态后端设置 filesUpdate={...};外部后端应使用 filesUpdate=null。
  • edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean) → EditResult
    • 除非 replaceAll=true,否则强制 oldString 唯一。如果未找到,返回错误。成功时包括 occurrences。

可选方法

  • uploadFiles(files: Array<[string, Uint8Array]>) → FileUploadResponse[] — 上传多个文件(用于沙盒后端)。
  • downloadFiles(paths: string[]) → FileDownloadResponse[] — 下载多个文件(用于沙盒后端)。

结果类型

支持类型

  • FileInfo — path(必需),可选 is_dir、size、modified_at。
  • GrepMatch — path、line(1-indexed)、text。
  • FileData — 带时间戳的文件内容。请参阅 FileData 格式。

沙盒扩展

SandboxBackendProtocolV2 用以下内容扩展了 BackendProtocolV2:
  • execute(command: string) → ExecuteResponse — 在沙盒中运行 Shell 命令。
  • readonly id: string — 沙盒实例的唯一标识符。

将现有后端更新到 V2

方法重命名

类型重命名

适配工具

如果您有需要与仅 V2 代码一起使用的现有 V1 后端,请使用适配函数:
框架会自动适配传递给 createDeepAgent() 的 V1 后端。仅在直接调用协议方法时才需要手动适配。