Skip to content

Deep Agents 通过 lsread_filewrite_fileedit_filedeleteglobgrep 等工具向智能体暴露文件系统接口。这些工具通过可插拔后端运行。read_file 工具在所有后端上都原生支持图片文件(.png.jpg.jpeg.gif.webp),并将其作为多模态内容块返回。

Deep Agents 通过 lsread_filewrite_fileedit_fileglobgrep 等工具向智能体暴露文件系统接口。这些工具通过可插拔后端运行。read_file 工具在所有后端上都原生支持二进制文件(图片、PDF、音频、视频),并返回包含类型化 contentmimeTypeReadResult

沙箱和 LocalShellBackend 还提供 execute 工具。 本页说明如何:

TIP

当你在 LangSmith Deployment 上部署时,系统会自动配置一个 store。使用 LangSmith 追踪来调试文件路径、权限拒绝和跨线程存储。请按照可观测性快速入门进行设置。

我们还建议你设置 LangSmith Engine,它会监控你的追踪、检测问题并提出修复建议。

快速入门

这里有几个内置文件系统后端,你可以与深度智能体一起快速使用:

内置后端说明
默认agent = create_deep_agent(model="google_genai:gemini-3.6-flash") 线程作用域。智能体的默认文件系统后端存储在 langgraph 状态中。文件在同一个线程内跨轮次持久化(通过你的检查点器),并且不在线程之间共享。
本地文件系统持久化agent = create_deep_agent(model="google_genai:gemini-3.6-flash", backend=FilesystemBackend(root_dir="/Users/nh/Desktop/")) 这使深度智能体能够访问你本地机器的文件系统。你可以指定智能体可访问的根目录。请注意,任何提供的 root_dir 必须是绝对路径。通常,将其包装在 CompositeBackend 中,以使内部智能体数据(已卸载的工具结果、对话历史)与你的项目文件分离。
持久化存储(LangGraph store)agent = create_deep_agent(model="google_genai:gemini-3.6-flash", backend=StoreBackend()) 这使智能体能够访问_跨线程持久化_的长期存储。这对于存储适用于智能体多次执行的长期记忆或指令非常有用。
Context Hubagent = create_deep_agent(model="google_genai:gemini-3.6-flash", backend=ContextHubBackend("my-agent")) 将文件持久化存储在 LangSmith Hub 仓库中,无需单独配置 LangGraph store。
沙箱agent = create_deep_agent(model="google_genai:gemini-3.6-flash", backend=sandbox) 在隔离环境中执行代码。沙箱提供文件系统工具以及用于运行 shell 命令的 execute 工具。可从 LangSmith、AgentCore、Daytona、Deno、E2B、Modal、Runloop 或本地 VFS 中进行选择。
本地 shellagent = create_deep_agent(model="google_genai:gemini-3.6-flash", backend=LocalShellBackend(root_dir=".", env={"PATH": "/usr/bin:/bin"})) 直接在主机上进行文件系统和 shell 执行。没有隔离——仅在受控的开发环境中使用。请参阅下面的安全注意事项
复合(Composite)默认按线程作用域划分,/memories/ 跨线程持久化。Composite 后端具有最大的灵活性。你可以在文件系统中指定不同的路由,使其指向不同的后端。请参阅下面的 Composite 路由以获取可直接粘贴的示例。

内置后端

StateBackend

python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="google_genai:gemini-3.6-flash")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="openai:gpt-5.5")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="anthropic:claude-sonnet-4-6")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="openrouter:z-ai/glm-5.2")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="fireworks:accounts/fireworks/models/glm-5p2")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="baseten:zai-org/GLM-5.2")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend

# 默认我们提供 StateBackend
agent = create_deep_agent(model="ollama:north-mini-code-1.0")

# 本质上等价于以下写法
agent2 = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StateBackend(),
)
ts
import { createDeepAgent, StateBackend } from "deepagents";

// 默认我们提供 StateBackend
const agent = createDeepAgent();

// 本质上等价于以下写法
const agent2 = createDeepAgent({
  backend: new StateBackend(),
});

工作原理:

  • 通过 StateBackend 将文件存储在当前线程的 LangGraph 智能体状态中。
  • 通过检查点在同一个线程上的多次智能体轮次中持久化。文件不在线程之间共享。

WARNING

设计用于在图内使用。在图运行之外调用后端方法(例如,state_backend.upload_files(...))在图执行之前不会生效。

适用场景:

  • 作为智能体写入中间结果的草稿区。
  • 自动驱逐大型工具输出,智能体之后可以逐段读回这些输出。

请注意,该后端在监督智能体和子智能体之间共享,子智能体写入的任何文件都会保留在 LangGraph 智能体状态中, 即使该子智能体的执行已经完成。这些文件仍可继续供监督智能体和其他子智能体使用。

FilesystemBackend(本地磁盘)

FilesystemBackend 在可配置的根目录下读写真实文件。

WARNING

该后端授予智能体直接的文件系统读写访问权限。 请谨慎使用,并且只在合适的环境中使用。

合适的用例:

  • 本地开发 CLI(编码助手、开发工具)
  • CI/CD 流水线(请参阅下面的安全注意事项)

