本指南涵盖了将 Deep Agent 从本地原型部署到生产环境的相关注意事项。它将逐步介绍如何管理记忆的作用域、配置执行环境、添加安全防护,以及连接前端界面。
Agent 利用来自记忆和执行环境的信息来完成任务。在生产环境中,有几个基本要素决定了信息的共享和访问方式:
线程 :一次单独的对话。消息历史和临时文件默认作用域为线程,不会跨对话保留。
用户 :与 Agent 交互的人。记忆和文件可以是用户私有的,也可以在用户之间共享。身份验证和授权来自您的认证层 。
助手 :一个配置好的 Agent 实例。记忆和文件可以绑定到一个助手,也可以跨所有助手共享。
本页涵盖:
LangSmith Deployments
将 Deep Agent 投入生产的最快方式是使用 deepagents deploy ,它将 Agent 配置打包并使用一条命令部署为 LangSmith Deployment。或者,您也可以直接配置 LangSmith Deployment 。这两种方式都会为您配置 Agent 所需的基础设施:助手 、线程 、运行 、存储和检查点器,因此您无需自行设置。它还开箱即用地提供身份验证 、Webhook 、定时任务 和可观测性 ,并可以通过 MCP 或 A2A 公开您的 Agent。
有关基于 CLI 的方法,请参阅使用 CLI 部署 。有关手动设置,请参阅 LangSmith Deployments 快速入门 。
除非另有说明,否则本页的所有代码片段都使用以下 langgraph.json:
{
" dependencies " : [ "." ],
" graphs " : {
" agent " : "./agent.py:agent"
},
" env " : ".env"
}
langgraph.json 是告诉 LangGraph 平台如何构建和运行应用程序的配置文件。它位于项目根目录,是本地开发(使用 langgraph dev)和生产部署所必需的。关键字段如下:
字段 描述 dependencies要安装的包。["."] 将当前目录安装为一个包(从 requirements.txt、pyproject.toml 或 package.json 读取)。 graphs将图形 ID 映射到其代码位置。每个条目的格式为 "<id>": "./<file>:<variable>",其中 <id> 是您通过 API 调用图形时使用的名称,<variable> 是从 <file> 导出的已编译图形或构造函数。 env包含环境变量(API 密钥、密钥)的 .env 文件路径。这些在构建时设置,在运行时可用。
有关完整的配置选项(自定义 Docker 步骤、存储索引、认证处理程序等),请参阅应用程序结构 。
生产环境注意事项
多租户
当您的 Agent 为多个用户提供服务时,您需要处理三个问题:验证每个用户是谁、控制他们可以访问的内容,以及管理 Agent 代表他们执行操作时使用的凭证。
用户身份和访问控制
LangSmith Deployments 支持自定义身份验证 来建立用户身份,以及授权处理程序 来控制对线程、助手和存储命名空间等资源的访问。授权处理程序在身份验证成功后运行,可以:
使用所有权元数据标记资源(例如 owner: user_id)
返回过滤器,使用户只能看到自己的资源
对于未授权的操作返回 HTTP 403 拒绝访问
有关分步教程,请参阅使对话私有化 。
您如何管理记忆的作用域 和执行环境 决定了用户之间共享哪些数据。请参阅下面的相关部分了解详情。
团队访问控制(RBAC)
LangSmith 的基于角色的访问控制 管理着团队中谁可以部署、配置和监控 Agent。这与上述最终用户授权是分开的。
角色 访问权限 工作区管理员 拥有全部权限,包括设置和成员管理 工作区编辑 创建和修改资源,但无法删除运行记录或管理成员 工作区查看者 只读访问
企业计划提供具有细粒度权限的自定义角色。请参阅 RBAC 参考 了解完整的权限模型。
最终用户凭证
当您的 Agent 需要代表用户调用外部 API(例如读取他们的 GitHub 仓库、发送 Slack 消息、查询他们的数据仓库)时,您需要一种方式将用户凭证传递给 Agent,而不是硬编码它们。
通过 Agent Auth 进行 OAuth。 Agent Auth 提供托管的 OAuth 2.0 流程。配置一个 OAuth 提供商,Agent 可以请求每个用户范围的令牌。第一次使用时,Agent 会中断 执行并显示 OAuth 同意 URL。用户身份验证后,Agent 会使用有效令牌恢复。令牌会自动存储和刷新。
from langchain_auth import Client
from langchain . tools import tool , ToolRuntime
auth_client = Client ()
# 在 Agent 的工具内:
@tool
async def github_action ( runtime : ToolRuntime ):
"""通过 GitHub 代表用户执行操作。"""
auth_result = await auth_client . authenticate (
provider = "github" ,
scopes = [ "repo" , "read:org" ],
user_id = runtime . server_info . user . identity ,
)
# 使用 auth_result.token 代表用户调用 GitHub API
**沙箱凭证注入。**如果您的 Agent 在沙箱 内运行调用外部 API 的代码,沙箱认证代理 可以自动将凭证注入出站请求,因此沙箱代码永远不会收到原始 API 密钥。请参阅管理密钥 了解设置详情。
**工作区密钥。**对于所有用户共享的 API 密钥(例如您组织的 LLM 提供商密钥、搜索 API 密钥),请将它们作为 LangSmith 工作区密钥 存储。请参阅管理密钥 了解详情。
基于 LLM 的应用程序是严重的 I/O 密集型应用:调用语言模型、数据库和外部服务。异步编程使这些操作可以并发运行而不是阻塞,从而提高吞吐量和响应性。
LangChain 遵循在异步方法名称前加 a 前缀的约定(例如 ainvoke、abefore_agent、astream)。同步和异步变体位于同一个类或命名空间中。
在构建生产环境应用时:
**创建异步工具。**LangChain 在单独线程中运行同步工具以避免阻塞,但原生异步可以完全避免线程开销。
**使用异步中间件方法。**自定义中间件 应实现异步钩子(例如 abefore_agent 而不是 before_agent)。
**使用异步管理外部资源生命周期。**创建沙箱 或连接 MCP 服务器 涉及网络调用,应该被 await。这就是图形工厂 (配置这些资源的工厂)是异步的原因。
持久性
Deep Agents 在 LangGraph 上运行,LangGraph 开箱即用地提供持久化执行 。持久化 层在每个步骤检查点保存状态,因此因故障、超时或人工介入 暂停而中断的运行会从上次记录的状态恢复,而不会重新处理之前的步骤。对于生成许多子代理的长时间运行的 Deep Agents,这意味着运行中途失败不会丢失已完成的工作。
检查点还支持:
**无限期中断 。**人工介入工作流可以暂停数分钟或数天,然后从中断处精确恢复。
**时间旅行 。**每个检查点步骤都是一个快照,您可以倒回该快照,让您可以从较早的状态重新播放,以防出现问题。
**安全处理敏感操作。**对于涉及支付或其他不可逆操作的工作流,检查点提供审计跟踪和恢复点,以检查导致操作的精确状态。
没有记忆,每个对话都从零开始。记忆让您的 Agent 能够跨对话保留信息(用户偏好、学习的指令、过去的经验),以便它可以随着时间的推移个性化其行为。有关记忆类型的概述,请参阅记忆概念指南 。
作用域
记忆在对话之间始终是持久化的。主要问题是它如何跨用户和助手边界进行作用域管理。正确的作用域取决于谁应该查看和修改数据:
作用域 命名空间 用例 示例 用户 (推荐的默认设置)(user_id)每个用户的偏好和上下文 ”我更喜欢简洁的回复” 助手 (assistant_id)一个助手的共享指令 ”帖子最多 280 个字符” 全局 (org_id)所有用户和助手只读策略 ”永不透露内部定价”
共享记忆(助手、用户或组织作用域)是提示注入的媒介。如果一个用户可以写入另一个用户对话所读取的记忆,恶意用户可能会将指令注入到该共享状态中。在适当的地方强制执行只读访问。例如,使组织范围的策略只能通过应用程序代码而不是 Agent 本身来写入。使用权限 来声明性地拒绝对共享路径的写入,或使用后端策略钩子 进行自定义验证逻辑。
在 Deep Agents 中,记忆作为文件存储在虚拟文件系统中。默认情况下,文件只持续单个对话。要使它们持久化,请将类似 /memories/ 的路径路由到写入 LangGraph 存储 的 StoreBackend 。使用 CompositeBackend 为 Agent 提供临时工作空间和持久化长期记忆 。
下面显示的 rt.server_info 和 rt.execution_info 命名空间模式需要 deepagents>=0.5.0。
按 user_id 进行命名空间隔离。每个用户拥有自己的私有记忆。这是推荐的默认设置,因为大多数应用程序部署单个助手。 from deepagents import create_deep_agent
from deepagents . backends import CompositeBackend , StateBackend , StoreBackend
agent = create_deep_agent (
backend = CompositeBackend (
default = StateBackend (),
routes = {
"/memories/" : StoreBackend (
namespace = lambda rt : (
rt . server_info . assistant_id ,
rt . server_info . user . identity ,
),
),
},
),
system_prompt = """您在 /memories/ 有持久化记忆。
在每个对话开始时读取 /memories/instructions.txt 以获取
积累的知识和偏好。当您学到应该持久化的内容时,
更新该文件。""" ,
)
按 assistant_id 进行命名空间隔离。记忆在相同助手的所有用户之间共享,因此任何用户都可以读取或更新它。将此用于适用于使用给定助手的所有人的共享指令或知识(例如,“始终以正式语气回复”)。 from deepagents import create_deep_agent
from deepagents . backends import CompositeBackend , StateBackend , StoreBackend
agent = create_deep_agent (
backend = CompositeBackend (
default = StateBackend (),
routes = {
"/memories/" : StoreBackend (
namespace = lambda rt : (
rt . server_info . assistant_id ,
),
),
},
),
)
仅按 user_id 进行命名空间隔离。记忆跨所有助手跟随用户。将此用于全局用户配置文件(姓名、时区、沟通偏好),无论用户与哪个助手交谈都应适用。 from deepagents import create_deep_agent
from deepagents . backends import CompositeBackend , StateBackend , StoreBackend
agent = create_deep_agent (
backend = CompositeBackend (
default = StateBackend (),
routes = {
"/memories/" : StoreBackend (
namespace = lambda rt : ( rt . server_info . user . identity ,),
),
},
),
)
按 org_id 进行命名空间隔离。记忆在所有用户和所有助手之间共享。通常用于组织范围的策略(合规规则、品牌指南),Agent 应该只读访问。写访问应仅限于应用程序代码,以防止提示注入。 from deepagents import create_deep_agent
from deepagents . backends import CompositeBackend , StateBackend , StoreBackend
agent = create_deep_agent (
backend = CompositeBackend (
default = StateBackend (),
routes = {
"/memories/" : StoreBackend (
namespace = lambda rt : ( rt . context . org_id ,),
),
},
),
)
您还可以使用存储 API 从应用程序代码中读取和写入存储。有关示例,请参阅高级用法 。
有关完整的命名空间工厂 API,请参阅命名空间工厂 。有关自我改进指令和知识库等记忆模式,请参阅长期记忆 。
执行环境
在本地,Agent 可以直接读取和写入磁盘文件并运行 shell 命令。在生产环境中,您需要考虑隔离和持久性。正确的设置取决于您的 Agent 是否需要执行代码:
文件系统后端 足以满足 Agent 仅读取和写入文件的情况。选择符合您持久化需求的后端:临时工作空间、持久化存储或两者混合。
沙箱 添加了具有 execute 工具的隔离容器,用于运行 shell 命令。如果您的 Agent 需要运行代码、安装包或做任何超出文件 I/O 的操作,请使用沙箱。
文件系统
根据需要持久化的内容选择后端:
有关后端完整列表以及如何构建自定义后端,请参阅后端 。
FilesystemBackend 和 LocalShellBackend 直接访问主机。请勿在已部署的 Agent 中使用它们。
如果您的 Agent 需要运行代码(不仅仅是读取和写入文件),请使用沙箱 。沙箱同时提供文件系统和用于运行 shell 命令的 execute 工具,全部在隔离的容器内。这种隔离也保护您的主机:如果 Agent 的代码耗尽内存或崩溃,只有沙箱会受到影响。您的服务器会继续运行。
生命周期
关键决策是沙箱的存活时间。每个对话获得一个新的沙箱,还是对话共享一个持久化环境?
作用域 沙箱 ID 存储位置 生命周期 示例用例 线程作用域 线程 元数据每个对话全新,在 TTL 时清理 一个数据分析机器人,每个对话都从干净状态开始 助手作用域 助手 配置跨所有对话共享 一个编码助手,在对话之间维护克隆的仓库
下面的示例使用异步图形工厂 而不是静态图形,因为沙箱需要 thread_id 或 assistant_id 来查找或创建正确的沙箱。图形工厂不接收完整的 Runtime(没有 server_info 或 execution_info);相反,接收 RunnableConfig 并从 config["configurable"] 读取 thread_id 和 assistant_id。工厂是异步的,因为沙箱创建是 I/O 密集型操作,需要仅在调用时可用的每次运行信息。
每个对话获得自己的沙箱。图形工厂 从运行配置中读取 thread_id,因此每个线程 自动获得自己的隔离环境。提供商的基于标签的查找处理跨运行的去重。在沙箱 TTL 到期时清理。 from daytona import CreateSandboxFromSnapshotParams , Daytona
from deepagents import create_deep_agent
from langchain_core . runnables import RunnableConfig
from langchain_daytona import DaytonaSandbox
client = Daytona ()
async def agent ( config : RunnableConfig ):
thread_id = config [ " configurable " ][ "thread_id" ]
try :
sandbox = await client . find_one ( labels = { "thread_id" : thread_id })
except Exception :
sandbox = await client . create (
CreateSandboxFromSnapshotParams (
labels = { "thread_id" : thread_id },
auto_delete_interval = 3600 , # TTL:空闲时清理
)
)
return create_deep_agent ( backend = DaytonaSandbox ( sandbox = sandbox ))
所有对话共享一个沙箱。图形工厂 从 config["configurable"] 读取助手 ID,因此同一助手上的每个线程都返回到相同的环境。文件、安装的包和克隆的仓库跨对话持久化。 from daytona import CreateSandboxFromSnapshotParams , Daytona
from deepagents import create_deep_agent
from langchain_core . runnables import RunnableConfig
from langchain_daytona import DaytonaSandbox
client = Daytona ()
async def agent ( config : RunnableConfig ):
assistant_id = config [ " configurable " ][ "assistant_id" ]
try :
sandbox = await client . find_one ( labels = { "assistant_id" : assistant_id })
except Exception :
sandbox = await client . create (
CreateSandboxFromSnapshotParams ( labels = { "assistant_id" : assistant_id })
)
return create_deep_agent ( backend = DaytonaSandbox ( sandbox = sandbox ))
助手作用域沙箱会随着时间累积文件、安装的包和其他沙箱内状态。请使用沙箱提供商的 TTL 配置、定期使用快照重置,或实现清理逻辑,以防止沙箱的磁盘和内存无限增长。
因为 agent 变量是一个异步函数(不是已编译的图形),服务器将其视为图形工厂 并在每次运行时调用它,注入配置。工厂通过提供商的基于标签的搜索查找或创建沙箱,并返回连接到该沙箱的新图形。
使用 langgraph deploy 部署后,使用 SDK 从应用程序代码调用 Agent。客户端代码无论作用域如何都相同。作用域管理完全在上面的 Agent 工厂中处理,但行为有所不同:
每个线程获得自己的沙箱。同一个对话中的后续消息会重用相同的沙箱,但新线程始终从干净状态开始,不会遗留上一个对话中的文件或已安装的包。 from langgraph_sdk import get_client
client = get_client ( url = "<DEPLOYMENT_URL>" , api_key = "<LANGSMITH_API_KEY>" )
# 对话 1:安装 pandas 并分析数据
thread_1 = await client . threads . create ()
async for chunk in client . runs . stream (
thread_1 [ " thread_id " ],
"agent" ,
input = { "messages" : [{ "role" : "human" , "content" : "Install pandas and analyze sales_data.csv" }]},
stream_mode = "updates" ,
):
print ( chunk . data )
# 同一对话中的后续消息 — pandas 仍然安装
async for chunk in client . runs . stream (
thread_1 [ " thread_id " ],
"agent" ,
input = { "messages" : [{ "role" : "human" , "content" : "Now plot the results" }]},
stream_mode = "updates" ,
):
print ( chunk . data )
# 对话 2:全新的沙箱 — pandas 未安装,没有对话 1 的文件
thread_2 = await client . threads . create ()
async for chunk in client . runs . stream (
thread_2 [ " thread_id " ],
"agent" ,
input = { "messages" : [{ "role" : "human" , "content" : "What packages are installed?" }]},
stream_mode = "updates" ,
):
print ( chunk . data )
所有线程共享一个沙箱。当沙箱状态重建成本很高时,这很有用,例如克隆的仓库、安装的依赖项或构建产物。任何同一助手上的对话都会从上一个对话中断的地方继续,无需重复设置。 from langgraph_sdk import get_client
client = get_client ( url = "<DEPLOYMENT_URL>" , api_key = "<LANGSMITH_API_KEY>" )
# 对话 1:克隆并设置项目
thread_1 = await client . threads . create ()
async for chunk in client . runs . stream (
thread_1 [ " thread_id " ],
"agent" ,
input = { "messages" : [{ "role" : "human" , "content" : "Clone https://github.com/org/repo and install dependencies" }]},
stream_mode = "updates" ,
):
print ( chunk . data )
# 对话 2:仓库和依赖项仍然存在
thread_2 = await client . threads . create ()
async for chunk in client . runs . stream (
thread_2 [ " thread_id " ],
"agent" ,
input = { "messages" : [{ "role" : "human" , "content" : "Run the test suite and fix any failures" }]},
stream_mode = "updates" ,
):
print ( chunk . data )
文件传输
沙箱是隔离的容器,因此您的应用程序代码无法直接访问其中的文件。使用 upload_files() 和 download_files() 在沙箱边界上移动数据:
在 Agent 运行前填充沙箱 :上传用户文件、技能 脚本、配置或持久化记忆 ,以便 Agent 从一开始就有所需的资源
在 Agent 完成后检索结果 :下载生成的产物(报告、图表、导出文件)并将更新的记忆同步回来以供未来对话使用
有关特定提供商的 파일传输示例,请参阅使用文件 。有关提供商设置、安全性和生命周期模式,请参阅完整的沙箱指南 。
Agent 需要执行的技能 脚本必须在上载到沙箱中。您可能还需要同步记忆 ,以便 Agent 可以在容器内读取和更新它们。使用带有 before_agent 和 after_agent 钩子的自定义中间件 在沙箱边界上移动文件: from deepagents import create_deep_agent
from langchain . agents . middleware import AgentMiddleware , AgentState
from langgraph . runtime import Runtime
def _safe_filename ( key : str ) -> str :
"""拒绝包含路径遍历或通配符字符的密钥。"""
name = key . split ( "/" )[ - 1 ]
if ".." in name or any ( c in name for c in ( "*" , "?" )):
raise ValueError ( f "无效的密钥: { key } " )
return name
class SandboxSyncMiddleware ( AgentMiddleware ):
"""在存储和沙箱之间同步技能和记忆。"""
def __init__ ( self , backend : CompositeBackend ):
super (). __init__ ()
self . backend = backend
async def abefore_agent ( self , state : AgentState , runtime : Runtime ) -> None :
"""将技能脚本和记忆上传到沙箱。"""
user_id = runtime . server_info . user . identity
store = runtime . store
files = []
for item in await store . asearch (( "skills" , user_id )):
name = _safe_filename ( item . key )
files . append (( f "/skills/ { name } " , item . value [ " content " ]. encode ()))
for item in await store . asearch (( "memories" , user_id )):
name = _safe_filename ( item . key )
files . append (( f "/memories/ { name } " , item . value [ " content " ]. encode ()))
if files :
await self . backend . upload_files ( files )
async def aafter_agent ( self , state : AgentState , runtime : Runtime ) -> None :
"""将更新的记忆同步回存储。"""
user_id = runtime . server_info . user . identity
store = runtime . store
items = await store . asearch (( "memories" , user_id ))
results = await self . backend . download_files (
[ f "/memories/ { item . key } " for item in items ]
)
for result in results :
if result . content is not None :
await store . aput (
( "memories" , user_id ),
result . path . split ( "/" )[ - 1 ],
{ "content" : result . content . decode ()},
)
backend = CompositeBackend (
default = DaytonaSandbox ( sandbox = sandbox ),
routes = {
"/skills/" : StoreBackend (
rt ,
namespace = lambda rt : ( "skills" , rt . server_info . user . identity ),
),
"/memories/" : StoreBackend (
rt ,
namespace = lambda rt : ( "memories" , rt . server_info . user . identity ),
),
},
)
agent = create_deep_agent (
backend = backend ,
middleware = [ SandboxSyncMiddleware ( backend )],
)
管理密钥
沙箱是隔离的容器,因此主机上的环境变量在沙箱内不可用。有两种方式可以向沙箱代码提供 API 密钥和其他密钥:
认证代理(推荐)。 沙箱认证代理 拦截来自沙箱的出站请求并自动注入认证头。沙箱代码正常调用外部 API,代理根据目标主机添加正确的凭证。这意味着 API 密钥永远不会出现在沙箱代码、环境变量或日志中。
{
" proxy_config " : {
" rules " : [
{
" name " : "openai-api" ,
" match_hosts " : [ "api.openai.com" ],
" inject_headers " : {
" Authorization " : "Bearer ${OPENAI_API_KEY}"
}
},
{
" name " : "anthropic-api" ,
" match_hosts " : [ "api.anthropic.com" ],
" inject_headers " : {
" x-api-key " : "${ANTHROPIC_API_KEY}"
}
}
]
}
}
${SECRET_KEY} 引用会解析为您在 LangSmith 工作区设置 中存储的密钥。在创建引用它们的模板之前,请先在这些设置中配置密钥。
**工作区密钥。**对于不需要代理注入的 API 密钥(例如 Agent 服务器本身使用的密钥,而不是沙箱代码使用的密钥),请将它们作为 LangSmith 工作区密钥 存储。这些在运行时作为环境变量对工作区中的所有 Agent 可用。
避免通过环境变量或文件上传将密钥传递给沙箱。Agent 可以读取沙箱内任何可访问的文件或环境变量,包括凭证。认证代理将密钥完全隔离在沙箱之外。
防护栏
生产环境中的 Agent 会自主运行,这意味着它们可能会无限循环、达到速率限制或处理包含敏感信息的用户数据。Deep Agents 提供两层保护:
权限 :声明性允许/拒绝规则,控制 Agent 可以读取或写入哪些文件和目录。使用权限将 Agent 隔离到工作目录、保护敏感文件或强制执行只读记忆。
中间件 :包装模型和工具调用的钩子,用于速率限制、错误处理和数据隐私。
速率限制
这里的速率限制指的是限制 Agent 在单个运行中的 LLM 和工具使用,而不是 API 网关对传入请求的速率限制。
如果没有限制,一个困惑的 Agent 可能会通过在同一个工具调用上循环或发出数百个模型调用,在几分钟内耗尽您的 LLM API 预算。为每次运行的模型调用和工具执行设置上限:
from deepagents import create_deep_agent
from langchain . agents . middleware import ModelCallLimitMiddleware , ToolCallLimitMiddleware
agent = create_deep_agent (
model = "claude-sonnet-4-6" ,
middleware = [
ModelCallLimitMiddleware ( run_limit = 50 ),
ToolCallLimitMiddleware ( run_limit = 200 ),
],
)
使用 run_limit 限制单个调用内的调用(每次轮次重置)。使用 thread_limit 限制整个对话的调用(需要检查点器)。请参阅 ModelCallLimitMiddleware 和 ToolCallLimitMiddleware 了解完整的配置。
错误处理
并非所有错误都应该以相同的方式处理。瞬态故障(网络超时、速率限制)应该自动重试。LLM 可以恢复的错误(工具输出不良、解析失败)应该反馈给模型。需要人工输入的错误应该暂停 Agent。有关完整细分和代码示例,请参阅适当处理错误 。
中间件处理瞬态情况。模型调用和工具调用各有自己的指数退避重试中间件。如果您的主要模型提供商完全宕机,回退中间件会切换到备选方案:
from deepagents import create_deep_agent
from langchain . agents . middleware import (
ModelFallbackMiddleware ,
ModelRetryMiddleware ,
ToolRetryMiddleware ,
)
agent = create_deep_agent (
model = "claude-sonnet-4-6" ,
middleware = [
# 在速率限制、超时和 5xx 错误时重试模型调用
ModelRetryMiddleware ( max_retries = 3 , backoff_factor = 2.0 , initial_delay = 1.0 ),
# 如果主要模型完全宕机,回退到备选方案
ModelFallbackMiddleware ( "gpt-4.1" ),
# 重试命中外部 API 的特定工具(不是所有工具)
ToolRetryMiddleware (
max_retries = 2 ,
tools = [ "search" , "fetch_url" ],
retry_on = ( TimeoutError , ConnectionError ),
),
],
)
将 ToolRetryMiddleware 作用域限定为特定工具,而不是重试所有内容。失败的 filesystem read_file 不会从重试中受益,但超时的网络搜索可能会。请参阅 ModelRetryMiddleware 和 ModelFallbackMiddleware 了解完整的配置。
数据隐私
如果您的 Agent 处理可能包含电子邮件、信用卡号码或其他 PII 的用户输入,您可以在数据到达模型或存储在日志中之前检测和处理它:
from deepagents import create_deep_agent
from langchain . agents . middleware import PIIMiddleware
agent = create_deep_agent (
model = "claude-sonnet-4-6" ,
middleware = [
PIIMiddleware ( "email" , strategy = "redact" , apply_to_input = True ),
PIIMiddleware ( "credit_card" , strategy = "mask" , apply_to_input = True ),
],
)
策略包括 redact(替换为 [REDACTED_EMAIL])、mask(部分掩码,如 ****-****-****-1234)、hash(确定性哈希)和 block(抛出错误)。您还可以为特定领域的模式编写自定义检测器。
请参阅 PIIMiddleware 了解完整的配置。
有关可用的完整中间件列表,请参阅预构建中间件 。
Deep Agents 使用 useStream 将您的 UI 连接到 Agent 后端。useStream 是一个前端钩子(可用于 React、Vue、Svelte 和 Angular),可实时从您的 Agent 流式传输消息、子代理进度和自定义状态。
在本地,useStream 指向 http://localhost:2024。在生产环境中,将其指向您的 LangSmith Deployment 并配置重新连接,这样用户就不会在连接断开时丢失进度。
import { useStream } from "@langchain/react" ;
function App () {
const stream = useStream < typeof agent > ( {
apiUrl : "https://your-deployment.langsmith.dev" ,
assistantId : "agent" ,
reconnectOnMount : true , // 页面刷新或导航后恢复流
fetchStateHistory : true , // 挂载时加载完整的线程历史
} ) ;
}
reconnectOnMount 自动接取进行中的运行。如果用户在 Agent 工作时刷新页面,他们会看到它继续而不是空白屏幕。fetchStateHistory 加载该线程的完整对话历史,因此返回的用户可以看到之前的消息。
对于生成许多子代理的 Deep Agent 工作流,在提交时设置较高的 recursionLimit 以避免切断长时间运行的执行:
stream . submit (
{ messages : [ { type : "human" , content : text } ] },
{
streamSubgraphs : true ,
config : { recursionLimit : 10000 },
},
) ;
有关 Deep Agents 特有的 UI 模式(如子代理卡片、待办事项列表和自定义状态渲染),请参阅前端指南 。
将这些文档 连接到 Claude、VSCode 等工具,通过 MCP 获取实时答案。