当 AI Agent 开始在你的服务器上执行命令、读写文件、创建容器时,你真的知道它做了什么吗?
链接:
-
SDK: GitHub – Rainbow0328/agent-sandbox-backend: 沙箱后端的封装,包含了上传、下载、执行命令等,还增加了操作历史的功能,实现操作的可追溯 · GitHub
-
Console: GitHub – Rainbow0328/sandbox-web: 沙箱文件可视化及操作历史 · GitHub
为什么做这件事
过去几个月,AI Agent 从"能聊天"进化到了"能干活"。Deep Agents、Manus、各种 Coding Agent 纷纷落地,它们需要真实的 Linux 环境来执行代码、安装依赖、运行测试。
但一个问题始终悬在工程师头上:
Agent 在沙箱里到底做了什么?出了问题怎么排查?删了什么文件?执行了什么命令?什么时候失败的?
市面上不缺沙箱运行时——E2B 用 Firecracker,Daytona 自研运行时,阿里开源了 OpenSandbox。但它们要么是纯 SaaS(数据不在自己手里),要么只提供基础 SDK(没有管理界面),没有一套方案能同时解决"给 Agent 用"和"给人看"这两个需求。
所以我做了两个开源项目,组合起来解决这个问题:
-
Agent Sandbox Backend SDK(agent-sandbox-backends)— 面向 AI Agent 的 OpenSandbox 适配 SDK,一行代码接入 Deep Agents 框架,内置沙箱内操作历史数据库、并发控制、文件上传安全策略
-
Sandbox Explorer(sandbox-explorer)— 自托管 Web 控制台,浏览器里管理沙箱、浏览文件、执行命令、打开终端、查看完整操作历史
两者通过沙箱内的 SQLite 历史数据库松耦合协作:SDK 写入,Console 读取,沙箱删除则历史一起删除,生命周期完全对齐。
整体架构
先看全貌:
┌─────────────────────────────────────────────┐
│ 你的 Python 进程 │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Deep Agents / 你的 Agent 代码 │ │
│ └──────────────┬────────────────────┘ │
│ │ as_deepagents_backend() │
│ ┌──────────────▼────────────────────┐ │
│ │ agent-sandbox-backends (SDK) │ │
│ │ │ │
│ │ ┌─────────┐ ┌───────────────┐ │ │
│ │ │Operation│ │ History │ │ │
│ │ │Pipeline │──│ Store │ │ │
│ │ └────┬────┘ └───────┬───────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼────┐ ┌───────▼───────┐ │ │
│ │ │Provider │ │ Concurrency │ │ │
│ │ │Adapter │ │ KeyedRWLock │ │ │
│ │ └────┬────┘ └───────────────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼────┐ ┌───────▼───────┐ │ │
│ │ │ Upload │ │ Security │ │ │
│ │ │ Scanner │ │ Scanner │ │ │
│ │ └─────────┘ └───────────────┘ │ │
│ └───────────────────────────────────┘ │
│ │ HTTP/gRPC │
└──────────────────┼─────────────────────────┘
│
┌──────────────────▼─────────────────────────┐
│ OpenSandbox 沙箱运行时 │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 沙箱实例 (Sandbox) │ │
│ │ │ │
│ │ /workspace/ ← Agent 工作目录 │ │
│ │ /.agent-history/ │ │
│ │ └── history.sqlite3 ← 操作历史DB │ │
│ │ /.agent-helper/ ← 历史写入工具 │ │
│ └──────────────────────────────────────┘ │
└──────────────────┬─────────────────────────┘
│
┌──────────────────▼─────────────────────────┐
│ Sandbox Explorer (Web Console) │
│ │
│ ┌────────────┐ ┌────────┐ ┌──────────┐ │
│ │ File Browse │ │Command │ │ Terminal │ │
│ │ (Monaco) │ │(SSE) │ │(xterm.js)│ │
│ └────────────┘ └────────┘ └──────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ History Timeline (历史时间线) │ │
│ │ SDK 操作 + Console 操作 统一展示 │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
核心设计思想:
SDK 不实现沙箱运行时,而是适配 OpenSandbox,让 Deep Agents 框架能用一行代码接入
操作历史写在沙箱内的 SQLite 里,而非 Web 后端,沙箱删除则历史自动清除,生命周期完全对齐
Console 和 SDK 互不感知,通过沙箱内的历史数据库松耦合协作
Console 是可选的,SDK 独立工作不受影响;Console 独立工作也能直连沙箱
项目一:Agent Sandbox Backend SDK
仓库:Rainbow0328/agent-sandbox-backend PyPI 包名:agent-sandbox-backends
一行代码接入 Deep Agents
from agent_sandbox_backends import CleanupPolicy, create_opensandbox_backend
from agent_sandbox_backends.integrations.deepagents import as_deepagents_backend
from deepagents import create_deep_agent
# 创建 Backend
core_backend = await create_opensandbox_backend(
"http://your-opensandbox-service:8080",
cleanup=CleanupPolicy.ON_CLOSE,
)
# 一行转换为 Deep Agents 后端
backend = as_deepagents_backend(core_backend)
# 交给 Deep Agents
agent = create_deep_agent(model=model, backend=backend)
Deep Agents 的文件查看、读取、写入、编辑、搜索、上传、下载和命令执行,全部自动适配到 OpenSandbox 沙箱。你不需要自己写任何 Adapter 代码。
沙箱内操作历史(核心差异化)
这是我认为这个项目最有价值的部分。
问题:Agent 在沙箱里执行了 50 条命令、改了 20 个文件,中间某一步失败了。你怎么排查?E2B 不记录,Daytona 不记录,OpenSandbox 官方 SDK 也不记录。
方案:SDK 的 OperationPipeline 在每次操作前后自动写入沙箱内的 /.agent-history/history.sqlite3,完整记录:
| event_id | 全局唯一操作 ID(UUIDv7,时间有序) |
| operation_type | 操作类型(command.execute / file.write / sandbox.create 等) |
| status | started / succeeded / failed / cancelled / timeout |
| actor_type | 执行者类型(agent / system / console / user) |
| actor_id | 执行者标识 |
| thread_id | 会话线程 ID |
| run_id | 运行批次 ID |
| correlation_id | 关联 ID,用于追踪操作链 |
| request_json | 完整请求参数 |
| result_json | 完整结果 |
| duration_ms | 耗时 |
| stdout/stderr | 完整命令输出(分块存储,支持流式读取) |
| occurred_at | 发生时间 |
| completed_at | 完成时间 |
关键设计:
-
四种历史模式:NONE(不记录)、PROVIDER(记到 Provider 端)、DATABASE(记到外部 PostgreSQL)、SANDBOX(记到沙箱内 SQLite,默认)
-
TTL + 容量限制:默认 7 天过期,数据库最大 128MB,单次操作输出最大 16MB,超限自动删除最旧记录
-
增量同步:基于 history_changes 变更日志 + history_consumers 消费者游标,Console 只拉取增量
-
分布式租约:history_leases 表防止多个消费者同时清理历史
-
输出分块存储:大命令输出分 16KB 块存储,支持流式读取,不会因为一次 cat 大文件就把数据库撑爆
安全保证:API Key 不会写入历史,但命令字符串会——所以不要把密码拼进命令里,优先用环境变量传递。
并发控制:KeyedRWLock
当多个子 Agent 同时操作同一沙箱时,SDK 提供 Writer-preferring Keyed Read/Write Lock:
# 多个 Agent 可以同时读同一个文件(共享锁)
async with backend._lock.read("/workspace/data.json"):
content = await backend.read_file("/workspace/data.json")
# 写操作排他(写优先,防止写饥饿)
async with backend._lock.write("/workspace/data.json"):
await backend.write_file("/workspace/data.json", new_content)
-
Writer-preferring:有等待中的写锁时,新读锁会让路,防止写饥饿
-
Keyed:不同文件不互相阻塞,粒度细
-
Idle-state cleanup:无引用的锁自动清理,不泄漏内存
-
超时控制:支持 timeout_seconds,防止死锁
文件上传安全
SDK 不会默认允许任意本地路径上传。必须显式声明允许的根目录:
from pathlib import Path
from agent_sandbox_backends import UploadConfig, UploadSpec, create_opensandbox_backend
backend = await create_opensandbox_backend(
"http://your-opensandbox-service:8080",
uploads=(UploadSpec(source="./project", target="/workspace/project"),),
upload_config=UploadConfig(allowed_local_roots=(Path.cwd(),)),
)
上传安全策略覆盖:
| 路径逃逸防护 | 检查 .. 和绝对路径,防止写到沙箱任意位置 |
| 符号链接防护 | 检测 symlink,防止读到宿主机敏感文件 |
| 特殊文件防护 | 跳过 .env、.ssh、.aws、.git、虚拟环境 |
| 归档炸弹防护 | 限制解压后总大小和文件数量 |
| 校验和验证 | 上传后重新读取验证 SHA256,防止传输损坏 |
| Staging + 提交 | 先写暂存区,校验通过后原子提交,失败自动回滚 |
| 冲突策略 | 支持 skip / overwrite / if_changed(只覆盖有变化的) |
| 文件数量限制 | 默认单次上传最多 10000 个文件 |
| 总大小限制 | 默认单次上传最大 1GB |
Actor 上下文追踪
每个操作都携带完整的执行者上下文:
with backend.agent_context(
agent_id="research-agent",
thread_id="thread-1",
run_id="run-1",
):
await backend.execute("python –version")
# 这条命令的历史记录会带上 agent_id="research-agent"
correlation_id 自动生成并贯穿整个上下文范围内的所有操作,方便在历史时间线中追踪一次完整的 Agent 运行。
项目二:Sandbox Explorer(Web 控制台)
仓库:Rainbow0328/sandbox-web npm 包名:sandbox-explorer
一键启动
# 生产模式:构建前端 + 后端服务
python start.py
# 开发模式:前后端热更新
python start.py –dev
# Docker
docker compose up -d
打开浏览器,就是完整的沙箱管理控制台。无需配置环境变量,认证默认关闭,开箱即用。
全功能沙箱管理
沙箱生命周期:创建、暂停、恢复、删除,支持通过 Connection 快速创建,也支持直接输入 URL + API Key 创建。
文件浏览器:
-
目录树浏览,支持面包屑导航
-
Monaco Editor 在线编辑代码(和 VS Code 同款编辑器)
-
上传文件(支持选择目标目录的自定义弹窗)
-
下载文件
-
创建文件夹(自定义弹窗,不用浏览器 prompt)
-
删除文件/文件夹
命令执行器:
-
SSE 实时流式输出,命令执行过程中可以看到逐行输出
-
支持中断正在执行的命令
-
命令历史记录
交互式终端:
-
基于 xterm.js + WebSocket 的完整交互终端
-
支持 Ctrl+C、Tab 补全、颜色输出
-
和真实终端体验一致
操作历史时间线(核心功能)
这是 Console 最有价值的页面。它会从沙箱内的 history.sqlite3 同步操作记录,并和 Console 自己的操作日志合并展示,形成一个统一的时间线。
你会看到什么:
-
SDK 的操作:Agent 执行的每一条命令、每一次文件写入、每一次沙箱创建
-
Console 的操作:你在 Web 界面上执行的命令、上传的文件、创建的文件夹
-
完整上下文:谁执行的(actor_type)、耗时多少、成功还是失败、完整的请求参数和结果
历史时间线的设计:
┌─────────────────────────────────────────────────────────────┐
│ History Timeline │
│ │
│ ┌─ 14:32:01 ─ [SDK] sandbox.create ✅ succeeded 120ms│
│ │ actor: research-agent | run: run-1 │
│ │ request: { image: "python:3.12", workdir: "/workspace" }│
│ └───────────────────────────────────────────────────────────│
│ │
│ ┌─ 14:32:05 ─ [SDK] command.execute ✅ succeeded 2.1s│
│ │ actor: research-agent | run: run-1 │
│ │ command: pip install fastapi │
│ │ ▸ stdout: Collecting fastapi… (点击展开) │
│ └───────────────────────────────────────────────────────────│
│ │
│ ┌─ 14:35:12 ─ [Console] file.write ✅ succeeded 45ms│
│ │ actor: admin | path: /workspace/main.py │
│ └───────────────────────────────────────────────────────────│
│ │
│ ┌─ 14:35:30 ─ [SDK] command.execute ❌ failed 5.0s │
│ │ actor: research-agent | run: run-1 │
│ │ command: python main.py │
│ │ ▸ stderr: ModuleNotFoundError: No module named 'uvicorn' │
│ └───────────────────────────────────────────────────────────│
└─────────────────────────────────────────────────────────────┘
技术实现:
Console 通过 SDK 的 SandboxHistoryStore 读取沙箱内 SQLite
基于 history_changes 变更日志做增量同步,只拉取上次同步之后的新记录
消费者游标(history_consumers)记录已确认的 seq,支持多 Console 实例独立消费
Console 自己的操作也会写入沙箱历史(best-effort),确保 SDK 和 Console 的操作在同一个时间线里
历史同步是限流的,不会阻塞正常操作
连接管理
Console 可以管理多个 OpenSandbox 服务连接,凭据使用 Fernet 对称加密存储:
端口可配置
支持通过 CLI、环境变量或 .env 文件配置端口:
# CLI
python start.py –port 3000 –frontend-port 3001
# 环境变量
EXPLORER_PORT=3000 python start.py
# .env 文件
echo "EXPLORER_PORT=3000" > .env
python start.py
实战演示:Deep Agents + OpenSandbox + Web Console
场景:用 Deep Agents 在沙箱里做代码审查
import asyncio
from agent_sandbox_backends import CleanupPolicy, create_opensandbox_backend
from agent_sandbox_backends.integrations.deepagents import as_deepagents_backend
from deepagents import create_deep_agent
async def main():
# 1. 创建沙箱 Backend
backend = await create_opensandbox_backend(
"http://your-opensandbox-service:8080",
sandbox_name="code-review-session",
image="python:3.12",
cleanup=CleanupPolicy.NEVER, # 不自动删除,方便后续在 Console 查看
)
# 2. 转换为 Deep Agents 后端
da_backend = as_deepagents_backend(backend)
# 3. 创建 Agent
agent = create_deep_agent(
model="claude-sonnet-4-20250514",
backend=da_backend,
)
# 4. 设置 Actor 上下文
with backend.agent_context(
agent_id="code-reviewer",
thread_id="review-001",
run_id="run-20260720",
):
# 5. 让 Agent 审查代码
result = await agent.run(
"Clone https://github.com/example/repo, "
"review the codebase for security issues, "
"and write a report to /workspace/report.md"
)
print(f"Review complete: {result}")
# 6. 不关闭 Backend(cleanup=NEVER),沙箱保留
# 7. 打开 Web Console 查看完整操作历史!
asyncio.run(main())
运行完毕后,打开 Sandbox Explorer:
在沙箱列表找到 code-review-session
Files 标签页:查看 Agent 生成的 report.md
History 标签页:查看 Agent 执行了哪些 git clone、grep、python 命令,每条命令的完整输出
Terminal 标签页:进入沙箱终端,自己验证 Agent 的发现
这就是"可观测的 AI Agent"——不是黑盒,是透明盒子。
安全设计
安全是这套系统的核心设计目标,不是事后补丁:
SDK 侧
| 上传路径白名单 | 必须显式声明 allowed_local_roots,默认不允许任何路径 |
| 符号链接检测 | 扫描所有上传文件,遇到 symlink 直接拒绝 |
| 特殊文件排除 | 自动排除 .env、.ssh、.aws、.git、__pycache__、node_modules |
| 归档炸弹防护 | 限制解压后总大小(默认 1GB)和文件数量(默认 10000) |
| 校验和验证 | 上传后重新读取并校验 SHA256,防止传输损坏 |
| Staging + 原子提交 | 先写暂存区,全部校验通过后原子提交,失败自动回滚 |
| API Key 不入历史 | 历史记录中不保存 API Key,但命令字符串会保存(注意不要拼密码) |
| 并发 KeyedRWLock | Writer-preferring,防止写操作饥饿 |
| 操作活动门控 | 关闭/删除沙箱时等待所有活动操作完成,阻止新操作进入 |
Console 侧
| 凭据加密存储 | API Key 使用 Fernet 对称加密(AES-128-CBC + HMAC-SHA256) |
| Master Key 可配 | 通过 EXPLORER_MASTER_KEY 环境变量配置加密密钥 |
| Admin Token 认证 | 可选的 Bearer Token 认证,空则禁用(本地开发友好) |
| 路径逃逸防护 | 文件操作做 POSIX 路径校验,防止 .. 逃逸 |
| CORS 可配 | 通过 EXPLORER_CORS_ORIGINS 限制跨域 |
| WebSocket Token 验证 | 终端 WebSocket 连接需要有效 Token |
与同类产品的对比
| 沙箱运行时 | OpenSandbox | E2B (Firecracker) | Daytona 自研 | OpenSandbox |
| Deep Agents 原生集成 | ✅ 一行代码 | ❌ 需自己封装 | ❌ 需自己封装 | ❌ 无 |
| 沙箱内操作历史 DB | ✅ 完整 Schema | ❌ | ❌ | ❌ |
| 自托管 Web 控制台 | ✅ 全功能 | ❌ SaaS 为主 | ❌ CLI 为主 | ❌ 无 |
| 文件上传安全策略 | ✅ 9 层防护 | ❌ | ❌ | ❌ |
| 并发控制 (KeyedRWLock) | ✅ | ❌ 基础 | ❌ 基础 | ❌ 基础 |
| 文件浏览器 | ✅ Monaco 编辑器 | ❌ | ❌ | ❌ |
| 交互式终端 | ✅ xterm.js | ❌ | ❌ | ❌ |
| SSE 流式命令输出 | ✅ | ❌ | ❌ | ❌ |
| 多沙箱连接管理 | ✅ 加密凭据 | ❌ | ❌ | ❌ |
| 部署方式 | Docker / 本地 | SaaS / 自建 | CLI / SaaS | SDK only |
| 开源协议 | Apache-2.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 |
一句话总结差异化:E2B 和 Daytona 是"自己做运行时 + 自己做 SDK + 做 SaaS 管理界面"的全栈方案;本方案是"适配 OpenSandbox + 做 Deep Agents 桥梁 + 做自托管全功能控制台 + 做沙箱内操作历史"的补充方案。不竞争,互补。
技术栈
SDK(agent-sandbox-backends):
-
Python 3.11+
-
Pydantic v2(领域模型)
-
SQLAlchemy 2.0 + aiosqlite / asyncpg(历史存储)
-
pathspec(上传安全扫描)
-
Hatchling(构建)
-
Ruff + Pyright(代码质量)
Console(sandbox-explorer):
-
后端:FastAPI + SQLAlchemy + aiosqlite
-
前端:React 18 + TypeScript + Vite
-
UI:Tailwind CSS + lucide-react
-
状态管理:Zustand + TanStack Query
-
编辑器:Monaco Editor (@monaco-editor/react)
-
终端:xterm.js + WebSocket
-
打包:Docker multi-stage build
快速上手
1. 安装 SDK
git clone https://github.com/Rainbow0328/agent-sandbox-backend.git
cd agent-sandbox-backend
pip install -e ".[deepagents]"
2. 启动 Web Console
git clone https://github.com/Rainbow0328/sandbox-web.git
cd sandbox-web
python start.py
3. 用 SDK 创建沙箱并执行操作
from agent_sandbox_backends import create_opensandbox_backend
backend = await create_opensandbox_backend(
"http://your-opensandbox-service:8080",
sandbox_name="my-first-sandbox",
)
with backend.agent_context(agent_id="my-agent"):
result = await backend.execute("echo 'Hello from sandbox!'")
print(result.stdout)
4. 打开浏览器查看
打开 http://localhost:8080,在沙箱列表中找到 my-first-sandbox,点击进入,切换到 History 标签页,你就能看到刚才那条 echo 命令的完整记录。
开源信息
| Agent Sandbox Backend SDK | Rainbow0328/agent-sandbox-backend | agent-sandbox-backends (PyPI) | Apache-2.0 |
| Sandbox Explorer | Rainbow0328/sandbox-web | sandbox-explorer (npm) | Apache-2.0 |
欢迎 Star、Issue、PR!
路线图
SDK
- 更多 Provider 适配器(E2B、Daytona)
- 历史数据导出(JSON / CSV)
- Webhook 通知(操作失败时回调)
- 更丰富的 Actor 权限模型
Console
- 沙箱快照与回滚
- 多用户协作(同时操作同一沙箱)
- 操作历史搜索与过滤
- 暗色主题
- 国际化(i18n)
写在最后
AI Agent 正在从"能聊天"走向"能干活"。当 Agent 真正开始操作你的服务器时,可观测性不是锦上添花,是安全底线。
这套方案的核心价值不是"又造了一个沙箱",而是:
让 Agent 的每一步操作都有据可查——操作历史是设计的,不是事后补的
让数据生命周期对齐——沙箱删除,历史一起删除,不残留
让管理界面可以自托管——数据在自己手里,不在 SaaS 平台
让 Deep Agents 一行代码接入——降低 Agent 开发门槛
如果你也在做 AI Agent 相关的项目,如果你也需要在沙箱里运行 Agent 代码,欢迎试试这套方案。
如果觉得有用,给个 Star 是对开源作者最大的鼓励 🙏
本文涉及的两个项目均为 Apache-2.0 开源协议,可免费用于商业用途。





