Deep Agents 通过 lsread_filewrite_fileedit_fileglobgrep 等工具向 agent 暴露 filesystem surface。这些工具通过可插拔 backend 运行。read_file 工具在所有 backends 中原生支持图片文件(.png.jpg.jpeg.gif.webp),并将它们作为 multimodal content blocks 返回。 read_file 工具在所有 backends 中原生支持 binary files(图片、PDF、音频、视频),并返回带有 typed contentmimeTypeReadResult Sandboxes 和 LocalShellBackend 也提供 execute 工具。 本页说明如何:
部署到 LangSmith Deployment 时,store 会自动 provision。使用 LangSmith tracing 调试文件路径、权限拒绝和跨 thread storage。按照可观测性快速入门完成设置。建议同时设置 LangSmith Engine,它会监控 traces、检测问题并提出修复建议。

快速开始

下面是一些预构建 filesystem backends,可快速用于 deep agent:
内置 backend描述
Defaultagent = create_deep_agent(model="google_genai:gemini-3.5-flash")
限定在 thread 范围内。Agent 的默认 filesystem backend 存储在 langgraph state 中。文件会在同一 thread 的多轮对话中持久存在(通过 checkpointer),但不会跨 threads 共享。
Local filesystem persistenceagent = create_deep_agent(model="google_genai:gemini-3.5-flash", backend=FilesystemBackend(root_dir="/Users/nh/Desktop/"))
这会让 deep agent 访问本地机器的 filesystem。你可以指定 agent 可以访问的根目录。注意,任何提供的 root_dir 都必须是绝对路径。通常应包裹在 CompositeBackend 中,以便将内部 agent 数据(offloaded tool results、conversation history)与项目文件分开。
Durable store (LangGraph store)agent = create_deep_agent(model="google_genai:gemini-3.5-flash", backend=StoreBackend())
这会让 agent 访问_跨 threads 持久化_的长期存储。它适合存储适用于 agent 多次执行的较长期 memory 或 instructions。
Context Hubagent = create_deep_agent(model="google_genai:gemini-3.5-flash", backend=ContextHubBackend("my-agent"))
将文件持久存储在 LangSmith Hub repo 中,无需 provision 单独的 LangGraph store。
Sandboxagent = create_deep_agent(model="google_genai:gemini-3.5-flash", backend=sandbox)
在隔离环境中执行代码。Sandboxes 提供 filesystem tools,以及用于运行 shell 命令的 execute 工具。可以选择 Modal、Daytona、Deno 或 local VFS。
Local shellagent = create_deep_agent(model="google_genai:gemini-3.5-flash", backend=LocalShellBackend(root_dir=".", env={"PATH": "/usr/bin:/bin"}))
直接在 host 上提供 filesystem 和 shell execution。没有隔离,只能在受控开发环境中使用。请参阅下方安全注意事项
Composite默认限定在 thread 范围内,/memories/ 跨 threads 持久化。Composite backend 最灵活。你可以指定 filesystem 中不同 routes 指向不同 backends。可直接复制的示例见下方 Composite routing。

内置 backends

StateBackend

import { createDeepAgent, StateBackend } from "deepagents";

// By default we provide a StateBackend
const agent = createDeepAgent();

// Under the hood, it looks like
const agent2 = createDeepAgent({
  backend: new StateBackend(),
});
工作方式:
  • 通过 StateBackend 将文件存储在当前 thread 的 LangGraph agent state 中。
  • 通过 checkpoints 在同一 thread 的多个 agent turns 中持久存在。文件不会跨 threads 共享。
设计上应在 graph 内使用。在 graph run 外调用 backend methods(例如 state_backend.upload_files(...))不会生效,直到 graph 执行。
最适合:
  • 作为 agent 写入中间结果的 scratch pad。
  • 自动驱逐大型 tool outputs,随后 agent 可以分块读回。
注意,此 backend 由 supervisor agent 和 subagents 共享,subagent 写入的任何文件都会保留在 LangGraph agent state 中,即使该 subagent 执行完成也是如此。这些文件会继续对 supervisor agent 和其他 subagents 可用。

FilesystemBackend(local disk)

FilesystemBackend 会在可配置的 root directory 下读取和写入真实文件。
此 backend 会授予 agents 直接 filesystem 读写访问权限。 请谨慎使用,并且只在适当环境中使用。适合的用例:
  • 本地开发 CLIs(coding assistants、development tools)
  • CI/CD pipelines(请参阅下方安全注意事项)
