外观
智能体生成代码、与文件系统交互并运行 shell 命令。由于我们无法预测智能体可能会做什么,因此隔离其环境非常重要,这样它就无法访问凭据、文件或网络。沙箱通过在智能体的执行环境与你的主机系统之间创建边界来提供这种隔离。
在 Deep Agents 中,沙箱是后端,它定义了智能体运行的环境。与只暴露文件操作的其他后端(State、Filesystem、Store)不同,沙箱后端还为智能体提供用于运行 shell 命令的 execute 工具。当你配置沙箱后端时,智能体会获得:
- 所有标准文件系统工具(
ls、read_file、write_file、edit_file、delete、glob、grep) - 所有标准文件系统工具(
ls、read_file、write_file、edit_file、glob、grep) - 用于在沙箱中运行任意 shell 命令的
execute工具 - 保护主机系统的安全边界
为什么要使用沙箱?
沙箱用于安全防护。 它们让智能体执行任意代码、访问文件和使用网络,而不会危及你的凭据、本地文件或主机系统。 当智能体自主运行时,这种隔离至关重要。
沙箱在以下场景尤其有用:
- 编码智能体:自主运行的智能体可以使用 shell、git、克隆仓库(许多提供商提供原生 git API,例如 Daytona 的 git 操作),并为构建和测试流水线运行 Docker-in-Docker
- 数据分析智能体——加载文件、安装数据分析库(pandas、numpy 等)、运行统计计算,并在安全、隔离的环境中创建 PowerPoint 演示文稿等输出
TIP
正在使用 Deep Agents Code? Deep Agents Code 通过 --sandbox 标志提供内置的沙箱支持。请参阅使用远程沙箱了解 Deep Agents Code 特有的设置、标志(--sandbox-id、--sandbox-setup)和示例。
INFO
如果你在寻找 LangSmith 沙箱: LangSmith 提供第一方托管的沙箱,你可以直接从 LangSmith UI 或 SDK 使用,无需第三方账户。有关托管沙箱资源、快照、服务 URL 和身份验证代理,请参阅 LangSmith 沙箱。
基本用法
这些示例假设你已经使用提供商的 SDK 创建了沙箱/devbox,并已设置好凭据。有关注册、身份验证和特定于提供商的生命周期详细信息,请参阅可用提供商。
ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "google-genai:gemini-3.6-flash" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "openai:gpt-5.5" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "anthropic:claude-sonnet-4-6" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "openrouter:openrouter:z-ai/glm-5.2" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "fireworks:accounts/fireworks/models/glm-5p2" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "baseten:zai-org/GLM-5.2" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { SandboxClient } from "langsmith/sandbox";
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "ollama:north-mini-code-1.0" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
void result;
} finally {
await client.deleteSandbox(lsSandbox.name);
}LangSmith
bash
pip install "langsmith[sandbox]"bash
uv add "langsmith[sandbox]"Daytona
bash
pip install langchain-daytonabash
uv add langchain-daytonaE2B
bash
pip install langchain-e2bbash
uv add langchain-e2bpython
from e2b import Sandbox
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_e2b import E2BSandbox
e2b_sandbox = Sandbox.create()
backend = E2BSandbox(sandbox=e2b_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="You are a Python coding assistant with sandbox access.",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a small Python package and run pytest",
}
]
}
)
finally:
e2b_sandbox.kill()Modal
bash
pip install langchain-modalbash
uv add langchain-modalpython
import modal
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_modal import ModalSandbox
app = modal.App.lookup("your-app")
modal_sandbox = modal.Sandbox.create(app=app)
backend = ModalSandbox(sandbox=modal_sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="You are a Python coding assistant with sandbox access.",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a small Python package and run pytest",
}
]
}
)
finally:
modal_sandbox.terminate()Runloop
bash
pip install langchain-runloopbash
uv add langchain-runlooppython
import os
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_runloop import RunloopSandbox
from runloop_api_client import RunloopSDK
client = RunloopSDK(bearer_token=os.environ["RUNLOOP_API_KEY"])
devbox = client.devbox.create()
backend = RunloopSandbox(devbox=devbox)
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="You are a Python coding assistant with sandbox access.",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a small Python package and run pytest",
}
]
}
)
finally:
devbox.shutdown()Vercel
bash
pip install langchain-vercel-sandboxbash
uv add langchain-vercel-sandboxpython
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_vercel_sandbox import VercelSandbox
from vercel.sandbox import Sandbox
sandbox = Sandbox.create(runtime="python3.13")
backend = VercelSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="You are a Python coding assistant with sandbox access.",
backend=backend,
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a small Python package and run pytest",
}
]
}
)
finally:
sandbox.stop()TIP
LangSmith 追踪会显示沙箱内运行了哪些 shell 命令,以及智能体如何使用文件系统工具。请按照可观测性快速入门进行设置。有关托管沙箱托管,请参阅 LangSmith 沙箱。
我们还建议你设置 LangSmith Engine,它会监控你的追踪、检测问题并提出修复建议。
可用提供商
有关特定于提供商的设置、身份验证和生命周期详细信息,请参阅沙箱集成。
INFO
技能需要 deepagents>=1.7.0。
LangSmith
Deno
Daytona
Leap0
Modal
Node VFS
没有看到你的提供商?你可以实现自己的沙箱后端。请参阅贡献沙箱集成。
生命周期和作用域
大多数应用程序会选择每个线程一个沙箱(线程作用域),或者为同一个助手上的每个线程共享一个沙箱(助手作用域)。
沙箱在关闭之前会消耗资源并产生费用。请确保一旦沙箱不再使用就将其关闭。
有关完整生命周期表、异步图工厂注意事项、TTL 行为、LangGraph Deployment 接线以及客户端示例,请参阅上线生产中的沙箱生命周期。
线程作用域(默认)
每个对话都有自己的沙箱。第一次运行会创建它;同一线程上的后续轮次会复用它。当线程结束或沙箱 TTL 过期时,环境会消失。请按照以下示例,将映射与沙箱名称或元数据一起存储,以便每次运行都解析到同一个沙箱。
TIP
当用户可能在空闲后返回时,请在沙箱上配置 TTL,以便提供商自动删除或归档空闲环境。
ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "google-genai:gemini-3.6-flash",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "openai:gpt-5.5",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "anthropic:claude-sonnet-4-6",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "openrouter:openrouter:z-ai/glm-5.2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "fireworks:accounts/fireworks/models/glm-5p2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "baseten:zai-org/GLM-5.2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const threadId = config.configurable?.thread_id as string;
const sandboxName = `thread-${threadId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
idleTtlSeconds: 3600, // TTL:空闲时清理
}));
return createDeepAgent({
model: "ollama:north-mini-code-1.0",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)助手作用域
同一个助手上的每个线程都复用一个沙箱。文件、已安装的软件包和克隆的仓库会在对话之间持久化。
WARNING
助手作用域的沙箱会随着时间的推移在沙箱内积累状态。请为你的沙箱提供商配置 TTL,使用快照定期重置,或实现清理逻辑,使磁盘和内存不会无限制地增长。
ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "google-genai:gemini-3.6-flash",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "openai:gpt-5.5",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "anthropic:claude-sonnet-4-6",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "openrouter:openrouter:z-ai/glm-5.2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "fireworks:accounts/fireworks/models/glm-5p2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "baseten:zai-org/GLM-5.2",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}ts
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
const client = new SandboxClient();
export async function agent(config: LangGraphRunnableConfig) {
const assistantId = config.configurable?.assistant_id as string;
const sandboxName = `assistant-${assistantId}`;
const existing = (await client.listSandboxes()).filter(
(sb) => sb.name === sandboxName,
);
const lsSandbox =
existing[0] ??
(await client.createSandbox({
name: sandboxName,
}));
return createDeepAgent({
model: "ollama:north-mini-code-1.0",
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
});
}python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)python
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),
)有关在图工厂之外手动创建、执行和销毁,请参阅基本用法和沙箱集成以了解特定于提供商的 API。
集成模式
根据智能体的运行位置,有两种将智能体与沙箱集成的架构模式。
智能体在沙箱中的模式
智能体在沙箱内运行,你通过网络与它通信。你构建一个预装了智能体框架的 Docker 或 VM 镜像,在沙箱内运行它,并从外部连接以发送消息。
优点:
- ✅ 与本地开发高度一致。
- ✅ 智能体与环境之间紧密耦合。
权衡:
- 🔴 API 密钥必须存放在沙箱内(安全风险)。
- 🔴 更新需要重建镜像。
- 🔴 需要通信基础设施(WebSocket 或 HTTP 层)。
要在沙箱中运行智能体,请构建一个镜像并在其上安装 deepagents。
dockerfile
FROM python:3.11
RUN pip install deepagents-code然后在沙箱内运行智能体。 要在沙箱内使用智能体,你必须添加额外的基础设施来处理你的应用程序与沙箱内智能体之间的通信。
沙箱作为工具模式
智能体在你的机器或服务器上运行。当它需要执行代码时,它会调用沙箱工具(例如 execute、read_file 或 write_file),这些工具会调用提供商的 API 在远程沙箱中执行操作。
优点:
- ✅ 无需重建镜像即可立即更新智能体代码。
- ✅ 智能体状态与执行之间的分离更清晰。
- API 密钥保留在沙箱之外。
- 沙箱故障不会丢失智能体状态。
- 可以选择在多个沙箱中并行运行任务。
- ✅ 只为执行时间付费。
权衡:
- 🔴 每次执行调用都有网络延迟。
python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)python
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="You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
)
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Create a hello world Python script and run it",
}
]
}
)
print(result["messages"][-1].content)
finally:
client.delete_sandbox(ls_sandbox.name)ts
import "dotenv/config";
import { createDeepAgent, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";
// 也可以使用 Deno、Daytona、E2B、Modal 或 Runloop 完成同样操作
const client = new SandboxClient();
const lsSandbox = await client.createSandbox();
const agent = createDeepAgent({
backend: new LangSmithSandbox({ sandbox: lsSandbox }),
systemPrompt:
"You are a coding assistant with sandbox access. You can create and run code in the sandbox.",
});
try {
const result = await agent.invoke({
messages: [
{
role: "user",
content: "Create a hello world Python script and run it",
},
],
});
const lastMessage = result.messages[result.messages.length - 1];
console.log(
typeof lastMessage.content === "string"
? lastMessage.content
: String(lastMessage.content),
);
} finally {
await client.deleteSandbox(lsSandbox.name);
}本文档中的示例使用沙箱作为工具模式。 当你的提供商 SDK 负责通信层、并且你希望生产环境与本地开发保持一致时,请选择智能体在沙箱中的模式。 当你需要快速迭代智能体逻辑、将 API 密钥保留在沙箱之外,或更倾向于更清晰关注点分离时,请选择沙箱作为工具模式。
沙箱的工作原理
隔离边界
所有沙箱提供商都会保护你的主机系统免受智能体的文件系统和 shell 操作影响。智能体无法读取你的本地文件、访问你机器上的环境变量,或干扰其他进程。但是,仅靠沙箱并不能防御:
- 上下文注入:控制智能体部分输入的攻击者可以指示它在沙箱内运行任意命令。沙箱是隔离的,但智能体在其中拥有完全控制权。
- 网络外泄:除非网络访问被阻止,否则被注入上下文的智能体可以通过 HTTP 或 DNS 将数据发送到沙箱之外。某些提供商支持阻止网络访问(例如,Modal 上的
blockNetwork: true)。
请参阅安全注意事项了解如何处理机密信息并降低这些风险。
execute 方法
沙箱后端架构简单:提供商必须实现的唯一方法是 execute(),它运行 shell 命令并返回其输出。
所有其他文件系统操作(read、write、edit、delete、ls、glob、grep)都由 BaseSandbox 基类构建在 execute() 之上,该基类构造脚本并通过 execute() 在沙箱内运行它们。 所有其他文件系统操作(read、write、edit、ls、glob、grep)都由 BaseSandbox 基类构建在 execute() 之上,该基类构造脚本并通过 execute() 在沙箱内运行它们。
这种设计意味着:
- 添加新提供商非常简单。 实现
execute()——基类处理其他所有事情。 execute工具有条件地可用。 每次模型调用时,框架都会检查后端是否实现了SandboxBackendProtocol。如果没有,该工具会被过滤掉,智能体永远不会看到它。
当智能体调用 execute 工具时,它会提供一个 command 字符串,并返回合并后的 stdout/stderr、退出码,如果输出过大还会返回截断通知。
你也可以在应用程序代码中直接调用后端的 execute() 方法。
LangSmith
python
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)AgentCore
bash
pip install langchain-agentcore-codeinterpreterbash
uv add langchain-agentcore-codeinterpreterpython
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()Daytona
bash
pip install langchain-daytonabash
uv add langchain-daytonapython
from daytona import Daytona
from langchain_daytona import DaytonaSandbox
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
result = backend.execute("python --version")
print(result.output)E2B
bash
pip install langchain-e2bbash
uv add langchain-e2bpython
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()Modal
python
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)NVIDIA OpenShell
bash
pip install langchain-nvidia-openshellbash
uv add langchain-nvidia-openshellpython
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)Runloop
bash
pip install langchain-runloopbash
uv add langchain-runlooppython
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()Vercel
bash
pip install langchain-vercel-sandboxbash
uv add langchain-vercel-sandboxpython
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() 进行。智能体使用它们来读取代码、写入文件并作为其任务的一部分运行命令。 智能体文件系统工具:read_file、write_file、edit_file、ls、glob、grep、execute 是 LLM 在执行期间调用的工具。它们会在沙箱内通过 execute() 进行。智能体使用它们来读取代码、写入文件并作为其任务的一部分运行命令。
文件传输 API:uploadFiles() 和 downloadFiles() 方法由你的应用程序代码调用。它们使用提供商的原生文件传输 API(而非 shell 命令),用于在主机环境与沙箱之间移动文件。使用它们来:
- 为沙箱注入种子,在智能体运行前提供源代码、配置或数据
- 在智能体完成后检索产物(生成的代码、构建输出、报告)
- 预填充智能体将需要的依赖
处理文件
为沙箱注入种子
在智能体运行前使用 uploadFiles() 填充沙箱。文件内容以 Uint8Array 形式提供:
ts
const encoder = new TextEncoder();
const responses = await sandbox.uploadFiles([
["src/index.js", encoder.encode("console.log('Hello')")],
["package.json", encoder.encode('{"name": "my-app"}')],
]);
// 每个响应表示成功或失败
for (const res of responses) {
if (res.error) {
console.error(`Failed to upload ${res.path}: ${res.error}`);
}
}检索产物
在智能体完成后使用 downloadFiles() 从沙箱中检索文件:
ts
const results = await sandbox.downloadFiles(["src/index.js", "output.txt"]);
const decoder = new TextDecoder();
for (const result of results) {
if (result.content) {
console.log(`${result.path}: ${decoder.decode(result.content)}`);
} else {
console.error(`Failed to download ${result.path}: ${result.error}`);
}
}INFO
在沙箱内部,智能体使用自己的文件系统工具(read_file、write_file):而不是 uploadFiles 或 downloadFiles。这些方法是为你的应用程序代码在主机与沙箱之间的边界移动文件而设计的。
处理文件
deepagents 沙箱后端支持用于在应用程序与沙箱之间移动文件的文件传输 API。
为沙箱注入种子
在智能体运行前使用 upload_files() 填充沙箱。路径必须是绝对路径,内容为 bytes:
LangSmith
python
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"),
]
)AgentCore
bash
pip install langchain-agentcore-codeinterpreterbash
uv add langchain-agentcore-codeinterpreterpython
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"),
]
)Daytona
bash
pip install langchain-daytonabash
uv add langchain-daytonapython
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"),
]
)E2B
bash
pip install langchain-e2bbash
uv add langchain-e2bpython
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()Modal
python
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"),
]
)Runloop
bash
pip install langchain-runloopbash
uv add langchain-runlooppython
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"),
]
)Vercel
bash
pip install langchain-vercel-sandboxbash
uv add langchain-vercel-sandboxpython
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
python
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"Failed to download {result.path}: {result.error}")AgentCore
bash
pip install langchain-agentcore-codeinterpreterbash
uv add langchain-agentcore-codeinterpreterpython
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()Daytona
bash
pip install langchain-daytonabash
uv add langchain-daytonapython
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}")E2B
bash
pip install langchain-e2bbash
uv add langchain-e2bpython
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()Modal
python
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}")Runloop
bash
pip install langchain-runloopbash
uv add langchain-runlooppython
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}")Vercel
bash
pip install langchain-vercel-sandboxbash
uv add langchain-vercel-sandboxpython
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}")INFO
在沙箱内部,智能体使用文件系统工具(read_file、write_file)。upload_files 和 download_files 方法是为你的应用程序代码在主机与沙箱之间的边界移动文件而设计的。
安全注意事项
沙箱将代码执行与你的主机系统隔离,但它们并不能防御上下文注入。控制智能体部分输入的攻击者可以指示它在沙箱内读取文件、运行命令或窃取数据。这使得沙箱内的凭据尤其危险。
WARNING
切勿将机密信息放入沙箱。 API 密钥、token、数据库凭据以及其他注入到沙箱(通过环境变量、挂载的文件或 secrets 选项)的机密信息,都可能被上下文注入的智能体读取和窃取。这甚至适用于短期或作用域受限的凭据——如果智能体可以访问它们,攻击者也可以。
安全地处理机密信息
如果你的智能体需要调用经过身份验证的 API 或访问受保护的资源,你有两个选择:
将机密信息保留在沙箱之外的工具中。 定义在你的主机环境中(而非沙箱内)运行并在此处处理身份验证的工具。智能体按名称调用这些工具,但永远不会看到凭据。这是推荐的方法。
使用注入凭据的网络代理。 某些沙箱提供商支持拦截沙箱发出的出站 HTTP 请求并在转发前附加凭据(例如
Authorization头)的代理。智能体永远不会看到机密信息——它只是向 URL 发出普通请求。这种方法在提供商中尚未广泛可用。
WARNING
如果你必须将机密信息注入沙箱(不推荐),请采取以下预防措施:
- 为所有工具调用启用人在回路审批,而不仅仅是敏感调用
- 阻止或限制沙箱的网络访问,以减少外泄路径
- 使用尽可能狭窄的凭据作用域和尽可能短的生存期
- 监控沙箱网络流量中的意外出站请求
即使有这些防护措施,这仍然是一个不安全的变通方案。一个足够有创造力的上下文注入攻击可以绕过输出过滤和 HITL 审查。
通用最佳实践
- 在应用程序中基于沙箱输出采取行动之前,先审查这些输出
- 在不需要时阻止沙箱的网络访问
- 使用中间件过滤或脱敏工具输出中的敏感模式
- 将沙箱内产生的所有内容视为不受信任的输入