Skip to content
On this page

7.后端(Backends)

为深度代理选择并配置文件系统后端。您可以指定到不同后端的路由、实现虚拟文件系统并实施策略。

深度代理通过一些工具向代理公开文件系统表面。这些工具通过可插拔的后端运行。本页介绍如何选择后端、将不同的路径路由到不同的后端]、实现自己的虚拟文件系统、添加策略挂钩以及遵守后端协议。

7.1内置后端

以下是一些预构建的文件系统后端,您可以将它们与深度代理快速一起使用:

StateBackend(临时)
python
# By default we provide a StateBackend
agent = create_deep_agent()

# Under the hood, it looks like
from deepagents.backends import StateBackend

agent = create_deep_agent(
    backend=(lambda rt: StateBackend(rt))   # Note that the tools access State through the runtime.state
)

StateBackend 是一个临时的文件存储后端,默认由 DeepAgents 提供。在当前线程中存储文件,在同一线程内可以持续存在,它们会通过 检查点(checkpoint) 机制保存下来,代理可以在后续步骤继续使用,但不会跨线程持久化。

StateBackend 就像一个临时便签本(scratch pad),代理可以在这里写入执行过程中的中间产物。或者当工具输出内容太大时,系统会自动清理这些数据,只保留可按需分块读取的方式,让代理稍后逐步读取使用。

FilesystemBackend(本地磁盘)
python
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    backend=FilesystemBackend(root_dir="/Users/nh/Desktop/")
)

root_dir为可以配置的根目录,必须为绝对路径,所有文件操作都被限制在这个目录下。若启用 virtual_mode=True,代理将在这个 root_dir 下模拟文件系统环境(即沙盒化)。

最适合的场景:在本地磁盘上运行项目、CI/CD 沙盒环境、挂载的持久存储卷

StoreBackend (LangGraph 商店)
python
from deepagents.backends import StoreBackend

agent = create_deep_agent(
    backend=(lambda rt: StoreBackend(rt))   # Note that the tools access Store through the runtime.store
)

将文件存储在运行时提供的 LangGraph 中,从而实现跨线程持久存储。即使 agent 结束运行,下次启动仍然能访问到之前保存的文件。

最适合的场景:

当你的运行环境已经配置了 LangGraph Store(如 Redis 或 Postgres)时。通过 LangSmith Deployments 部署代理时(会自动为代理预配存储)。

CompositeBackend(路由器)
python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
from deepagents.backends.composite import build_composite_state_backend

composite_backend = lambda rt: CompositeBackend(
    default=StateBackend(rt)
    routes={
        "/memories/": StoreBackend(rt),
        "/docs/": CustomBackend()
    }
)

agent = create_deep_agent(backend=composite_backend)

CompositeBackend 让 agent 能根据路径前缀自动路由文件读写请求到不同的存储后端,从而同时支持临时存储、本地存储、持久存储、甚至自定义虚拟文件系统。

最适合的场景:

同时拥有临时和长期记忆的 Agent。多来源融合(多文件系统整合)。

注意:

  • 较长的前缀获胜(例如,路由可以覆盖)。"/memories/projects/"``"/memories/"
  • 对于 StoreBackend 路由,请确保代理运行时提供 store ()。runtime.store

7.2使用虚拟文件系统

构建自定义后端,将远程或数据库文件系统(例如 S3 或 Postgres)投影到工具命名空间中。设计指南:

  • 路径是绝对的 (/x/y.txt)。决定如何将它们映射到存储密钥/行。
  • 实现并高效(如果可用,则为服务器端列表,否则为本地过滤器)。
  • 返回用户可读的错误字符串,以显示缺少的文件或无效的正则表达式模式。即自定义后端应该返回 可读错误信息
  • 对于外部持久性,请设置结果;只有状态内后端才应该返回一个字典。files_update=None``files_update。就是说根据存储类型处理 files_update → 外部持久化直接写入,状态内返回字典。

7.3协议参考

后端必须实现 .BackendProtocol,所有 DeepAgents 文件系统后端都必须遵循这个协议

8.子代理(subagents)

深度代理可以创建子代理来委派工作。您可以在参数中指定自定义子代理。子代理对于上下文隔离(保持主代理的上下文干净)和提供专用指令非常有用。

子代理解决上下文膨胀问题。当代理使用具有大量输出的工具(Web 搜索、文件读取、数据库查询)时,上下文窗口会很快填满中间结果。子代理将这些详细工作隔离开来——主代理只接收最终结果,而不是产生它的数十个工具调用。

何时使用子代理:

  • ✅ 会使主代理的上下文变得混乱的多步骤任务
  • ✅ 需要自定义说明或工具的专用域
  • ✅ 需要不同模型功能的任务
  • ✅ 当您想让主代理专注于高层协调时