不适合的用例:
  • Web servers 或 HTTP APIs,请改用 StateBackendStoreBackendsandbox backend
安全风险:
  • Agents 可以读取任何可访问文件,包括 secrets(API keys、credentials、.env files)
  • 如果与 network tools 结合,secrets 可能通过 SSRF attacks 外泄
  • 文件修改是永久且不可逆的
推荐防护:
  1. 启用 Human-in-the-Loop (HITL) middleware 以审查敏感操作。
  2. 从可访问 filesystem paths 中排除 secrets,尤其是在 CI/CD 中。
  3. 在需要 filesystem 交互的生产环境中使用 sandbox backend
  4. 使用 root_dir 时,始终启用 virtual_mode=True,以启用基于路径的访问限制(阻止 ..~ 和 root 外的 absolute paths)。 注意,默认值(virtual_mode=False)即使设置了 root_dir 也不提供安全性。
import { createDeepAgent, FilesystemBackend } from "deepagents";

const agent = createDeepAgent({
  model: "google-genai:gemini-3.5-flash",
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
工作方式:
  • 在可配置的 root_dir 下读取/写入真实文件。
  • 可以选择设置 virtual_mode=True,在 root_dir 下 sandbox 并 normalize paths。
  • 使用安全路径解析,尽可能防止不安全 symlink traversal,并可使用 ripgrep 进行快速 grep
最适合:
  • 本机上的本地项目
  • CI sandboxes
  • Mounted persistent volumes
大多数用例都应将 FilesystemBackend 包裹在 CompositeBackend 中。 Deep Agents 会自动向 backend 写入内部数据,包括 offloaded large tool results(位于 /large_tool_results/ 下)和 conversation history(位于 /conversation_history/ 下)。单独使用 FilesystemBackend 时,这些内部文件会写入 root_dir 下的真实磁盘,把 agent artifacts 与项目文件混在一起。使用 CompositeBackend 可以将项目目录 route 到 FilesystemBackend,同时让内部路径保留在临时 StateBackend storage 中:
import { createDeepAgent, CompositeBackend, FilesystemBackend, StateBackend } from "deepagents";

const agent = createDeepAgent({
  backend: new CompositeBackend(
    new StateBackend(),
    {
      "/workspace/": new FilesystemBackend({ rootDir: "/path/to/project", virtualMode: true }),
    },
  ),
});
这样,agent 在 /workspace/ 下的读写会进入真实磁盘,而 offloaded tool results 和其他内部数据会留在临时 state 中。更多 routing 模式请参阅Route to different backends

LocalShellBackend(local shell)

此 backend 会授予 agents 直接 filesystem 读写访问权限,并且在 host 上执行不受限制的 shell commands。 请极其谨慎使用,并且只在适当环境中使用。适合的用例:
  • 本地开发 CLIs(coding assistants、development tools)
  • 你信任 agent 代码的个人开发环境
  • 具有正确 secret management 的 CI/CD pipelines
不适合的用例:
  • 生产环境,例如 web servers、APIs、multi-tenant systems
  • 处理不受信任的用户输入或执行不受信任代码
安全风险:
  • Agents 可以用你的用户权限执行任意 shell commands
  • Agents 可以读取任何可访问文件,包括 secrets(API keys、credentials、.env files)
  • Secrets 可能被暴露
  • 文件修改和命令执行是永久且不可逆的
  • 命令直接在 host system 上运行
  • 命令可能消耗无限 CPU、memory 和 disk
推荐防护:
  1. 启用 Human-in-the-Loop (HITL) middleware,在执行前审查并批准操作。强烈推荐这样做。
  2. 只在专用开发环境中运行。不要在共享或生产系统上使用。
  3. 对于需要 shell execution 的生产环境,请使用 sandbox backend
注意: 启用 shell access 时,virtual_mode=True 不提供安全性,因为命令可以访问系统上的任何路径。
import { createDeepAgent, LocalShellBackend } from "deepagents";

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

const agent = createDeepAgent({
  model: "google-genai:gemini-3.5-flash",
  backend,
});
工作方式:
  • 使用 execute 工具扩展 FilesystemBackend,用于在 host 上运行 shell commands。
  • 命令直接在你的机器上通过 subprocess.run(shell=True) 运行,没有 sandboxing。
  • 支持 timeout(默认 120s)、max_output_bytes(默认 100,000)、envinherit_env 环境变量。
  • Shell commands 使用 root_dir 作为工作目录,但可以访问系统上的任何路径。
最适合:
  • 本地 coding assistants 和 development tools
  • 你信任 agent 时,在开发期间快速迭代

StoreBackend(LangGraph store)

import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore(); // Good for local dev; omit for LangSmith Deployment

const agent = createDeepAgent({
  model: "google-genai:gemini-3.5-flash",
  backend: new StoreBackend({
    namespace: (rt) => [rt.serverInfo.user.identity],
  }),
  store,
});
部署到 LangSmith Deployment 时,请省略 store 参数。平台会自动为 agent provision store。
namespace 参数控制数据隔离。对于多用户部署,请始终设置 namespace factory,按用户或 tenant 隔离数据。
工作方式:
  • StoreBackend 将文件存储在运行时提供的 LangGraph BaseStore 中,启用跨 thread durable storage。
最适合:
  • 已经使用配置好的 LangGraph store 时,例如 BaseStore 背后的 Redis、Postgres 或 cloud implementations。
  • 通过 LangSmith Deployment 部署 agent 时,平台会自动为 agent provision store。

Namespace factories

Namespace factory 控制 StoreBackend 在何处读写数据。它接收 LangGraph Runtime,并返回作为 store namespace 的字符串 tuple。使用 namespace factories 在 users、tenants 或 assistants 之间隔离数据。 构造 StoreBackend 时,将 namespace factory 传给 namespace 参数:
NamespaceFactory = Callable[[Runtime], tuple[str, ...]]
Runtime 提供:
  • rt.context,通过 LangGraph context schema 传入的用户提供上下文,例如 user_id
  • rt.serverInfo,在 LangGraph Server 上运行时的 server-specific metadata(assistant ID、graph ID、authenticated user)
  • rt.executionInfo,execution identity information(thread ID、run ID、checkpoint ID)
Runtime 参数可在 deepagents>=1.9.1 中使用。更早的 1.9.x releases 会传入 BackendContext,请参阅下方BackendContext 迁移rt.serverInfort.executionInfo 需要 deepagents>=1.9.0
常见 namespace 模式:
import { StoreBackend } from "deepagents";

// Per-user: each user gets their own isolated storage
const backend = new StoreBackend({
  namespace: (rt) => [rt.serverInfo.user.identity],
});

// Per-assistant: all users of the same assistant share storage
const backend = new StoreBackend({
  namespace: (rt) => [rt.serverInfo.assistantId],
});

// Per-thread: storage scoped to a single conversation
const backend = new StoreBackend({
  namespace: (rt) => [rt.executionInfo.threadId],
});
你可以组合多个组件来创建更具体的 scopes,例如 (user_id, thread_id) 用于每用户每对话隔离,或追加 "filesystem" 等 suffix,以便在同一 scope 使用多个 store namespaces 时消除歧义。 Namespace 组件只能包含字母数字字符、hyphens、underscores、dots、@+、colons 和 tildes。通配符(*?)会被拒绝,以防止 glob injection。
namespace 参数将在 v1.9.0 中必需。新代码请始终显式设置它。
没有提供 namespace factory 时,legacy default 会使用 LangGraph config metadata 中的 assistant_id。这意味着同一 assistant 的所有用户共享同一 storage。对于多用户生产部署,请始终提供 namespace factory。

ContextHubBackend

ContextHubBackend 将文件存储在 LangSmith Hub repo 中。使用 owner/namename 格式的 repo identifier 构造它。
使用 ContextHubBackend 前,请设置 LANGSMITH_API_KEY
工作方式:
  • 首次使用时惰性 pull Hub repo tree,然后从 in-memory cache 提供 reads。
  • 将 writes 和 edits 作为 Hub commits 持久化,并在成功 commit 后更新 cache。
  • 使用 optimistic parent-commit writes(parent_commit):每次 push 都以最新已知 commit hash 为目标。
行为和限制:
  • 如果 repo 不存在,第一次 pull 会被视为空;第一次成功 write 可以创建 repo。
  • 如果另一个 writer 先推进了 repo,你的 stale parent-commit write 可能失败。冲突时请重新 pull 并重试。
  • upload_files() 接受 UTF-8 文本。Non-UTF-8 files 会按路径以 invalid_path 拒绝。
最适合:
  • 不单独连接 LangGraph BaseStore,同时使用 LangSmith-native durable filesystem persistence。
  • 受益于 filesystem changes 的 Hub commit history 的 workflows。

CompositeBackend(router)

import {
  createDeepAgent,
  CompositeBackend,
  StateBackend,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = createDeepAgent({
  model: "google-genai:gemini-3.5-flash",
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: () => ["memories"],
    }),
  }),
  store,
});
工作方式:
  • CompositeBackend 基于 path prefix 将 file operations route 到不同 backends。
  • 在 listings 和 search results 中保留原始 path prefixes。
