前面几篇文章介绍了 Deep Agents 的 Planning、Tools、Filesystem 和 Backend。通过这些机制,Agent 已经能够规划任务、管理文件,并在多个步骤之间维护工作状态。
但对于 Coding Agent、数据分析 Agent 等应用,仅有这些能力还不够。Agent 不仅需要编写代码,还需要实际运行程序、执行测试,并根据结果继续工作。
Deep Agents 通过 Shell、execute 和 Sandbox 支持这类能力。
这三个概念分别对应命令执行机制、框架调用接口和实际运行环境。理解它们之间的关系,是构建具备自主执行能力的 Agent 的重要基础。
一、工具调用的能力边界
在普通 Agent 中,执行能力通常来自预先定义好的 Tools。
例如,我们可以定义一个 calculate() 工具,让 Agent 完成计算;或者定义一个 query_database() 工具,让它查询数据库。
这种方式有一个明显特点:Agent 能做什么,取决于我们提前提供了哪些工具。
假设需要完成下面的任务:
读取一个 CSV 文件,统计各月份的销售额,找出增长最快的月份,并生成分析报告。
为此,可能需要提供 CSV 解析、数据过滤、统计计算和报告生成等多个工具。
如果后续增加其他相关功能或更复杂的功能,还需要提供其他工具。
另一种方式是让 Agent 自行编写 Python 脚本,通过运行环境执行代码,再读取执行结果。
这样,Agent 不必依赖大量针对具体业务编写的工具。只要运行环境具备相应能力,就可以组合已有的程序、库和命令完成任务。
这也是 Shell 对 Deep Agents 的主要价值。
不过,Shell 并不会替代所有 Tools。两者解决的是不同类型的问题。
对于数据库写入、支付、订单操作等业务行为,显式定义的工具通常更容易控制参数、权限以及安全验证。
Shell 更适合代码执行、文件处理、自动化测试,以及需要结合操作系统工具的任务。
二、文件操作与命令执行
前一篇介绍 Backend 时,已经区分了 StateBackend、FilesystemBackend 等不同实现。
这里需要进一步明确:文件可读写,并不意味着命令可以执行。
Deep Agents 默认使用 StateBackend。它可以为 Agent 提供文件管理能力,但不会因此获得操作系统的 Shell。
FilesystemBackend 可以操作真实文件,同样不提供通用命令执行能力。
例如,Agent 可以通过 write_file 创建一个 analysis.py 文件,但不能仅凭文件操作工具运行:
python analysis.py
要完成这一步,Backend 还需要支持命令执行接口。
Deep Agents 的 Backend 类型
Deep Agents 通过统一的 Backend 接口支持不同的存储和执行环境,主要区别在于文件存储方式及是否支持命令执行。
| Backend | 主要特点 | Shell 执行 |
|---|---|---|
StateBackend | 默认实现,文件保存在 Agent State 中 | 否 |
FilesystemBackend | 读写本地真实文件 | 否 |
StoreBackend | 基于 LangGraph Store,支持跨线程存储 | 否 |
ContextHubBackend | 基于 LangSmith Context Hub,支持版本化管理 | 否 |
CompositeBackend | 按路径组合、路由不同 Backend | 取决于默认 Backend |
LocalShellBackend | 本地文件操作与命令执行,无系统隔离 | 是 |
LangSmithSandbox | LangSmith 托管的隔离执行环境 | 是 |
| 第三方 Sandbox Backend | E2B、Daytona、Modal、Vercel 等执行环境 | 是 |
其中,StateBackend、FilesystemBackend 和 StoreBackend 主要解决文件存储问题;LocalShellBackend 和 Sandbox Backend 则进一步提供 Shell 执行能力。
CompositeBackend 比较特殊:文件操作按路径路由,而命令执行始终交给默认 Backend。
需要注意,Backend 支持命令执行,不代表具备安全隔离。 LocalShellBackend 直接运行本地命令,而 Sandbox Backend 通常依赖独立的隔离环境。
Shell、Execute 与 Sandbox
这三个概念容易混淆,但职责不同。
可以把它们理解为:execute 是命令入口,Shell 是命令执行器,Sandbox 是运行命令的工作环境。
例如,Agent 需要运行脚本:
python analysis.py
Agent 并不直接执行这条命令,而是调用 execute 工具。框架通过 Backend 将命令交给 Shell,由 Shell 启动 Python 进程,并将执行结果返回给 Agent。
整个过程如下:
Agent
│
▼
execute(提交命令)
│
▼
Backend(转发命令)
│
▼
Shell(执行命令)
│
▼
返回输出与退出码
Sandbox 决定这条命令在哪里运行,以及受到哪些隔离限制。例如,使用 LocalShellBackend 时,命令直接在本机执行;使用远程 Sandbox Backend 时,命令则在隔离的远程环境中执行。
三、执行接口的内部机制
Deep Agents 使用 SandboxBackendProtocol 描述支持命令执行的 Backend。
这个协议扩展了基础文件操作协议 BackendProtocol,增加了 execute()、aexecute() 等命令执行接口。
其核心调用形式如下:
result = backend.execute(
"python analysis.py",
timeout=60,
)
print(result.output)
print(result.exit_code)
print(result.truncated)
这里展示的是应用程序直接调用 Backend 的方式。Agent 通过 execute 工具执行命令时,也会使用相应的 Backend 接口。
返回结果中有三个重要信息。
output:命令执行的输出,包含标准输出和错误输出。exit_code:进程退出码。truncated:输出内容是否经过截断。
通常,退出码为 0 表示进程正常完成,非零值表示出现错误。不过,进程正常退出并不等于结果一定正确。
例如,Python 脚本可能成功执行,但由于计算逻辑错误,生成了不准确的数据。
另外,不能简单地用工具消息的成功状态判断命令是否成功。即使 Shell 进程返回非零退出码,工具调用本身也可能正常完成,并将错误信息交还给 Agent。
真正判断命令执行结果时,应检查 exit_code。
Deep Agents 的 FilesystemMiddleware 负责向模型提供文件操作工具,并根据 Backend 的能力决定是否提供可用的 execute。
对于实现了 SandboxBackendProtocol 的 Backend,Agent 可以通过 execute 运行命令;不支持该协议的 Backend 则无法执行 Shell 命令。
也就是说,execute 并不是所有 Deep Agent 默认拥有的能力。
本地命令执行
Deep Agents 内置了 LocalShellBackend,适合在受控开发环境中使用。
from pathlib import Path
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend
backend = LocalShellBackend(
root_dir=Path("./workspace").resolve(),
virtual_mode=True,
timeout=60,
)
agent = create_deep_agent(
model="openai:gpt-5.5",
backend=backend,
)
配置完成后,Agent 就可以通过 execute 调用本地 Shell。
LocalShellBackend 继承自 FilesystemBackend,同时实现 SandboxBackendProtocol,因此兼具文件操作和命令执行能力。
但这里有一个必须明确的细节。
root_dir 是文件操作的根目录,也是 Shell 命令的工作目录。virtual_mode=True 主要约束文件工具的路径解析,并不能限制 Shell 访问工作目录以外的文件。
LocalShellBackend 实际通过本地进程执行命令,不提供真正的系统隔离。
因此,它适合可信、受控的个人开发环境,不适合直接用于公开的多用户应用。
四、隔离工作空间的结构
真正需要自主执行代码的 Agent,通常应该使用 Sandbox。
Sandbox 可以理解为一个独立的运行工作空间,内部具备文件系统、进程环境和必要的软件依赖。
Agent 在其中创建文件、安装依赖、执行命令或生成结果,而不需要直接操作宿主机的工作环境。
从运行结构来看,可以将其划分为四层:
用户任务
│
▼
Deep Agent
│ 规划任务、调用工具
▼
FilesystemMiddleware
│ read_file / write_file / execute
▼
Sandbox Backend
│ 文件接口、命令执行接口
▼
Sandbox Runtime
│
├── Filesystem
├── Shell / Processes
├── Python / Node.js
├── Dependencies
└── Generated Artifacts
这里的 Sandbox Runtime 是真正运行程序的地方。
例如,Agent 决定运行 pytest,框架将命令传给 Sandbox Backend,后者通过运行环境执行测试,再把输出和退出码返回给 Agent。
Agent 根据测试结果判断是否需要继续修改代码。
需要注意,Sandbox 不一定由 Deep Agents 自身创建。
它可以由 Docker、虚拟机或云端执行平台提供。Deep Agents 通过对应的 Backend 接入执行环境。
不同运行方式的区别主要在于执行位置及隔离边界。
| 运行方式 | 命令执行位置 | 隔离能力 |
|---|---|---|
本机 LocalShellBackend | 本地操作系统 | 无系统级隔离 |
Docker 内的 LocalShellBackend | Docker 容器内部 | 容器级隔离 |
| 远程 Sandbox Backend | 远程 Sandbox | 取决于服务提供方的隔离实现 |
这里的 Docker 方案,是将 Agent 程序和 LocalShellBackend 一起放入容器运行,并不是让本机 Agent 自动获得一个远程 Sandbox Backend。
五、实际任务示例
下面通过一个简单的数据分析任务,串联整个过程。
目标是让 Agent 读取销售数据,编写 Python 脚本完成计算,执行脚本,并生成 Markdown 报告。
为了降低复现成本,这里使用 LocalShellBackend,不依赖额外的云端 Sandbox 服务。
准备运行环境
首先安装依赖:
pip install -U deepagents langchain-openai
配置 OPENAI_API_KEY 环境变量,并确保本地可以通过 python 命令运行 Python。
本例使用 Python 标准库处理 CSV,不需要安装 Pandas 等数据分析库。
特别说明:下面示例仅用于可信、受控的开发环境。运行前应确认程序所在机器没有不应被 Agent 访问的敏感文件或权限。
创建执行工作空间
首先准备一个工作目录,将测试数据写入其中。
from pathlib import Path
import os
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend
workspace = Path("./workspace").resolve()
workspace.mkdir(parents=True, exist_ok=True)
# 写入测试数据
(workspace / "sales.csv").write_text(
"date,amount\n"
"2026-10-01,100\n"
"2026-10-02,120\n"
"2026-10-03,90\n"
"2026-10-04,150\n",
encoding="utf-8",
)
backend = LocalShellBackend(
root_dir=workspace,
virtual_mode=True,
timeout=60,
env={"PATH": os.environ.get("PATH", "")},
)
这里有两个细节值得注意。
第一个是 virtual_mode=True。
启用虚拟路径后,Agent 通过 read_file 访问 /sales.csv,实际对应的是本地 workspace/sales.csv 文件。
第二个是 Shell 的工作目录。
execute 调用的 Shell 会以 workspace 作为当前工作目录。因此,执行脚本时使用:
python analysis.py
而不是:
python /analysis.py
因为文件工具的虚拟路径与操作系统的真实路径并不是同一个概念。
此外,env 显式指定了传递给 Shell 的环境变量。LocalShellBackend 默认不会继承父进程的全部环境变量,这有助于减少直接暴露给子进程的配置,但不能作为完整的安全隔离措施。
创建并运行 Agent
接下来,将 Backend 传入 create_deep_agent()。
agent = create_deep_agent(
model="openai:gpt-5.5",
backend=backend,
system_prompt=(
"你是一名 Python 数据分析工程师。"
"使用工作空间中的文件完成任务。"
"文件操作工具使用 / 开头的虚拟路径。"
"Shell 命令在工作空间目录中执行。"
"请先读取 /sales.csv,"
"再编写 /analysis.py,"
"使用 python analysis.py 执行计算。"
"仅使用 Python 标准库。"
"最终报告保存为 /report.md。"
"必须根据实际执行结果生成报告。"
"不得将未经运行验证的结果描述为已验证。"
),
)
result = agent.invoke(
{
"messages": [{
"role": "user",
"content": (
"分析 sales.csv 中的销售数据。"
"计算总销售额、日均销售额和最高单日销售额。"
"生成 Python 脚本并实际运行。"
"检查执行结果后生成 Markdown 报告。"
),
}]
},
config={"recursion_limit": 40},
)
print(result["messages"][-1].content)
在这个示例中,Agent 可以自主决定如何组织 Python 代码,以及何时调用 execute。
典型的执行过程如下:
读取 /sales.csv
│
▼
生成 /analysis.py
│
▼
execute("python analysis.py")
│
▼
获取 output / exit_code
│
▼
检查计算结果
│
▼
生成 /report.md
对于给定数据,正确的计算结果应为:
| 指标 | 结果 |
|---|---|
| 总销售额 | 460 |
| 日均销售额 | 115 |
| 最高单日销售额 | 150 |
这些数值来自输入数据的直接计算。实际 Agent 是否完成对应步骤,需要以执行记录和生成的文件为准。
检查执行产物
由于使用的是本地工作空间,应用程序不需要通过 download_files() 下载结果。
我们可以直接读取生成的文件。
继续在上面的代码后添加:
script_path = workspace / "analysis.py"
report_path = workspace / "report.md"
if not script_path.is_file():
raise RuntimeError("Agent 未生成分析脚本")
if not report_path.is_file():
raise RuntimeError("Agent 未生成分析报告")
# 再次执行脚本
check = backend.execute(
"python analysis.py",
timeout=60,
)
print("exit_code:", check.exit_code)
print("output:", check.output)
if check.exit_code != 0:
raise RuntimeError("分析脚本执行失败")
print(report_path.read_text(encoding="utf-8"))
这里增加了一次由应用程序主动发起的命令执行。
Agent 在执行过程中可以调用 execute,应用程序也可以直接调用 backend.execute()。
两者使用同一个 Backend,但调用主体不同。
Agent 的工具调用是模型自主决策的一部分;应用程序直接调用 Backend,则可以用于执行确定性的验证逻辑,不需要模型再次参与。
到这里,一个基本的数据分析 Agent 就已经可以运行。
它不仅能读取数据和编写代码,还可以实际执行程序,再根据执行结果生成报告。
文件与执行环境的关系
通过这个例子,还可以看到两个容易忽略的设计细节。
第一个是文件操作与命令执行需要使用同一工作空间。
Agent 使用 write_file 生成脚本,随后通过 execute 执行。如果两个接口指向不同的环境,就可能出现文件已经创建,但命令无法找到文件的问题。
第二个是任务完成不等于产物已经持久化。
在本地示例中,报告保存在 workspace/report.md。
在 Docker 中,使用 Bind Mount 或 Volume 可以让文件在容器删除后继续保留。
而对于远程 Sandbox,通常需要通过文件传输接口或外部对象存储,将产物保存到业务系统中。
这些方式虽然不同,但 Deep Agents 面向 Agent 的文件操作和命令执行接口保持相对统一。
这正是 Backend 抽象的重要价值:Agent 不需要关心底层具体使用哪种运行环境,只需要围绕文件、命令和执行反馈完成任务。
六、执行结果的可靠判断
Shell 能让 Agent 执行代码,但命令运行成功不代表任务完成。
实际开发中,应关注三个方面:
-
执行验证:不能只依赖 Agent 的最终回答,还应检查
exit_code、错误输出和生成的文件。对于关键任务,需要通过独立测试或断言验证结果。 -
错误处理:Agent 应根据执行反馈修正问题,而不是盲目重试。例如,依赖缺失需要调整环境,测试失败则需要检查代码逻辑。
-
输出控制:构建和测试日志可能占用大量 Token。
LocalShellBackend可通过max_output_bytes限制输出大小,也可以将完整日志保存到文件,让 Agent 按需读取。
核心原则是:以实际执行结果验证任务完成情况,同时控制反馈进入模型上下文的成本。
七、工程实践的设计取舍
并不是所有 Agent 都需要 Shell。
对于固定 API 调用、数据库操作和结构化业务流程,明确定义的 Tools 更容易维护和控制。
而运行测试、构建项目、执行脚本等任务,则更适合使用 Shell,减少对专用工具的依赖。
在实际部署中,我们还需关注三个边界。
权限边界:Sandbox 应遵循最小权限原则,避免直接访问宿主机凭据、生产数据库和内部网络,敏感密钥应按需授权。
资源边界:除了命令超时,还应限制 CPU、内存、磁盘和网络资源,防止异常任务影响系统稳定性。
操作边界:删除文件、访问外部服务、发布代码等高风险操作,可以引入 Human-in-the-loop 审批,但审批不能代替环境隔离。
从架构上看,Deep Agents 通过 Backend 将文件操作与命令执行整合到同一工作空间,使 Agent 能够连续完成文件生成、代码执行、结果检查和后续修正。
社区讨论
参与讨论
有问题或想法?欢迎继续讨论。