不合适的用例:

  • Web 服务器或 HTTP API——请改用 StateBackendStoreBackend沙箱后端

安全风险:

  • 智能体可以读取任何可访问的文件,包括机密信息(API 密钥、凭据、.env 文件)
  • 结合网络工具,机密信息可能通过 SSRF 攻击被窃取
  • 文件修改是永久且不可逆的

推荐的安全防护措施:

  1. 启用人在回路(HITL)中间件来审查敏感操作。

  2. 从可访问的文件系统路径中排除机密信息(尤其是在 CI/CD 中)。

  3. 对于需要文件系统交互的生产环境,使用沙箱后端

  4. 始终使用带 root_dirvirtual_mode=True 以启用基于路径的访问限制(阻止 ..~ 以及根目录之外的绝对路径)。

    请注意,默认值(virtual_mode=False)即使设置了 root_dir 也不提供任何安全保障。

python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="openai:gpt-5.5",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="openrouter:z-ai/glm-5.2",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="fireworks:accounts/fireworks/models/glm-5p2",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="baseten:zai-org/GLM-5.2",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    model="ollama:north-mini-code-1.0",
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "google-genai:gemini-3.6-flash",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "openai:gpt-5.5",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "anthropic:claude-sonnet-4-6",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "openrouter:openrouter:z-ai/glm-5.2",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "fireworks:accounts/fireworks/models/glm-5p2",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "baseten:zai-org/GLM-5.2",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
ts
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "ollama:north-mini-code-1.0",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});

工作原理:

  • 在可配置的 root_dir 下读写真实文件。
  • 你可以选择设置 virtual_mode=True 来对 root_dir 下的路径进行沙箱化和规范化。
  • 使用安全的路径解析,在可能时防止不安全的符号链接遍历,可以使用 ripgrep 实现快速的 grep

适用场景:

  • 你机器上的本地项目
  • CI 沙箱
  • 挂载的持久化卷

TIP

对于大多数用例,将 FilesystemBackend 包装在 CompositeBackend。Deep Agents 会自动将内部数据写入后端,包括卸载的大型工具结果(位于 /large_tool_results/ 下)和对话历史(位于 /conversation_history/ 下)。当你单独使用 FilesystemBackend 时,这些内部文件会被写入 root_dir 下的真实磁盘,将智能体产物与你的项目文件混在一起。

使用 CompositeBackend 将你的项目目录路由到 FilesystemBackend,同时将内部路径保留在临时的 StateBackend 存储中:

python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, FilesystemBackend

agent = create_deep_agent(
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/workspace/": FilesystemBackend(root_dir="/path/to/project", virtual_mode=True),
        },
    )
)
typescript
import { createDeepAgent, CompositeBackend, FilesystemBackend, StateBackend } from "deepagents";

const agent = createDeepAgent({
  backend: new CompositeBackend(
    new StateBackend(),
    {
      "/workspace/": new FilesystemBackend({ rootDir: "/path/to/project", virtualMode: true }),
    },
  ),
});

这样,智能体在 /workspace/ 下的读写会落到真实磁盘,而卸载的工具结果和其他内部数据则保留在临时状态中。请参阅将不同路径路由到不同后端以了解更多路由模式。

LocalShellBackend(本地 shell)

WARNING

该后端授予智能体直接的文件系统读写访问权限以及在你的主机上不受限制的 shell 执行权限。 请极其谨慎地使用,并且只在合适的环境中使用。

合适的用例:

  • 本地开发 CLI(编码助手、开发工具)
  • 你信任智能体代码的个人开发环境
  • 具有适当机密管理措施的 CI/CD 流水线

不合适的用例:

  • 生产环境(例如 Web 服务器、API、多租户系统)
  • 处理不受信任的用户输入或执行不受信任的代码

安全风险:

  • 智能体可以使用你的用户权限执行任意 shell 命令
  • 智能体可以读取任何可访问的文件,包括机密信息(API 密钥、凭据、.env 文件)
  • 机密信息可能被暴露
  • 文件修改和命令执行是永久且不可逆的
  • 命令直接在主机系统上运行
  • 命令可以无限消耗 CPU、内存和磁盘

推荐的安全防护措施:

  1. 启用人在回路(HITL)中间件,在执行前审查并批准操作。强烈建议这样做。
  2. 仅在专用的开发环境中运行。切勿在共享或生产系统上使用。
  3. 对于需要 shell 执行的生产环境,使用沙箱后端

注意: 启用 shell 访问后,virtual_mode=True 不提供任何安全保障,因为命令可以访问系统上的任何路径。

python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="openai:gpt-5.5",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="openrouter:z-ai/glm-5.2",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="fireworks:accounts/fireworks/models/glm-5p2",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="baseten:zai-org/GLM-5.2",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend

agent = create_deep_agent(
    model="ollama:north-mini-code-1.0",
    backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "google-genai:gemini-3.6-flash",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "openai:gpt-5.5",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "anthropic:claude-sonnet-4-6",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "openrouter:openrouter:z-ai/glm-5.2",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "fireworks:accounts/fireworks/models/glm-5p2",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "baseten:zai-org/GLM-5.2",
  backend,
});
ts
import { createDeepAgent, LocalShellBackend } from "deepagents";