最适合:
  • 想同时为 agent 提供 thread-scoped 和 cross-thread storage 时,CompositeBackend 允许同时提供 StateBackendStoreBackend
  • 想把多个信息来源作为单个 filesystem 的一部分提供给 agent 时。
    • 例如,你在一个 Store 的 /memories/ 下存储长期 memories,同时还有一个自定义 backend 在 /docs/ 下提供文档访问。

指定 backend

  • 将 backend 实例传给 createDeepAgent({ backend: ... })。Filesystem middleware 会将它用于所有 tooling。
  • Backend 必须实现 AnyBackendProtocolBackendProtocolV1BackendProtocolV2),例如 new StateBackend()new FilesystemBackend({ rootDir: "." })new StoreBackend()
  • 如果省略,默认值为 new StateBackend()
1.9.0 之前只支持 BackendProtocol,现在称为 BackendProtocolV1。V1 backends 会在运行时通过 adaptBackendProtocol() 自动适配到 V2。继续使用现有 V1 backends 不需要修改代码。要更新到 v2,请参阅将现有 backends 更新到 v2

Route 到不同 backends

将 namespace 的不同部分 route 到不同 backends。常见用法是跨 threads 持久化 /memories/*,并让其他所有内容限定在 thread 范围内。
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(thread-scoped)
  • /memories/agent.md/deepagents/myagent 下的 FilesystemBackend
  • lsglobgrep 会聚合结果,并显示原始 path prefixes。
注意:
  • 更长 prefix 优先,例如 route "/memories/projects/" 可以覆盖 "/memories/"
  • 对于 StoreBackend routing,请确保通过 create_deep_agent(model=..., store=...) 提供 store,或由平台 provision store。
  • Deep Agents 会将内部数据(offloaded tool results、conversation history)写入默认 backend。使用 StateBackend 作为默认 backend,可以让这些 artifacts 保持临时状态,并避免写入磁盘或持久 store。完整示例请参阅 FilesystemBackend tip

使用虚拟文件系统

构建自定义 backend,将远程或数据库 filesystem(例如 S3 或 Postgres)投射到 tools namespace 中。 设计指南:
  • Paths 是 absolute(/x/y.txt)。决定如何将它们映射到 storage keys/rows。
  • 高效实现 lsglob,可用时使用 server-side filtering,否则使用 local filter。
  • 对于外部持久化(S3、Postgres 等),在 write/edit results 中返回 files_update=None(Python)或省略 filesUpdate(JS)。只有 in-memory state backends 需要返回 files update dict。
  • 使用 lsglob 作为 method names。
  • 所有 query methods(lsreadreadRawgrepglob)都必须返回带有可选 error 字段的结构化 Result objects,例如 LsResultReadResult
  • read() 中支持 binary files,返回带有适当 mimeTypeUint8Array content。
S3-style outline:
import {
  type BackendProtocolV2,
  type LsResult,
  type ReadResult,
  type ReadRawResult,
  type GrepResult,
  type GlobResult,
  type WriteResult,
  type EditResult,
} 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> {
    // List objects under key(path); return { files: [...] }
    ...
  }

  async read(filePath: string, offset?: number, limit?: number): Promise<ReadResult> {
    // Fetch object; return { content, mimeType }
    // For binary files, return Uint8Array content
    ...
  }

  async readRaw(filePath: string): Promise<ReadRawResult> {
    // Return { data: FileData }
    ...
  }

  async grep(pattern: string, path?: string | null, glob?: string | null): Promise<GrepResult> {
    // Search text files; skip binary; return { matches: [...] }
    ...
  }

  async glob(pattern: string, path = "/"): Promise<GlobResult> {
    // Apply glob relative to path; return { files: [...] }
    ...
  }

  async write(filePath: string, content: string): Promise<WriteResult> {
    // Enforce create-only semantics; return { path: filePath, filesUpdate: null }
    ...
  }

  async edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): Promise<EditResult> {
    // Read → replace → write → return { path, occurrences }
    ...
  }
}
Postgres-style outline:
  • Table files(path text primary key, content text, mime_type text, created_at timestamptz, modified_at timestamptz)
  • 将 tool operations 映射到 SQL:
    • ls 使用 WHERE path LIKE $1 || '%' → 返回 LsResult
    • glob 在 SQL 中过滤,或 fetch 后本地应用 glob → 返回 GlobResult
    • grep 可以按 extension 或 last modified time fetch candidate rows,然后扫描 lines(跳过 mime_type 为 binary 的 rows)→ 返回 GrepResult

Permissions

使用 permissions 以声明方式控制 agent 可以读取或写入哪些 files 和 directories。Permissions 会应用于内置 filesystem tools,并在调用 backend 之前评估。 完整选项,包括 rule ordering、subagent permissions 和 composite backend interactions,请参阅 permissions guide

添加 policy hooks

对于 path-based allow/deny rules 之外的自定义验证逻辑,例如 rate limiting、audit logging、content inspection,可以通过继承或包裹 backend 来强制执行企业规则。 在选定 prefixes 下阻止 writes/edits(subclass):
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);
  }
}
Generic wrapper(适用于任何 backend):
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);
  }
}

Multimodal 和 binary files

Multi-modal file support(PDFs、audio、video)需要 deepagents>=1.9.0
V2 backends 原生支持 binary files。当 read() 遇到 binary file(由文件扩展名推断 MIME type)时,会返回带有 Uint8Array content 和相应 mimeTypeReadResult。Text files 返回 string content。

支持的 MIME types

类别扩展名MIME types
Images.png, .jpg/.jpeg, .gif, .webp, .svg, .heic, .heifimage/png, image/jpeg, image/gif, image/webp, image/svg+xml, image/heic, image/heif
Audio.mp3, .wav, .aiff, .aac, .ogg, .flacaudio/mpeg, audio/wav, audio/aiff, audio/aac, audio/ogg, audio/flac
Video.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
Documents.pdf, .ppt, .pptxapplication/pdf, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation
Text.txt, .html, .json, .js, .ts, .pytext/plain, text/html, application/json

读取 binary files

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

if (result.error) {
  console.error(result.error);
} else if (result.content instanceof Uint8Array) {
  // Binary file — content is Uint8Array, mimeType is set
  console.log(`Binary file: ${result.mimeType}`); // "image/png"
} else {
  // Text file — content is string
  console.log(`Text file: ${result.mimeType}`); // "text/plain"
}

FileData format

FileData 是用于在 state 和 store backends 中存储文件内容的类型。
type FileData =
  // Current format (v2)
  | {
      content: string | Uint8Array; // string for text, Uint8Array for binary
      mimeType: string;             // e.g. "text/plain", "image/png"
      created_at: string;           // ISO 8601 timestamp
      modified_at: string;          // ISO 8601 timestamp
    }
  // Legacy format (v1)
  | {
      content: string[];            // array of lines
      created_at: string;           // ISO 8601 timestamp
      modified_at: string;          // ISO 8601 timestamp
    };
Backends 从 state 或 store 读取时可能遇到任一格式。Framework 会透明处理两者。新的 writes 默认使用 v2 格式。在 rolling deployments 中,如果较旧 readers 需要 legacy format,请将 fileFormat: "v1" 传给 backend constructor,例如 new StoreBackend({ fileFormat: "v1" })

从 backend factories 迁移

Backend factory pattern 自 deepagents 1.9.0 起已弃用。请直接传入预构造 backend instances,而不是 factory functions。
以前,StateBackendStoreBackend 等 backends 需要接收 runtime object 的 factory function,因为它们需要 runtime context(state、store)才能运行。Backends 现在会通过 LangGraph 的 get_config()get_store()get_runtime() helpers 在内部解析此上下文,因此你可以直接传入 instances。

发生了什么变化

Before(deprecated)After
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()

Deprecated APIs

DeprecatedReplacement
BackendFactory type直接传入 backend instance
BackendRuntime interfaceBackends 在内部解析 context
StateBackend(runtime, options?) constructor overloadnew StateBackend(options?)
StoreBackend(stateAndStore, options?) constructor overloadnew StoreBackend(options?)
WriteResultEditResult 上的 filesUpdate 字段State writes 现在由 backend 内部处理
Factory pattern 运行时仍可工作,并会发出 deprecation warning。请在下一个 major version 前更新代码,改用 direct instances。

Migration example

// Before (deprecated)
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],
    }) },
  ),
});

// After
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)中,namespace factories 会直接接收 LangGraph Runtime,而不是 BackendContext wrapper。旧的 BackendContext 形式仍会通过 backwards-compatible .runtime.state accessors 工作,但这些 accessors 会发出 deprecation warning,并将在 deepagents>=0.7 中移除。 发生了什么变化:
  • Factory argument 现在是 Runtime,不是 BackendContext
  • 移除 .runtime accessor,例如 ctx.runtime.context.user_id 变为 rt.server_info.user.identity
  • ctx.state 没有直接替代项。Namespace info 应是 read-only,并在一次 run 的生命周期内保持稳定,而 state 是可变的且逐步变化。从 state 派生 namespace 可能导致数据进入不一致的 keys。如果你有需要读取 agent state 的用例,请打开 issue
// Before (deprecated, removed in v0.7)
new StoreBackend({
  namespace: (ctx) => [ctx.runtime.context.userId],
});

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

Protocol reference

Backends 实现 BackendProtocolV2。所有 query methods 都返回带有 { error?: string, ...data } 的结构化 Result objects。

Required methods

  • ls(path: string) → LsResult
    • 列出指定 directory 中的 files 和 directories(non-recursive)。Directories 的 path 末尾带 /,并且 is_dir=true。可用时包含 is_dirsizemodified_at
  • read(filePath: string, offset?: number, limit?: number) → ReadResult
    • 读取 file content。对于 text files,content 按 line offset/limit 分页(默认 offset 0、limit 500)。对于 binary files,会返回完整 raw Uint8Array content,并设置 mimeType 字段。缺失文件时,返回 { error: "File '/x' not found" }
  • readRaw(filePath: string) → ReadRawResult
    • 以 raw FileData 读取 file content。返回包含 timestamps 的完整 file data。
  • grep(pattern: string, path?: string | null, glob?: string | null) → GrepResult
    • 在 file contents 中搜索 literal text pattern。Binary files(由 MIME type 判定)会被跳过。失败时返回 { error: "..." }
  • glob(pattern: string, path?: string) → GlobResult
    • 将匹配 glob pattern 的 files 作为 FileInfo entries 返回。
  • write(filePath: string, content: string) → WriteResult
    • Create-only semantics。冲突时返回 { error: "..." }。成功时设置 path,并对 state backends 设置 filesUpdate={...};external backends 应使用 filesUpdate=null
  • edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean) → EditResult
    • 除非 replaceAll=true,否则强制 oldString 唯一。如果找不到,返回 error。成功时包含 occurrences

Optional methods

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

Result types

TypeSuccess fieldsError field
ReadResultcontent?: string | Uint8Array, mimeType?: stringerror
ReadRawResultdata?: FileDataerror
LsResultfiles?: FileInfo[]error
GlobResultfiles?: FileInfo[]error
GrepResultmatches?: GrepMatch[]error
WriteResultpath?: stringerror
EditResultpath?: string, occurrences?: numbererror

Supporting types

  • FileInfopath(必需),可选 is_dirsizemodified_at
  • GrepMatchpathline(1-indexed)、text
  • FileData,包含 timestamps 的 file content。请参阅 FileData format

Sandbox extension

SandboxBackendProtocolV2 使用以下内容扩展 BackendProtocolV2
  • execute(command: string) → ExecuteResponse,在 sandbox 中运行 shell command。
  • readonly id: string,sandbox instance 的唯一标识符。

将现有 backends 更新到 V2

Method renames

V1 methodV2 methodReturn type change
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(...)Unchanged (WriteResult)
edit(...)edit(...)Unchanged (EditResult)

Type renames

V1 typeV2 type
BackendProtocolBackendProtocolV2
SandboxBackendProtocolSandboxBackendProtocolV2

Adaptation utilities

如果你有需要与 V2-only code 一起使用的现有 V1 backends,请使用 adaptation functions:
import { adaptBackendProtocol, adaptSandboxProtocol } from "deepagents";

// Adapt a V1 backend to V2
const v2Backend = adaptBackendProtocol(v1Backend);

// Adapt a V1 sandbox to V2
const v2Sandbox = adaptSandboxProtocol(v1Sandbox);
Framework 会自动适配传给 createDeepAgent() 的 V1 backends。只有在直接调用 protocol methods 时,才需要手动 adaptation。