execute 工具。当您配置一个沙箱后端时,代理将获得:
-
所有标准文件系统工具 (
ls,read_file,write_file,edit_file,delete,glob,grep) -
用于在沙箱中运行任意 Shell 命令的
execute工具 - 一个保护您主机系统的安全边界
为什么使用沙箱?
沙箱用于保障安全性。 它们允许代理执行任意代码、访问文件和使用网络,而不会危及您的凭据、本地文件或主机系统。 当代理自主运行时,这种隔离至关重要。 沙箱特别适用于:- 编程代理:自主运行的代理可以使用 Shell、Git、克隆仓库(许多提供商提供原生 Git API,例如 Daytona 的 Git 操作),并运行 Docker-in-Docker 以构建和测试流水线。
- 数据分析代理— 在安全、隔离的环境中加载文件、安装数据分析库(pandas、numpy 等)、运行统计计算并创建如 PowerPoint 演示文稿等输出。
正在使用 Deep Agents Code? Deep Agents Code 通过
--sandbox 标志内置沙箱支持。有关 Deep Agents Code 的特定设置、标志(--sandbox-id, --sandbox-setup)和示例,请参阅 使用远程沙箱。如果您在寻找 LangSmith 沙箱: LangSmith 提供您可以直接从 LangSmith UI 或 SDK 使用的第一方托管沙箱,无需第三方账户。有关托管沙箱资源、快照、服务 URL 和认证代理,请参阅 LangSmith 沙箱。
基本用法
这些示例假设您已经使用提供商的 SDK 创建了沙箱/devbox 并设置了凭据。有关注册、身份验证和提供商特定生命周期的详细信息,请参阅可用提供商。- LangSmith
- Daytona
- E2B
- Modal
- Runloop
- Vercel
pip install "langsmith[sandbox]"
uv add "langsmith[sandbox]"
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="google_genai:gemini-3.6-flash"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="openai:gpt-5.5"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="anthropic:claude-sonnet-4-6"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="openrouter:z-ai/glm-5.2"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="fireworks:accounts/fireworks/models/glm-5p2"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="baseten:zai-org/GLM-5.2"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends import LangSmithSandbox
from langchain_anthropic import ChatAnthropic
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="ollama:north-mini-code-1.0"),
system_prompt="你是一个拥有沙盒访问权限的Python编程助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
client.delete_sandbox(ls_sandbox.name)
pip install langchain-daytona
uv add langchain-daytona
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="google_genai:gemini-3.6-flash"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="openai:gpt-5.5"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="anthropic:claude-sonnet-4-6"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="openrouter:z-ai/glm-5.2"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="fireworks:accounts/fireworks/models/glm-5p2"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="baseten:zai-org/GLM-5.2"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
from daytona import Daytona
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="ollama:north-mini-code-1.0"),
system_prompt="你是一个拥有沙箱访问权限的Python编码助手。",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型Python包并运行pytest",
}
]
}
)
finally:
sandbox.stop()
pip install langchain-e2b
uv add langchain-e2b
from e2b import Sandbox
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_e2b import E2BSandbox
# 创建一个 E2B 沙箱实例
e2b_sandbox = Sandbox.create()
# 使用 E2B 沙箱包装器
backend = E2BSandbox(sandbox=e2b_sandbox)
# 创建一个可以访问沙箱的代理
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="你是一个可以访问沙箱的 Python 编程助手。",
backend=backend,
)
try:
# 与代理交互,执行一个任务
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型 Python 包并运行 pytest",
}
]
}
)
finally:
# 关闭沙箱
e2b_sandbox.kill()
pip install langchain-modal
uv add langchain-modal
import modal
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_modal import ModalSandbox
# 查找你现有的 Modal 应用
app = modal.App.lookup("your-app")
# 创建一个 Modal 沙箱实例
modal_sandbox = modal.Sandbox.create(app=app)
# 使用 Modal 沙箱包装器
backend = ModalSandbox(sandbox=modal_sandbox)
# 创建一个可以访问沙箱的代理
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="你是一个可以访问沙箱的 Python 编程助手。",
backend=backend,
)
try:
# 与代理交互,执行一个任务
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型 Python 包并运行 pytest",
}
]
}
)
finally:
# 终止沙箱
modal_sandbox.terminate()
pip install langchain-runloop
uv add langchain-runloop
import os
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_runloop import RunloopSandbox
from runloop_api_client import RunloopSDK
# 使用 API 密钥初始化 Runloop 客户端
client = RunloopSDK(bearer_token=os.environ["RUNLOOP_API_KEY"])
# 创建一个新的开发箱
devbox = client.devbox.create()
# 使用 Runloop 开发箱包装器
backend = RunloopSandbox(devbox=devbox)
# 创建一个可以访问沙箱的代理
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="你是一个可以访问沙箱的 Python 编程助手。",
backend=backend,
)
try:
# 与代理交互,执行一个任务
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型 Python 包并运行 pytest",
}
]
}
)
finally:
# 关闭开发箱
devbox.shutdown()
pip install langchain-vercel-sandbox
uv add langchain-vercel-sandbox
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_vercel_sandbox import VercelSandbox
from vercel.sandbox import Sandbox
# 创建一个指定 Python 运行时的沙箱
sandbox = Sandbox.create(runtime="python3.13")
# 使用 Vercel 沙箱包装器
backend = VercelSandbox(sandbox=sandbox)
# 创建一个可以访问沙箱的代理
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="你是一个可以访问沙箱的 Python 编程助手。",
backend=backend,
)
try:
# 与代理交互,执行一个任务
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个小型 Python 包并运行 pytest",
}
]
}
)
finally:
# 停止沙箱
sandbox.stop()
LangSmith 跟踪显示哪些 Shell 命令在沙箱内运行以及代理如何使用文件系统工具。请按照可观测性快速入门进行设置。有关托管沙箱托管,请参阅 LangSmith 沙箱。我们建议您也设置 LangSmith Engine,它可以监控您的跟踪记录、检测问题并提出修复建议。
可用提供商
有关提供商特定的设置、身份验证和生命周期详细信息,请参阅沙箱集成。 没看到您的提供商?您可以实现自己的沙箱后端。请参阅贡献沙箱集成。生命周期和作用域
大多数应用程序选择每个会话一个沙箱(会话作用域)或同一个助手的所有会话共享一个沙箱(助手作用域)。 沙箱会消耗资源并产生成本,直到它们被关闭。请确保在不再使用沙箱时将其关闭。 有关完整的生命周期表、异步图工厂说明、TTL 行为、LangGraph Deployment 配线以及客户端示例,请参阅投产指南中的沙箱生命周期。会话作用域(默认)
每个对话拥有自己的沙箱。首次运行时创建它;同一会话上的后续轮次会复用它。当会话结束或沙箱 TTL 到期时,环境将消失。如以下示例所示,使用沙箱名称或元数据存储映射,以便每次运行都解析到相同的沙箱。当用户可能在空闲后返回时,请为沙箱配置 TTL,以便提供商自动删除或归档空闲环境。
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="google_genai:gemini-3.6-flash",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="openai:gpt-5.5",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="openrouter:z-ai/glm-5.2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="baseten:zai-org/GLM-5.2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
thread_id = config["configurable"]["thread_id"]
sandbox_name = f"thread-{thread_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(
name=sandbox_name,
idle_ttl_seconds=3600, # TTL: 空闲时清理
)
return create_deep_agent(
model="ollama:north-mini-code-1.0",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
助手作用域
同一助手上的每个会话都复用一个沙箱。文件、已安装的包和克隆的仓库会在对话之间持久存在。助手作用域的沙箱会随时间在沙箱内累积状态。请与您的沙箱提供商配置 TTL,使用快照定期重置,或实现清理逻辑,以防止磁盘和内存无限增长。
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="google_genai:gemini-3.6-flash",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="openai:gpt-5.5",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="openrouter:z-ai/glm-5.2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="baseten:zai-org/GLM-5.2",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langchain_core.runnables import RunnableConfig
from langsmith.sandbox import SandboxClient
client = SandboxClient()
async def agent(config: RunnableConfig):
assistant_id = config["configurable"]["assistant_id"]
sandbox_name = f"assistant-{assistant_id}"
existing = [
sb
for sb in client.list_sandboxes()
if getattr(sb, "name", None) == sandbox_name
]
if existing:
ls_sandbox = existing[0]
else:
ls_sandbox = client.create_sandbox(name=sandbox_name)
return create_deep_agent(
model="ollama:north-mini-code-1.0",
backend=LangSmithSandbox(sandbox=ls_sandbox),
)
集成模式
根据代理运行的位置,有两种将代理与沙箱集成的架构模式。代理在沙箱内模式
代理在沙箱内部运行,您通过网络与其通信。您构建一个预装了代理框架的 Docker 或 VM 镜像,在沙箱内运行它,并从外部连接以发送消息。 优点:- ✅ 与本地开发高度相似。
- ✅ 代理与环境紧密耦合。
- 🔴 API 密钥必须存在于沙箱内部(安全风险)。
- 🔴 更新需要重新构建镜像。
- 🔴 需要通信基础设施(WebSocket 或 HTTP 层)。
FROM python:3.11
RUN pip install deepagents-code
沙箱作为工具模式
代理在您的机器或服务器上运行。当需要执行代码时,它调用沙箱工具(如execute、read_file 或 write_file),这些工具调用提供商的 API 在远程沙箱中运行操作。
优点:
- ✅ 无需重新构建镜像即可即时更新代理代码。
- ✅ 代理状态与执行更清晰地分离。
- API 密钥保留在沙箱外部。
- 沙箱故障不会丢失代理状态。
- 可以选择在多个沙箱中并行运行任务。
- ✅ 仅为执行时间付费。
- 🔴 每次执行调用都有网络延迟。
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="google_genai:gemini-3.6-flash",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="openai:gpt-5.5",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="openrouter:z-ai/glm-5.2",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="baseten:zai-org/GLM-5.2",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
from deepagents import create_deep_agent
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
agent = create_deep_agent(
model="ollama:north-mini-code-1.0",
backend=backend,
system_prompt="您是一个具有沙盒访问权限的编程助手。您可以在沙盒中创建和运行代码。",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "创建一个hello world Python脚本并运行它",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)
沙箱工作原理
隔离边界
所有沙箱提供商都保护您的主机系统免受代理的文件系统和 Shell 操作的影响。代理无法读取您的本地文件、访问您机器上的环境变量或干扰其他进程。然而,沙箱本身不能防止:- 上下文注入:控制代理部分输入的攻击者可以指示其在沙箱内运行任意命令。沙箱是隔离的,但代理在其中有完全控制权。
- 网络数据渗出:除非网络访问被阻止,否则上下文注入的代理可以通过 HTTP 或 DNS 从沙箱发送数据。一些提供商支持阻止网络访问(例如 Modal 上的
blockNetwork: true)。
execute 方法
沙箱后端架构简单:提供商唯一必须实现的方法是 execute(),它运行 Shell 命令并返回其输出。
所有其他文件系统操作(read, write, edit, delete, ls, glob, grep)都由 BaseSandbox 基类在 execute() 之上构建,该基类构造脚本并通过 execute() 在沙箱内运行它们。
这种设计意味着:
- 添加新提供商很简单。 只需实现
execute()——基类会处理其他所有事情。 execute工具是条件可用的。 在每次模型调用时,工具箱会检查后端是否实现了SandboxBackendProtocol。如果没有,则该工具会被过滤掉,代理永远不会看到它。
execute 工具时,它提供一个 command 字符串并返回合并的 stdout/stderr、退出代码,如果输出过大则返回截断通知。
您也可以在应用程序代码中直接调用后端 execute() 方法。
- LangSmith
- AgentCore
- Daytona
- E2B
- Modal
- NVIDIA OpenShell
- Runloop
- Vercel
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
result = backend.execute("python --version")
print(result.output)
pip install langchain-agentcore-codeinterpreter
uv add langchain-agentcore-codeinterpreter
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
from langchain_agentcore_codeinterpreter import AgentCoreSandbox
interpreter = CodeInterpreter(region="us-west-2")
interpreter.start()
backend = AgentCoreSandbox(interpreter=interpreter)
try:
result = backend.execute("python3 --version")
print(result.output)
finally:
interpreter.stop()
pip install langchain-daytona
uv add langchain-daytona
from daytona import Daytona
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
result = backend.execute("python --version")
print(result.output)
pip install langchain-e2b
uv add langchain-e2b
from e2b import Sandbox
from langchain_e2b import E2BSandbox
e2b_sandbox = Sandbox.create()
sandbox = E2BSandbox(sandbox=e2b_sandbox)
try:
result = sandbox.execute("python --version")
print(result.output)
finally:
e2b_sandbox.kill()
import modal
from langchain_modal import ModalSandbox
app = modal.App.lookup("your-app")
modal_sandbox = modal.Sandbox.create(app=app)
backend = ModalSandbox(sandbox=modal_sandbox)
result = backend.execute("python --version")
print(result.output)
pip install langchain-nvidia-openshell
uv add langchain-nvidia-openshell
import openshell
from langchain_nvidia_openshell import OpenShellSandbox
with openshell.Sandbox(delete_on_exit=True) as sandbox:
backend = OpenShellSandbox(sandbox=sandbox)
result = backend.execute("python3 --version")
print(result.output)
pip install langchain-runloop
uv add langchain-runloop
from runloop_api_client import RunloopSDK
from langchain_runloop import RunloopSandbox
api_key = "..."
client = RunloopSDK(bearer_token=api_key)
devbox = client.devbox.create()
backend = RunloopSandbox(devbox=devbox)
try:
result = backend.execute("python --version")
print(result.output)
finally:
devbox.shutdown()
pip install langchain-vercel-sandbox
uv add langchain-vercel-sandbox
from vercel.sandbox import Sandbox
from langchain_vercel_sandbox import VercelSandbox
sandbox = Sandbox.create(runtime="python3.13")
backend = VercelSandbox(sandbox=sandbox)
try:
result = backend.execute("python --version")
print(result.output)
finally:
sandbox.stop()
4
[Command succeeded with exit code 0]
bash: foobar: command not found
[Command failed with exit code 127]
read_file 增量访问它。这可以防止上下文窗口溢出。
文件访问的两个层面
文件进出沙箱有两种截然不同的方式,了解何时使用每种方式很重要: 代理文件系统工具:read_file, write_file, edit_file, delete, ls, glob, grep, execute 是 LLM 在执行期间调用的工具。这些工具通过沙箱内的 execute() 执行。代理使用它们来读取代码、写入文件和运行命令作为其任务的一部分。
文件传输 API:您的应用程序代码调用的 uploadFiles() 和 downloadFiles() 方法。这些方法使用提供商的原生文件传输 API(而非 Shell 命令),旨在在主机环境和沙箱之间移动文件。使用这些方法可以:
- 在代理运行前用源代码、配置或数据填充沙箱
- 在代理完成后检索工件(生成的代码、构建输出、报告)
- 预填充代理将需要的依赖项
处理文件
deepagents 沙箱后端支持文件传输 API,用于在应用程序和沙箱之间移动文件。填充沙箱
在代理运行之前,使用upload_files() 来填充沙箱。路径必须是绝对路径,内容为 bytes 类型:
- LangSmith
- AgentCore
- Daytona
- E2B
- Modal
- Runloop
- Vercel
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
backend.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
pip install langchain-agentcore-codeinterpreter
uv add langchain-agentcore-codeinterpreter
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
from langchain_agentcore_codeinterpreter import AgentCoreSandbox
interpreter = CodeInterpreter(region="us-west-2")
interpreter.start()
backend = AgentCoreSandbox(interpreter=interpreter)
backend.upload_files(
[
("hello.py", b"print('Hello')\n"),
("data.csv", b"name,value\na,1\nb,2\n"),
]
)
pip install langchain-daytona
uv add langchain-daytona
from daytona import Daytona
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
backend.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
pip install langchain-e2b
uv add langchain-e2b
from e2b import Sandbox
from langchain_e2b import E2BSandbox
e2b_sandbox = Sandbox.create()
sandbox = E2BSandbox(sandbox=e2b_sandbox)
try:
sandbox.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
finally:
e2b_sandbox.kill()
import modal
from langchain_modal import ModalSandbox
app = modal.App.lookup("your-app")
modal_sandbox = modal.Sandbox.create(app=app)
backend = ModalSandbox(sandbox=modal_sandbox)
backend.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
pip install langchain-runloop
uv add langchain-runloop
from runloop_api_client import RunloopSDK
from langchain_runloop import RunloopSandbox
api_key = "..."
client = RunloopSDK(bearer_token=api_key)
devbox = client.devbox.create()
backend = RunloopSandbox(devbox=devbox)
backend.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
pip install langchain-vercel-sandbox
uv add langchain-vercel-sandbox
from vercel.sandbox import Sandbox
from langchain_vercel_sandbox import VercelSandbox
sandbox = Sandbox.create(runtime="python3.13")
backend = VercelSandbox(sandbox=sandbox)
backend.upload_files(
[
("/src/index.py", b"print('Hello')\n"),
("/pyproject.toml", b"[project]\nname = 'my-app'\n"),
]
)
检索工件
在代理完成后,使用download_files() 从沙箱检索文件:
- LangSmith
- AgentCore
- Daytona
- E2B
- Modal
- Runloop
- Vercel
from deepagents.backends.langsmith import LangSmithSandbox
from langsmith.sandbox import SandboxClient
client = SandboxClient()
ls_sandbox = client.create_sandbox()
backend = LangSmithSandbox(sandbox=ls_sandbox)
results = backend.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"下载 {result.path} 失败: {result.error}")
pip install langchain-agentcore-codeinterpreter
uv add langchain-agentcore-codeinterpreter
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
from langchain_agentcore_codeinterpreter import AgentCoreSandbox
interpreter = CodeInterpreter(region="us-west-2")
interpreter.start()
backend = AgentCoreSandbox(interpreter=interpreter)
results = backend.download_files(["hello.py"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
interpreter.stop()
pip install langchain-daytona
uv add langchain-daytona
from daytona import Daytona
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
results = backend.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
pip install langchain-e2b
uv add langchain-e2b
from e2b import Sandbox
from langchain_e2b import E2BSandbox
e2b_sandbox = Sandbox.create()
sandbox = E2BSandbox(sandbox=e2b_sandbox)
try:
results = sandbox.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
finally:
e2b_sandbox.kill()
import modal
from langchain_modal import ModalSandbox
app = modal.App.lookup("your-app")
modal_sandbox = modal.Sandbox.create(app=app)
backend = ModalSandbox(sandbox=modal_sandbox)
results = backend.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
pip install langchain-runloop
uv add langchain-runloop
from runloop_api_client import RunloopSDK
from langchain_runloop import RunloopSandbox
api_key = "..."
client = RunloopSDK(bearer_token=api_key)
devbox = client.devbox.create()
backend = RunloopSandbox(devbox=devbox)
results = backend.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
pip install langchain-vercel-sandbox
uv add langchain-vercel-sandbox
from vercel.sandbox import Sandbox
from langchain_vercel_sandbox import VercelSandbox
sandbox = Sandbox.create(runtime="python3.13")
backend = VercelSandbox(sandbox=sandbox)
results = backend.download_files(["/src/index.py", "/output.txt"])
for result in results:
if result.content is not None:
print(f"{result.path}: {result.content.decode()}")
else:
print(f"Failed to download {result.path}: {result.error}")
在沙箱内部,代理使用文件系统工具 (
read_file, write_file)。upload_files 和 download_files 方法是供您的应用程序代码在主机和沙箱之间移动文件的。安全注意事项
沙箱将代码执行与您的主机系统隔离,但它们无法防止上下文注入。控制代理部分输入的攻击者可以指示其读取文件、运行命令或从沙箱内渗出数据。这使得沙箱内的凭据尤其危险。切勿将机密信息放入沙箱内。 API 密钥、令牌、数据库凭据和其他通过环境变量、挂载文件或
secrets 选项注入沙箱的机密信息,都可以被上下文注入的代理读取和渗出。这甚至适用于短期或范围受限的凭据——如果代理可以访问它们,那么攻击者也可以。安全处理机密信息
如果您的代理需要调用经过身份验证的 API 或访问受保护的资源,您有两个选择:- 将机密信息保留在沙箱外的工具中。 定义在主机环境(而非沙箱内部)运行的工具,并在其中处理身份验证。代理通过名称调用这些工具,但永远不会看到凭据。这是推荐的方法。
-
使用注入凭据的网络代理。 一些沙箱提供商支持代理,这些代理拦截来自沙箱的传出 HTTP 请求,并在转发之前附加凭据(例如
Authorization头)。代理永远不会看到机密信息——它只是向 URL 发出普通请求。此方法尚未在所有提供商中广泛提供。
如果您必须将机密信息注入沙箱(不推荐),请采取以下预防措施:
- 对所有工具调用启用人在回路审批,而不仅仅是敏感调用
- 阻止或限制沙箱的网络访问以限制渗出路径
- 使用尽可能窄的凭据范围和尽可能短的生命周期
- 监控沙箱网络流量以发现意外的出站请求
通用最佳实践
- 在应用程序中对沙箱输出采取行动之前先进行审查
- 在不需要时阻止沙箱网络访问
- 使用中间件过滤或编辑工具输出中的敏感模式
- 将沙箱内产生的一切都视为不受信任的输入
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