何时不使用子代理:

  • ❌ 简单的单步任务
  • ❌ 当您需要维护中间上下文时
  • ❌ 当管理费用大于收益时

8.1子代理的配置

DeepAgents 支持两种子代理类型:SubAgent(使用字典结构定义)和 CompiledSubAgent(已编译的可运行实例)。有关每种类型的详细定义及字段说明,请参阅第 5 节中的5.2以及5.3。

8.2子代理的示例

这两种类型的子代理应用示例,请参阅第5节中的5.4。

8.3通用子代理(general-purpose)

除了任何用户定义的子代理之外,深度代理还可以随时访问此子代理。

  • 具有与主代理相同的系统提示
  • 可以访问所有相同的工具
  • 使用相同的模型(除非被覆盖)

通用子代理非常适合上下文隔离,无需特殊行为。主代理可以将复杂的多步骤任务委托给该子代理,并获得简洁的结果,而不会因中间工具调用而膨胀。

8.4高效使用建议

1.写清楚的描述:

主代理通过子代理的“描述(description)”来判断它是否适合处理当前任务。描述越具体、越清楚,主代理越容易准确地调用合适的子代理。

2.保持系统提示的详细性

包括有关如何使用工具和格式输出的具体指南

3.最小化工具集

只为子代理提供他们需要的工具。这提高了焦点和安全性:

python
# ✅ Good: Focused tool set
email_agent = {
    "name": "email-sender",
    "tools": [send_email, validate_email],  # Only email-related
}

# ❌ Bad: Too many tools
email_agent = {
    "name": "email-sender",
    "tools": [send_email, web_search, database_query, file_upload],  # Unfocused
}

4.按任务选择模型

不同的模型擅长不同的任务:

python
subagents = [
    {
        "name": "contract-reviewer",
        "description": "Reviews legal documents and contracts",
        "system_prompt": "You are an expert legal reviewer...",
        "tools": [read_document, analyze_contract],
        "model": "claude-sonnet-4-5-20250929",  # Large context for long documents
    },
    {
        "name": "financial-analyst",
        "description": "Analyzes financial data and market trends",
        "system_prompt": "You are an expert financial analyst...",
        "tools": [get_stock_price, analyze_fundamentals],
        "model": "openai:gpt-4o",  # Better for numerical analysis
    },
]

5.返回简洁的结果

指示子代理返回摘要,而不是原始数据。

8.5常见模式

多个专用子代理,为不同的域创建专用子代理

例如三个子代理,data-collector、data-analyzer、report-writer。每个子代理都使用仅专注于其任务的干净上下文。

9.人机交互(Human-in-the-loop)

某些工具作可能很敏感,需要人工批准才能执行。Deep Agent 通过 LangGraph 的中断功能支持人机交互工作流程。您可以使用该参数配置哪些工具需要批准。interrupt_on

9.1基本配置

该参数接受将工具名称映射到中断配置的字典。每个工具都可以配置:interrupt_on

  • True:启用具有默认行为的中断(允许批准、编辑、拒绝)
  • False:禁用此工具的中断
  • {“allowed_decisions”: [...]}: 具有特定允许决策的自定义配置

决策类型,该列表控制人类在查看工具调用时可以执行的动作:allowed_decisions

  • “approve”:按照代理建议的原始参数执行工具
  • “edit”:执行前修改工具参数
  • “reject”:完全跳过执行此工具调用

示例代码:

python
from langchain_core.tools import tool
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver

@tool
def delete_file(path: str) -> str:
    """Delete a file from the filesystem."""
    return f"Deleted {path}"

@tool
def read_file(path: str) -> str:
    """Read a file from the filesystem."""
    return f"Contents of {path}"

@tool
def send_email(to: str, subject: str, body: str) -> str:
    """Send an email."""
    return f"Sent email to {to}"

# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()

agent = create_deep_agent(
    model="claude-sonnet-4-5-20250929",
    tools=[delete_file, read_file, send_email],
    interrupt_on={
        "delete_file": True,  # Default: approve, edit, reject
        "read_file": False,   # No interrupts needed
        "send_email": {"allowed_decisions": ["approve", "reject"]},  # No editing
    },
    checkpointer=checkpointer  # Required!
)

9.2处理中断

触发中断时,代理会暂停执行并返回控制权。检查结果中的中断并相应地处理它们。

python
# Create config with thread_id for state persistence
config = {"configurable": {"thread_id": str(uuid.uuid4())}}

# Invoke the agent
result = agent.invoke({
    "messages": [{"role": "user", "content": "Delete the file temp.txt"}]
}, config=config)

