7.后端(Backends)
为深度代理选择并配置文件系统后端。您可以指定到不同后端的路由、实现虚拟文件系统并实施策略。
深度代理通过一些工具向代理公开文件系统表面。这些工具通过可插拔的后端运行。本页介绍如何选择后端、将不同的路径路由到不同的后端]、实现自己的虚拟文件系统、添加策略挂钩以及遵守后端协议。
7.1内置后端
以下是一些预构建的文件系统后端,您可以将它们与深度代理快速一起使用:
StateBackend(临时)
# 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(本地磁盘)
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 商店)
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(路由器)
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.最小化工具集
只为子代理提供他们需要的工具。这提高了焦点和安全性:
# ✅ 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.按任务选择模型
不同的模型擅长不同的任务:
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”:完全跳过执行此工具调用
示例代码:
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处理中断
触发中断时,代理会暂停执行并返回控制权。检查结果中的中断并相应地处理它们。
# 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设置
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运行方式
启用长期内存后,深度代理会维护两个单独的文件系统:
- 短期(瞬态)文件系统
- 存储在代理的状态下
- 仅在单个线程中保留
- 线程结束时文件丢失
- 通过标准路径访问:
/notes.txt
- 长期(持久)文件系统
- 存储在 LangGraph 存储中
- 在所有线程和对话中保留
- 文件无限期存续
- 通过特殊前缀访问:
/memories/notes.txt
10.3/memories/ 路径
长期记忆的关键是 /memories/ 路径前缀:
- 以
/memories/开头的文件路径会存储在 Store 中(持久化存储)。 - 没有此前缀的文件将保持暂时状态
- 所有文件系统工具(
ls、read_file、write_file、edit_file)都可以同时操作临时文件和持久文件。 - 跨线程持久性可以从任何线程访问中的文件:
/memories/
# 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 或自动清理。如果需要,您需要实施清理策略。