const backend = new LocalShellBackend({ workingDirectory: "." });

const agent = createDeepAgent({
  model: "ollama:north-mini-code-1.0",
  backend,
});

工作原理:

  • 通过 execute 工具扩展 FilesystemBackend,用于在主机上运行 shell 命令。
  • 命令使用 subprocess.run(shell=True) 直接在你的机器上运行,且没有任何沙箱化。
  • 支持 timeout(默认 120 秒)、max_output_bytes(默认 100,000)以及用于环境变量的 envinherit_env
  • shell 命令使用 root_dir 作为工作目录,但可以访问系统上的任何路径。

适用场景:

  • 本地编码助手和开发工具
  • 在你信任智能体的情况下,开发期间的快速迭代

StoreBackend(LangGraph store)

python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="openai:gpt-5.5",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="openrouter:z-ai/glm-5.2",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="fireworks:accounts/fireworks/models/glm-5p2",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="baseten:zai-org/GLM-5.2",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
python
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="ollama:north-mini-code-1.0",
    backend=StoreBackend(
        namespace=lambda rt: (rt.server_info.user.identity,),
    ),
    store=InMemoryStore(),  # 适合本地开发;部署到 LangSmith 时请省略
)
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "google-genai:gemini-3.6-flash",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "openai:gpt-5.5",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "anthropic:claude-sonnet-4-6",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "openrouter:openrouter:z-ai/glm-5.2",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "fireworks:accounts/fireworks/models/glm-5p2",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "baseten:zai-org/GLM-5.2",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // 适合本地开发;部署到 LangSmith 时请省略

const agent = createDeepAgent({
  model: "ollama:north-mini-code-1.0",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});

INFO

部署到 LangSmith Deployment 时,请省略 store 参数。平台会自动为你的智能体配置一个 store。

TIP

namespace 参数控制数据隔离。对于多用户部署,始终设置命名空间工厂以按用户或租户隔离数据。

工作原理:

  • StoreBackend 将文件存储在运行时提供的 LangGraph BaseStore 中,从而实现跨线程的持久化存储。

适用场景:

  • 当你的运行时已经配置了 LangGraph store(例如,BaseStore 背后的 Redis、Postgres 或云实现)。
  • 当你通过 LangSmith Deployment 部署智能体时(系统会自动为你的智能体配置一个 store)。

命名空间工厂

命名空间工厂控制 StoreBackend 在何处读写数据。它接收一个 LangGraph Runtime,并返回一组用作 store 命名空间的字符串元组。使用命名空间工厂在用户、租户或助手之间隔离数据。

在构造 StoreBackend 时将命名空间工厂传递给 namespace 参数:

python
NamespaceFactory = Callable[[Runtime], tuple[str, ...]]

Runtime 提供:

  • rt.context —— 通过 LangGraph 的上下文模式提供的用户自定义上下文(例如,user_id
  • rt.server_info —— 在 LangGraph Server 上运行时与服务器相关的元数据(助手 ID、图 ID、已认证用户)
  • rt.execution_info —— 执行身份信息(线程 ID、运行 ID、检查点 ID)
  • rt.serverInfo —— 在 LangGraph Server 上运行时与服务器相关的元数据(助手 ID、图 ID、已认证用户)
  • rt.executionInfo —— 执行身份信息(线程 ID、运行 ID、检查点 ID)

INFO

Runtime 参数在 deepagents>=0.5.2 中可用。更早的 0.5.x 版本改为传递 BackendContext——请参阅下面的BackendContext 迁移rt.server_infort.execution_info 需要 deepagents>=0.5.0

INFO

Runtime 参数在 deepagents>=1.9.1 中可用。更早的 1.9.x 版本改为传递 BackendContext——请参阅下面的BackendContext 迁移rt.serverInfort.executionInfo 需要 deepagents>=1.9.0

常见的命名空间模式:

python
from deepagents.backends import StoreBackend

# 按用户划分:每个用户拥有自己独立的存储
backend = StoreBackend(
    namespace=lambda rt: (rt.server_info.user.identity,),  
)

# 按助手划分:同一助手的用户共享存储
backend = StoreBackend(
    namespace=lambda rt: (
        rt.server_info.assistant_id,  
    ),
)

# 按线程划分:存储限定在单个对话内
backend = StoreBackend(
    namespace=lambda rt: (
        rt.execution_info.thread_id,  
    ),
)
typescript
import { StoreBackend } from "deepagents";

// 按用户划分:每个用户拥有自己独立的存储
const backend = new StoreBackend({
  namespace: (rt) => [rt.serverInfo.user.identity],  
});

// 按助手划分:同一助手的用户共享存储
const backend = new StoreBackend({
  namespace: (rt) => [rt.serverInfo.assistantId],  
});

// 按线程划分:存储限定在单个对话内
const backend = new StoreBackend({
  namespace: (rt) => [rt.executionInfo.threadId],  
});

你可以组合多个组件来创建更具体的作用域——例如,使用 (user_id, thread_id) 实现按用户按对话的隔离,或者在同一个作用域使用多个 store 命名空间时附加 "filesystem" 之类的后缀以示区分。

命名空间组件只能包含字母数字字符、连字符、下划线、点号、@+、冒号和波浪号。通配符(*?)会被拒绝,以防止 glob 注入。

WARNING

namespace 参数在 v0.5.0 中将是必填的。对于新代码,始终显式设置它。

WARNING

namespace 参数在 v1.9.0 中将是必填的。对于新代码,始终显式设置它。

INFO

当未提供命名空间工厂时,旧版默认值使用 LangGraph 配置元数据中的 assistant_id。这意味着同一个助手的所有用户共享同一个存储。对于多用户上线生产,始终提供命名空间工厂。

ContextHubBackend

INFO

开始之前: ContextHubBackend 需要先在 LangSmith 中设置一个 Context Hub 仓库。如果你不熟悉智能体仓库和技能仓库,请先阅读 Context Hub 概念页面。

ContextHubBackend 将你的智能体文件系统存储在 LangSmith Context Hub 仓库中。它可以单独使用一个仓库,也可以使用一个链接到技能仓库的智能体仓库。

仓库结构: 在 Context Hub 中,_智能体仓库_保存智能体的顶层指令和配置(例如,AGENTS.mdtools.json)。它可以链接到一个或多个 技能仓库,每个技能仓库都打包为可复用的能力(例如,包含电子邮件格式或代码审查指令的 SKILL.md)。当你传入 ContextHubBackend("my-agent") 时,后端会将智能体仓库挂载到文件系统根目录;链接的技能仓库会以 /skills/ 下的子目录形式出现。

这意味着你的智能体上下文有意地分布在多个仓库中:每个智能体一个仓库,每个技能单独一个仓库。这种分离使得技能可以独立地进行版本管理、共享,并在多个智能体之间复用。如果这让你觉得过于碎片化,请参阅链接仓库了解其设计理由。

python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="openai:gpt-5.5",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="openrouter:z-ai/glm-5.2",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="fireworks:accounts/fireworks/models/glm-5p2",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="baseten:zai-org/GLM-5.2",
    backend=ContextHubBackend("my-agent"),
)
python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend

agent = create_deep_agent(
    model="ollama:north-mini-code-1.0",
    backend=ContextHubBackend("my-agent"),
)

使用 owner/namename 格式的仓库标识符来构造它。

INFO

在使用 ContextHubBackend 之前,请设置 LANGSMITH_API_KEY

工作原理:

  • 首次使用时惰性拉取 Hub 仓库树,之后从内存缓存中提供读取。
  • 将写入和编辑持久化为 Hub 提交,并在成功提交后更新缓存。
  • 使用乐观父提交写入(parent_commit):每次推送都针对最新的已知提交哈希。

行为与限制:

  • 如果仓库不存在,第一次拉取会视为空;第一次成功的写入可以创建该仓库。
  • 如果另一个写入者先推进了仓库,你过时的父提交写入可能会失败。发生冲突时请重新拉取并重试。
  • upload_files() 接受 UTF-8 文本。非 UTF-8 文件会按路径以 invalid_path 被拒绝。

适用场景:

  • 无需单独接线 LangGraph BaseStore 的 LangSmith 原生持久化文件系统。
  • 能从文件系统变更的 Hub 提交历史中受益的工作流。

CompositeBackend(路由器)

python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="openai:gpt-5.5",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="openrouter:z-ai/glm-5.2",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="fireworks:accounts/fireworks/models/glm-5p2",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="baseten:zai-org/GLM-5.2",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="ollama:north-mini-code-1.0",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
        },
    ),
    store=InMemoryStore(),  # Store 传给 create_deep_agent,而不是后端
)
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "google-genai:gemini-3.6-flash",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "openai:gpt-5.5",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "anthropic:claude-sonnet-4-6",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "openrouter:openrouter:z-ai/glm-5.2",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "fireworks:accounts/fireworks/models/glm-5p2",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "baseten:zai-org/GLM-5.2",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
ts
import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "ollama:north-mini-code-1.0",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});

工作原理:

  • CompositeBackend 根据路径前缀将文件操作路由到不同的后端。
  • 在列表和搜索结果中保留原始路径前缀。

适用场景:

  • 当你想同时为智能体提供线程作用域和跨线程存储时,CompositeBackend 允许你同时提供 StateBackendStoreBackend
  • 当你有多个信息源,并希望作为单个文件系统的一部分提供给智能体时。
    • 例如,你在某个 Store 中将长期记忆存储在 /memories/ 下,同时还有一个自定义后端,其中的文档可通过 /docs/ 访问。

指定后端

  • 将后端实例传递给 create_deep_agent(model=..., backend=...)。文件系统中间件会将其用于所有工具。

  • 后端必须实现 BackendProtocol(例如,StateBackend()FilesystemBackend(root_dir=".")StoreBackend()ContextHubBackend("my-agent"))。

  • 如果省略,默认是 StateBackend()

  • 将后端实例传递给 createDeepAgent({ backend: ... })。文件系统中间件会将其用于所有工具。

  • 后端必须实现 AnyBackendProtocolBackendProtocolV1BackendProtocolV2)——例如,new StateBackend()new FilesystemBackend({ rootDir: "." })new StoreBackend()

  • 如果省略,默认是 new StateBackend()

INFO

