别让你的 AI Agent 裸奔:Sandbox 沙箱隔离从入门到选型
你的 AI Agent 会写代码、跑命令、操作文件 —— 但你真的放心让它直接跑在你的电脑上吗?
如果 Agent 误读了某个 prompt 来一句rm -rf /,或者 curl 到了不安全网络……沙箱(Sandbox),就是给 Agent 套的"笼子"。
本文将讲清两种主流方案:
- 模式一:Agent in Sandbox(Docker 自建)
- 模式二:Sandbox as Tool(云服务托管,如 Daytona / E2B)
并最终给出一张选型决策图。
一、什么是 Sandbox
定义:Sandbox 通过在 Agent 的执行环境和主机系统之间建立边界,实现隔离。
由于当前 Agent 行为常常无法预测,因此沙箱用于防止:
- 🔒 访问隐私数据
- 📁 修改权限文件
- 🌐 访问不安全网络
二、模式一:Agent in Sandbox(Docker 自建)
用户预先建立 Docker 镜像,Agent 运行在沙箱内部,通过网络与外部通讯。
2.1 整体架构
2.2 项目结构
.
├── .env # 环境变量(API Key 等)
├── requirements.txt # Python 依赖
├── Agent.py # 沙箱内运行的 Agent 服务
├── Dockerfile # 容器镜像构建脚本
├── Client.py # 本地客户端(与沙箱通讯)
└── workspace/ # 卷挂载目录(承载 Agent 生成的文件)
2.3 关键文件
📄 Dockerfile
FROM python:3.11-slim # 基础镜像
WORKDIR /app # 容器内工作目录
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN mkdir -p /workspace # Agent 操作的目标目录
COPY agent.py .
EXPOSE 8000 # 声明端口
CMD ["python", "agent.py"] # 容器启动默认命令
📄 Agent.py(5 个步骤)
# ========== 1. 配置沙盒后端 ==========
BACKEND = LocalShellBackend(
root_dir="/workspace",
env={"PATH": "/usr/local/bin:/usr/bin:/bin"},
inherit_env=False, # 不继承主机环境变量
timeout=120,
max_output_bytes=500_000 # 命令输出内存上限
)
# ========== 2. 创建 DeepAgent ==========
model = init_chat_model(
model="openai:deepseek-ai/DeepSeek-V3.2",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url=os.getenv("DEEPSEEK_BASE_URL")
)
AGENT = create_deep_agent(model=model, backend=BACKEND)
# ========== 3. FastAPI 数据模型 ==========
app = FastAPI(title="DeepAgent in Docker")
class ChatRequest(BaseModel):
message: str
thread_id: Optional[str] = "default"
class ChatResponse(BaseModel):
response: str
thread_id: str
# ========== 4. 对话路由 ==========
@app.post("/chat", response_model=ChatResponse)
def chat(request: ChatRequest):
try:
result = AGENT.invoke(
input={"messages": [{"role": "user", "content": request.message}]},
config={"configurable": {"thread_id": request.thread_id}},
)
return ChatResponse(
response=result["messages"][-1].content,
thread_id=request.thread_id
)
except Exception as e:
return ChatResponse(response=f"错误:{e}", thread_id=request.thread_id)
# ========== 5. 启动入口 ==========
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
📄 Client.py(本地客户端)
import requests
def chat(message, thread_id="default"):
resp = requests.post(
url="http://localhost:8000/chat",
json={"message": message, "thread_id": thread_id}
)
return resp.json()
# ====== 测试 ======
print("=== 测试1:简单对话 ===")
print(chat("你好,请介绍一下自己", thread_id="test-chat"))
print("\n=== 测试2:代码执行 ===")
print(chat("在workspace文件夹下,创建一个Python文件打印Hello World字符串。",
thread_id="test-code"))
2.4 构建与运行流程
# 构建镜像
docker build -t deepagent .
# 运行容器
docker run -it --rm `
-p 8000:8000 `
-v "$($PWD -replace '\\','/'):/workspace" `
--env-file .env `
deepagent
| 参数 | 作用 |
|---|---|
-it | 交互模式 |
--rm | 容器退出后自动清理 |
-p 8000:8000 | 端口映射 |
-v | 卷挂载 |
--env-file .env | 从文件加载环境变量(不进入镜像) |
deepagent | 使用的镜像名 |
2.5 通讯时序图
2.6 卷挂载的核心特性
主机和容器访问的是同一个物理目录,任何一方的修改对另一方"立即可见"。
Agent 在容器内 /workspace 创建的 hello.py,立即出现在宿主机的 workspace/ 目录里。
三、模式二:Sandbox as Tool(云服务沙箱)
Agent 运行在本地,当需要执行代码时,在沙箱中调用工具(如
.read_file、.write_file)。
云服务厂商(E2B / Codespaces / AWS / Daytona)帮我们管理沙盒环境,用户只用,不运维。
3.1 整体架构
3.2 Daytona 示例代码
from daytona import Daytona, DaytonaConfig
from langchain_daytona import DaytonaSandbox
from langchain.chat_models import init_chat_model
from deepagents import create_deep_agent
# ========== 1. 创建云端沙盒 ==========
daytona = Daytona(DaytonaConfig(api_key=os.getenv("DAYTONA_API_KEY")))
sandbox = daytona.create() # 云端创建新沙盒
backend = DaytonaSandbox(sandbox=sandbox) # 包装为后端
# ========== 2. 创建 DeepAgent ==========
model = init_chat_model(
model="openai:deepseek-ai/DeepSeek-V3.2",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url=os.getenv("DEEPSEEK_BASE_URL")
)
agent = create_deep_agent(
model=model,
system_prompt="你是一位拥有沙盒访问权限的Python编码助手。",
backend=backend
)
# ========== 3. 交互 ==========
result = agent.invoke({
"messages": [{
"role": "user",
"content": "编写一个python代码计算:5的十一次方。"
}]
})
for mes in result["messages"]:
print(mes.content)
# ========== 4. ⚠️ 用完即停 ==========
sandbox.stop()
3.3 通讯时序图
3.4 计费提醒
云沙盒按时计费,但有一定的免费额度。
务必每次"用完即停"(sandbox.stop()),否则账单爆炸 💸。
四、深度对比:两种模式 × 两种实现
4.1 模式对比
| 维度 | Agent in Sandbox | Sandbox as Tool |
|---|---|---|
| Agent 位置 | 隔离容器 | 本地系统 |
| 更新方式 | 重建 Docker 镜像 | 代码热更新 |
| API 密钥 | 放入沙盒(有安全风险) | 留在沙盒外 |
| 状态维持 | 沙盒崩溃 → Agent 状态丢失 | 沙盒崩溃 → Agent 状态不丢 |
| 并行能力 | 单实例 | 多沙盒并行 |
| 适用场景 | 强环境耦合 | 快速迭代 / 高安全 |
4.2 实现对比
| 维度 | Docker 自建 | 云服务托管 |
|---|---|---|
| 基础设施 | 本地机器(服务器) | 云服务商 |
| 控制权限 | 完全控制 | 受限于接口 |
| 计算资源 | 本机 CPU / 内存 | 零本地占用 |
| 网络端口 | 占用本地端口 | 仅 API 调用 |
| 并行能力 | 受限于本机硬件 | 理论上无上限 |
| 隔离强度 | 依赖 Docker 配置 | 通常更强 |
五、怎么选?一张决策图
六、关键收获
- 沙箱的本质:在 Agent 与主机之间建立边界
- 两种模式的核心差异:Agent 在哪、密钥在哪、状态如何保留
- Docker 自建三件套:
Dockerfile(构建)+--env-file(安全传密钥)+-v(卷挂载看产物) - 云沙箱第一原则:用完即停,否则账单爆炸 💸
📎 参考资料:
- Daytona 官方:https://www.daytona.io/
- DeepAgents:基于 LangChain 的多步 Agent 框架
许可协议:
CC BY 4.0