# Check if execution was interrupted
if result.get("__interrupt__"):
    # Extract interrupt information
    interrupts = result["__interrupt__"][0].value
    action_requests = interrupts["action_requests"]
    review_configs = interrupts["review_configs"]

    # Create a lookup map from tool name to review config
    config_map = {cfg["action_name"]: cfg for cfg in review_configs}

    # Display the pending actions to the user
    for action in action_requests:
        review_config = config_map[action["name"]]
        print(f"Tool: {action['name']}")
        print(f"Arguments: {action['args']}")
        print(f"Allowed decisions: {review_config['allowed_decisions']}")

    # Get user decisions (one per action_request, in order)
    decisions = [
        {"type": "approve"}  # User approved the deletion
    ]

    # Resume execution with decisions
    result = agent.invoke(
        Command(resume={"decisions": decisions}),
        config=config  # Must use the same config!
    )

# Process final result
print(result["messages"][-1]["content"])

Agent 首先根据用户指令开始执行任务(如删除文件)。若任务涉及敏感操作,会触发 中断(interrupt),返回需人工审批的操作列表。用户查看并决定是否批准这些操作。批准后,通过 resume 命令 恢复执行,Agent 继续完成任务并返回最终结果。

9.3中断机制扩展

9.3.1多个工具调用

当代理调用多个需要批准的工具时,所有中断都会在单个中断中批处理在一起。您必须按顺序为每个项目提供决策。

9.3.2编辑工具参数

当在允许的决策中时,您可以在执行之前修改工具参数:"edit"

9.3.3子代理中断

每个子代理都可以有自己的配置,以覆盖主代理的设置:interrupt_on

当一个子代理(subagent)触发中断(interrupt)时,处理方式与主代理相同 —— 你需要检查返回结果中是否包含 __interrupt__,然后使用 Command 对象(即 Command(resume={...}))来恢复执行。

9.4高效使用建议

始终使用检查点:人机交互需要一个检查点来在中断和恢复之间持久化代理状态

使用相同的线程 ID:恢复时,您必须使用相同的配置和相同的 :thread_id

将决策顺序与作匹配:决策列表必须与以下顺序匹配:action_requests

按风险定制配置:根据风险级别配置不同的工具

10.长期记忆(Long-term memory)

深度代理带有一个本地文件系统来卸载内存。此文件系统存储在状态中,因此是暂时的,到单个线程 - 会话结束时文件会丢失。你可以通过提供一个 LangGraph 并设置 use_longterm_memory=True 来为 Deep Agent 添加长期记忆功能。这样,代理的状态和信息可以跨线程和跨对话持续保存,不只是一次调用中的临时上下文。

10.1设置

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

store = InMemoryStore()  # Or any other Store object
agent = create_deep_agent(
    store=store,
    use_longterm_memory=True
)

10.2运行方式

启用长期内存后,深度代理会维护两个单独的文件系统

  1. 短期(瞬态)文件系统
  • 存储在代理的状态下
  • 仅在单个线程中保留
  • 线程结束时文件丢失
  • 通过标准路径访问:/notes.txt
  1. 长期(持久)文件系统
  • 存储在 LangGraph 存储中
  • 在所有线程和对话中保留
  • 文件无限期存续
  • 通过特殊前缀访问:/memories/notes.txt

10.3/memories/ 路径

长期记忆的关键是 /memories/ 路径前缀:

  • /memories/ 开头的文件路径会存储在 Store 中(持久化存储)。
  • 没有此前缀的文件将保持暂时状态
  • 所有文件系统工具(lsread_filewrite_fileedit_file)都可以同时操作临时文件和持久文件。
  • 跨线程持久性可以从任何线程访问中的文件:/memories/
python
# Transient file (lost after thread ends)
agent.invoke({
    "messages": [{"role": "user", "content": "Write draft to /draft.txt"}]
})

# Persistent file (survives across threads)
agent.invoke({
    "messages": [{"role": "user", "content": "Save final report to /memories/report.txt"}]
})

10.4使用案例

1.用户首选项:存储跨会话保留的用户偏好

2.自我改进说明:代理可以根据反馈更新自己的指令,随着时间的推移,指令文件会积累用户偏好,帮助代理改进。

3.知识库:通过多次对话积累知识

4.研究项目:跨会话保持研究状态

10.5高效使用建议

1.使用描述性路径,使用清晰的分层路径组织长期文件

2.记录持久化的内容,在系统提示中,明确何时使用长期存储与短期存储

3.按 assistant_id隔离存储,对于多租户应用程序,可以提供一个 assistant_id 来隔离不同助手的数据存储。

10.6局限性

1.store是必填的,启用长期记忆时,必须提供存储。

2.代理必须使用正确的路径,代理需要学会使用 /memories/ 前缀来实现持久化存储。系统提示会指导这一点,但代理必须遵循这些指令。

3.没有自动清理,长期文件会无限期地保留。没有内置 TTL 或自动清理。如果需要,您需要实施清理策略。