在 1.9.0 之前,只支持 BackendProtocol,即现在的 BackendProtocolV1。V1 后端会在运行时通过 adaptBackendProtocol() 自动适配为 V2。继续使用现有的 V1 后端无需更改代码。要升级到 v2,请参阅将现有后端升级到 v2

路由到不同后端

将命名空间的部分路径路由到不同的后端。通常用于在跨线程持久化 /memories/*,同时让其他所有内容保持线程作用域。

python
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, FilesystemBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": FilesystemBackend(root_dir="/deepagents/myagent", virtual_mode=True),
        },
    )
)
typescript
import { createDeepAgent, CompositeBackend, FilesystemBackend, StateBackend } from "deepagents";

const agent = createDeepAgent({
  backend: new CompositeBackend(
    new StateBackend(),
    {
      "/memories/": new FilesystemBackend({ rootDir: "/deepagents/myagent", virtualMode: true }),
    },
  ),
});

行为:

  • /workspace/plan.mdStateBackend(线程作用域)
  • /memories/agent.md/deepagents/myagent 下的 FilesystemBackend
  • lsglobgrep 聚合结果并显示原始路径前缀。

注意:

  • 较长的前缀优先(例如,路由 "/memories/projects/" 可以覆盖 "/memories/")。
  • 对于 StoreBackend 路由,请确保通过 create_deep_agent(model=..., store=...) 提供 store,或由平台配置。
  • Deep Agents 将内部数据(已卸载的工具结果、对话历史)写入默认后端。使用 StateBackend 作为默认后端,以保持这些产物为临时状态,并避免将它们写入磁盘或持久化存储。请参阅 FilesystemBackend 提示获取完整示例。

自定义后端

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

实现后端协议

子类化 BackendProtocol 并实现以下方法:

方法签名功能
ls(path: str) -> LsResult列出给定路径下的文件和目录。
read(file_path: str, offset: int, limit: int) -> ReadResult返回文件内容,可选择分页。
write(file_path: str, content: str) -> WriteResult创建或覆盖文件。
edit(file_path: str, old_string: str, new_string: str, replace_all: bool) -> EditResult在现有文件中进行查找替换。
glob(pattern: str, path: str | None) -> GlobResult返回与 glob 模式匹配的路径。
grep(pattern: str, path: str | None, glob: str | None) -> GrepResult在文件内容中搜索字面字符串。
delete(file_path: str) -> DeleteResult可选。删除一个文件,或递归地删除一个目录。如果后端不支持删除,该工具会在请求时自动从模型中隐藏。

要同时支持 execute 工具(运行 shell 命令),请改为实现 SandboxBackendProtocol,它用 execute 方法扩展了 BackendProtocol

始终返回带有 error 字段的结构化结果类型用于失败情况。不要抛出异常。

实现 BackendProtocolBackendProtocolV2)并提供以下方法:

方法签名功能
ls(path: string) => Promise<LsResult>列出给定路径下的文件和目录。
read(filePath: string, offset?, limit?) => Promise<ReadResult>返回文件内容,可选择分页。二进制文件返回带 mimeTypeUint8Array 内容。
readRaw(filePath: string) => Promise<ReadRawResult>返回原始 FileData(由框架内部使用)。
write(filePath: string, content: string) => Promise<WriteResult>创建或覆盖文件。
edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean) => Promise<EditResult>在现有文件中进行查找替换。
glob(pattern: string, path?: string) => Promise<GlobResult>返回与 glob 模式匹配的路径。
grep(pattern: string, path?, glob?) => Promise<GrepResult>在文件内容中搜索字面字符串。

要同时支持 execute 工具(运行 shell 命令),请改为实现 SandboxBackendProtocol,它用 execute 方法扩展了 BackendProtocolV2

所有方法都必须返回带有可选 error 字段的结构化 Result 对象——对于不存在的文件或无效的模式,不要抛出异常。

示例:S3 风格后端骨架

该骨架将文件系统路径映射为对象键。请使用你的存储客户端的列出、读取、搜索、上传和读-修改-写操作来填充每个方法。

python
from deepagents.backends.protocol import (
    BackendProtocol,
    EditResult,
    GlobResult,
    GrepResult,
    LsResult,
    ReadResult,
    WriteResult,
)

class S3Backend(BackendProtocol):
    def __init__(self, bucket: str, prefix: str = ""):
        self.bucket = bucket
        self.prefix = prefix.rstrip("/")

    def _key(self, path: str) -> str:
        return f"{self.prefix}{path}"

    def ls(self, path: str) -> LsResult:
        ...

    def read(self, file_path: str, offset: int = 0, limit: int = 2000) -> ReadResult:
        ...

    def grep(self, pattern: str, path: str | None = None, glob: str | None = None) -> GrepResult:
        ...

    def glob(self, pattern: str, path: str | None = None) -> GlobResult:
        ...

    def write(self, file_path: str, content: str) -> WriteResult:
        ...

    def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:
        ...
typescript
import {
  type BackendProtocolV2,
  type EditResult,
  type GlobResult,
  type GrepResult,
  type LsResult,
  type ReadRawResult,
  type ReadResult,
  type WriteResult,
} from "deepagents";

class S3Backend implements BackendProtocolV2 {
  constructor(private bucket: string, private prefix: string = "") {
    this.prefix = prefix.replace(/\/$/, "");
  }

  private key(path: string): string {
    return `${this.prefix}${path}`;
  }

  async ls(path: string): Promise<LsResult> {
    ...
  }

  async read(filePath: string, offset?: number, limit?: number): Promise<ReadResult> {
    ...
  }

  async readRaw(filePath: string): Promise<ReadRawResult> {
    ...
  }

  async grep(pattern: string, path?: string | null, glob?: string | null): Promise<GrepResult> {
    ...
  }

  async glob(pattern: string, path = "/"): Promise<GlobResult> {
    ...
  }

  async write(filePath: string, content: string): Promise<WriteResult> {
    ...
  }

  async edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): Promise<EditResult> {
    ...
  }
}

权限

使用权限以声明式方式控制智能体可以读取或写入哪些文件和目录。权限适用于内置文件系统工具,并在调用后端之前进行评估。

python
from deepagents import create_deep_agent, FilesystemPermission

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/policies/": StoreBackend(
                namespace=lambda rt: (rt.context.org_id,),
            ),
        },
    ),
    permissions=[
        FilesystemPermission(
            operations=["write"],
            paths=["/policies/**"],
            mode="deny",
        ),
    ],
)

有关完整选项(包括规则排序、子智能体权限和复合后端交互),请参阅权限指南

添加策略钩子

对于超出基于路径的允许/拒绝规则的自定义验证逻辑(速率限制、审计日志、内容检查),可以通过子类化或包装后端来强制实施企业规则。

阻止在选定前缀下进行写入/编辑(子类化):

python
from deepagents.backends.filesystem import FilesystemBackend
from deepagents.backends.protocol import WriteResult, EditResult

class GuardedBackend(FilesystemBackend):
    def __init__(self, *, deny_prefixes: list[str], **kwargs):
        super().__init__(**kwargs)
        self.deny_prefixes = [p if p.endswith("/") else p + "/" for p in deny_prefixes]

    def write(self, file_path: str, content: str) -> WriteResult:
        if any(file_path.startswith(p) for p in self.deny_prefixes):
            return WriteResult(error=f"Writes are not allowed under {file_path}")
        return super().write(file_path, content)

    def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:
        if any(file_path.startswith(p) for p in self.deny_prefixes):
            return EditResult(error=f"Edits are not allowed under {file_path}")
        return super().edit(file_path, old_string, new_string, replace_all)
typescript
import { FilesystemBackend, type WriteResult, type EditResult } from "deepagents";

class GuardedBackend extends FilesystemBackend {
  private denyPrefixes: string[];

  constructor({ denyPrefixes, ...options }: { denyPrefixes: string[]; rootDir?: string }) {
    super(options);
    this.denyPrefixes = denyPrefixes.map(p => p.endsWith("/") ? p : p + "/");
  }

  async write(filePath: string, content: string): Promise<WriteResult> {
    if (this.denyPrefixes.some(p => filePath.startsWith(p))) {
      return { error: `Writes are not allowed under ${filePath}` };
    }
    return super.write(filePath, content);
  }

  async edit(filePath: string, oldString: string, newString: string, replaceAll = false): Promise<EditResult> {
    if (this.denyPrefixes.some(p => filePath.startsWith(p))) {
      return { error: `Edits are not allowed under ${filePath}` };
    }
    return super.edit(filePath, oldString, newString, replaceAll);
  }
}

通用包装器(可与任何后端配合使用):

python
from deepagents.backends.protocol import (
    BackendProtocol, WriteResult, EditResult, LsResult, ReadResult, GrepResult, GlobResult,
)

class PolicyWrapper(BackendProtocol):
    def __init__(self, inner: BackendProtocol, deny_prefixes: list[str] | None = None):
        self.inner = inner
        self.deny_prefixes = [p if p.endswith("/") else p + "/" for p in (deny_prefixes or [])]

    def _deny(self, path: str) -> bool:
        return any(path.startswith(p) for p in self.deny_prefixes)

    def ls(self, path: str) -> LsResult:
        return self.inner.ls(path)

    def read(self, file_path: str, offset: int = 0, limit: int = 2000) -> ReadResult:
        return self.inner.read(file_path, offset=offset, limit=limit)
    def grep(self, pattern: str, path: str | None = None, glob: str | None = None) -> GrepResult:
        return self.inner.grep(pattern, path, glob)
    def glob(self, pattern: str, path: str | None = None) -> GlobResult:
        return self.inner.glob(pattern, path)
    def write(self, file_path: str, content: str) -> WriteResult:
        if self._deny(file_path):
            return WriteResult(error=f"Writes are not allowed under {file_path}")
        return self.inner.write(file_path, content)
    def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:
        if self._deny(file_path):
            return EditResult(error=f"Edits are not allowed under {file_path}")
        return self.inner.edit(file_path, old_string, new_string, replace_all)
typescript
import {
  type BackendProtocolV2,
  type LsResult,
  type ReadResult,
  type ReadRawResult,
  type GrepResult,
  type GlobResult,
  type WriteResult,
  type EditResult,
} from "deepagents";

class PolicyWrapper implements BackendProtocolV2 {
  private denyPrefixes: string[];

  constructor(private inner: BackendProtocolV2, denyPrefixes: string[] = []) {
    this.denyPrefixes = denyPrefixes.map(p => p.endsWith("/") ? p : p + "/");
  }

  private isDenied(path: string): boolean {
    return this.denyPrefixes.some(p => path.startsWith(p));
  }

  ls(path: string): Promise<LsResult> { return this.inner.ls(path); }
  read(filePath: string, offset?: number, limit?: number): Promise<ReadResult> { return this.inner.read(filePath, offset, limit); }
  readRaw(filePath: string): Promise<ReadRawResult> { return this.inner.readRaw(filePath); }
  grep(pattern: string, path?: string | null, glob?: string | null): Promise<GrepResult> { return this.inner.grep(pattern, path, glob); }
  glob(pattern: string, path?: string): Promise<GlobResult> { return this.inner.glob(pattern, path); }

  async write(filePath: string, content: string): Promise<WriteResult> {
    if (this.isDenied(filePath)) return { error: `Writes are not allowed under ${filePath}` };
    return this.inner.write(filePath, content);
  }

  async edit(filePath: string, oldString: string, newString: string, replaceAll = false): Promise<EditResult> {
    if (this.isDenied(filePath)) return { error: `Edits are not allowed under ${filePath}` };
    return this.inner.edit(filePath, oldString, newString, replaceAll);
  }
}

多模态和二进制文件

INFO

多模态文件支持(PDF、音频、视频)需要 deepagents>=1.9.0

V2 后端原生支持二进制文件。当 read() 遇到二进制文件(根据文件扩展名确定 MIME 类型)时,它会返回包含 Uint8Array 内容和相应 mimeTypeReadResult。文本文件返回 string 内容。

支持的 MIME 类型

类别扩展名MIME 类型
图片.png, .jpg/.jpeg, .gif, .webp, .svg, .heic, .heifimage/png, image/jpeg, image/gif, image/webp, image/svg+xml, image/heic, image/heif
音频.mp3, .wav, .aiff, .aac, .ogg, .flacaudio/mpeg, audio/wav, audio/aiff, audio/aac, audio/ogg, audio/flac
视频.mp4, .webm, .mpeg/.mpg, .mov, .avi, .flv, .wmv, .3gppvideo/mp4, video/webm, video/mpeg, video/quicktime, video/x-msvideo, video/x-flv, video/x-ms-wmv, video/3gpp
文档.pdf, .ppt, .pptxapplication/pdf, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation
文本.txt, .html, .json, .js, .ts, .pytext/plain, text/html, application/json

读取二进制文件

typescript
const result = await backend.read("/workspace/screenshot.png");

if (result.error) {
  console.error(result.error);
} else if (result.content instanceof Uint8Array) {
  // 二进制文件——content 为 Uint8Array,mimeType 已设置
  console.log(`Binary file: ${result.mimeType}`); // "image/png"
} else {
  // 文本文件——content 为 string
  console.log(`Text file: ${result.mimeType}`); // "text/plain"
}

FileData 格式

FileData 是用于在状态和存储后端中存储文件内容的类型。

typescript
type FileData =
  // 当前格式(v2)
  | {
      content: string | Uint8Array; // 文本为 string,二进制为 Uint8Array
      mimeType: string;             // 例如 "text/plain"、"image/png"
      created_at: string;           // ISO 8601 时间戳
      modified_at: string;          // ISO 8601 时间戳
    }
  // 旧版格式(v1)
  | {
      content: string[];            // 行数组
      created_at: string;           // ISO 8601 时间戳
      modified_at: string;          // ISO 8601 时间戳
    };

后端在从状态或存储读取时可能会遇到两种格式中的任何一种。框架会透明地处理两者。新写入默认采用 v2 格式。在滚动部署期间,当旧的读取方需要旧版格式时,请向后端构造函数传递 fileFormat: "v1"(例如,new StoreBackend({ fileFormat: "v1" }))。

从后端工厂迁移

WARNING

后端工厂模式从 deepagents 0.5.0 开始已弃用。请直接传递预先构造好的后端实例,而不是工厂函数。 后端工厂模式从 deepagents 1.9.0 开始已弃用。请直接传递预先构造好的后端实例,而不是工厂函数。

以前,StateBackendStoreBackend 等后端需要一个接收运行时对象的工厂函数,因为它们需要运行时上下文(状态、存储)才能运行。现在,后端通过 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=...)
WriteResultEditResult 上的 files_update 字段状态写入现在由后端在内部处理
中间件写入/编辑工具中的 Command 包装工具返回纯字符串;无需 Command(update=...)
已弃用替代方案
BackendFactory 类型直接传递后端实例
BackendRuntime 接口后端在内部解析上下文
StateBackend(runtime, options?) 构造函数重载new StateBackend(options?)
StoreBackend(stateAndStore, options?) 构造函数重载new StoreBackend(options?)
WriteResultEditResult 上的 filesUpdate 字段状态写入现在由后端在内部处理

INFO

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

迁移示例

python
# 之前(已弃用)
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=lambda rt: CompositeBackend(
        default=StateBackend(rt),
        routes={"/memories/": StoreBackend(rt, namespace=lambda rt: (rt.server_info.user.identity,))},
    ),
)

# 之后
agent = create_deep_agent(
    model="google_genai:gemini-3.6-flash",
    backend=CompositeBackend(
        default=StateBackend(),
        routes={"/memories/": StoreBackend(namespace=lambda rt: (rt.server_info.user.identity,))},
    ),
)
typescript
// 之前(已弃用)
import { createDeepAgent, CompositeBackend, StateBackend, StoreBackend } from "deepagents";

const agent = createDeepAgent({
  backend: (config) => new CompositeBackend(
    new StateBackend(config),
    { "/memories/": new StoreBackend(config, {
      namespace: (rt) => [rt.serverInfo.user.identity],
    }) },
  ),
});

// 之后
const agent = createDeepAgent({
  backend: new CompositeBackend(
    new StateBackend(),
    { "/memories/": new StoreBackend({
      namespace: (rt) => [rt.serverInfo.user.identity],
    }) },
  ),
});

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 没有直接的替代品。命名空间信息在运行的生命周期内应是只读且稳定的,而状态是可变的并且会逐步变化——基于它推导命名空间可能会导致数据落入不一致的键下。如果你有需要读取智能体状态的用例,请提交一个问题
python
# 之前(已弃用,已在 v0.7 移除)
StoreBackend(
    namespace=lambda ctx: (ctx.runtime.context.user_id,),  
)

# 之后
StoreBackend(
    namespace=lambda rt: (rt.server_info.user.identity,),  
)
typescript
// 之前(已弃用,已在 v0.7 移除)
new StoreBackend({
  namespace: (ctx) => [ctx.runtime.context.userId],  
});

// 之后
new StoreBackend({
  namespace: (rt) => [rt.serverInfo.user.identity],  
});

协议参考

后端必须实现 BackendProtocol

必需方法:

  • ls(path: str) -> LsResult
    • 返回至少包含 path 的条目。可用时包含 is_dirsizemodified_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) —— 成功时 entrieslist[FileInfo],失败时为 None
  • ReadResult(error, file_data) —— 成功时 file_dataFileData 字典,失败时为 None
  • GrepResult(error, matches) —— 成功时 matcheslist[GrepMatch],失败时为 None
  • GlobResult(error, matches) —— 成功时 matcheslist[FileInfo],失败时为 None
  • WriteResult(error, path, files_update)
  • EditResult(error, path, files_update, occurrences)
  • FileInfo 字段:path(必填),可选 is_dirsizemodified_at
  • GrepMatch 字段:pathlinetext
  • FileData 字段:content(str)、encoding"utf-8""base64")、created_atmodified_at

后端实现 BackendProtocolV2。所有查询方法都返回结构化 Result 对象,格式为 { error?: string, ...data }

必需方法

  • ls(path: string) → LsResult

    • 列出指定目录中的文件和目录(非递归)。目录的路径以 / 结尾且 is_dir=true。可用时包含 is_dirsizemodified_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[] —— 下载多个文件(用于沙箱后端)。

结果类型

类型成功字段错误字段
ReadResultcontent?: string | Uint8Array, mimeType?: stringerror
ReadRawResultdata?: FileDataerror
LsResultfiles?: FileInfo[]error
GlobResultfiles?: FileInfo[]error
GrepResultmatches?: GrepMatch[]error
WriteResultpath?: stringerror
EditResultpath?: string, occurrences?: numbererror

支持的类型

  • FileInfo —— path(必填),可选 is_dirsizemodified_at
  • GrepMatch —— pathline(从 1 开始)、text
  • FileData —— 带时间戳的文件内容。请参阅 FileData 格式

沙箱扩展

SandboxBackendProtocolV2 用以下内容扩展 BackendProtocolV2

  • execute(command: string) → ExecuteResponse —— 在沙箱中运行 shell 命令。
  • readonly id: string —— 沙箱实例的唯一标识符。

将现有后端升级到 V2

迁移指南

方法重命名

V1 方法V2 方法返回类型变化
lsInfo(path)ls(path)FileInfo[]LsResult
read(filePath, offset, limit)read(filePath, offset, limit)stringReadResult
readRaw(filePath)readRaw(filePath)FileDataReadRawResult
grepRaw(pattern, path, glob)grep(pattern, path, glob)GrepMatch[] | stringGrepResult
globInfo(pattern, path)glob(pattern, path)FileInfo[]GlobResult
write(...)write(...)不变(WriteResult
edit(...)edit(...)不变(EditResult

类型重命名

V1 类型V2 类型
BackendProtocolBackendProtocolV2
SandboxBackendProtocolSandboxBackendProtocolV2

适配工具

如果你有需要与仅 V2 代码一起使用的现有 V1 后端,可以使用适配函数:

typescript
import { adaptBackendProtocol, adaptSandboxProtocol } from "deepagents";

// 将 V1 后端适配为 V2
const v2Backend = adaptBackendProtocol(v1Backend);

// 将 V1 沙箱适配为 V2
const v2Sandbox = adaptSandboxProtocol(v1Sandbox);

INFO

框架会自动适配传递给 createDeepAgent() 的 V1 后端。只有在直接调用协议方法时才需要手动适配。