Files
tmp/agentscope-sandbox.md
V-LiuShuang 8979eca3a0 add
2026-07-29 16:33:23 +08:00

242 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Intro
分析 agentscope、agentscope-java 对于容器沙箱的支持。
## 支持的沙箱类型
| 沙箱类型 | agentscope | agentscope-java | 共同点 |
| --- | --- | --- | --- |
| Docker | ✅ `DockerWorkspace` | ✅ `DockerFilesystemSpec`harness 内置) | 本地隔离、需 Docker |
| Kubernetes | ✅ `K8sWorkspace`Pod + PVC | ✅ `KubernetesFilesystemSpec`extension | 集群级资源、适合生产 K8s |
| E2B | ✅ `E2BWorkspace` | ✅ `E2bFilesystemSpec` | 云沙箱 SDK、metadata/API 重连 |
| Daytona | ✅ `DaytonaWorkspace` | ✅ `DaytonaFilesystemSpec` | 云沙箱、标签/API 重挂接 |
| AgentRun | ❌ 暂未支持 | ✅ `AgentRunFilesystemSpec`(阿里云) | — |
| OpenSandbox | ✅ `OpenSandboxWorkspace` | ❌ 暂未支持 | — |
| Bubblewrap | ✅(另有 Local | ❌(有 LocalFilesystemSpec | Linux 轻量沙箱 / 本机模式 |
### agentscope
| 后端 | 供给方式 | 持久化 | Teardown | Bootstrap |
| --- | --- | --- | --- | --- |
| **Docker** | aiodocker 建容器 | Bind-mount 或 ephemeral | kill + delete 容器 | 镜像已含 gateway |
| **K8s** | Pod + PVC`as-ws-{id}` | PVC 跨 Pod 存活 | 删 Pod默认可保留 PVC | 首次 apt + uv + gateway |
| **E2B** | `AsyncSandbox.create/connect` | pause 保留磁盘 | `pause()` | 首次 bootstrap |
| **Daytona** | SDK create / label 查找 | `stop(force=False)` | stop + close client | 首次 bootstrap路径由 SDK 推导) |
| **OpenSandbox** | `Sandbox.create` / resume / connect | `pause()` | pause + close | 首次 bootstrap |
云后端共性:用 `agentscope.workspace.id`(或等价 metadata/label索引Manager 缓存 miss 时可跨服务副本重连——这是文档推荐的**分布式部署**路径。
[OpenSandbox](https://open-sandbox.ai/getting-started) 是通用沙箱平台Docker/K8s 运行时 + 多语言 SDK。agentscope 通过官方 `opensandbox` SDK
- 按 metadata 过滤 RUNNING/PAUSED 沙箱并 resume/connect
- close 时 **pause** 保文件系统;
- 与 E2B 类似走 `_bootstrap_commands` 安装 gateway。
Java 侧 v2.0.0 **未集成**,若要在 Java 使用需自研 `SandboxClient` 或等待官方 extension。
## 隔离模型
| | agentscope `IsolationPolicy` | agentscope-java `IsolationScope` |
| --- | --- | --- |
| 会话级 | `PER_SESSION` | `SESSION`(沙箱默认) |
| 用户级 | `PER_USER`(跨 agent 慎用) | `USER`(跨 session 共享记忆/快照) |
| Agent 级 | `PER_AGENT`(默认,按 user+agent | `AGENT`(按 agent 名共享) |
| 全局 | 无对等枚举 | `GLOBAL` |
| 绑定时机 | Session 创建时写入 `workspace_id` | 每次 call 用 RuntimeContext 算 isolation key |
### agentscope-java
| 后端 | 模块位置 | 交互方式 | 持久化侧重 |
| --- | --- | --- | --- |
| **Docker** | harness 核心 | CLI | Tar 快照 + 可选 bind |
| **Kubernetes** | extension | fabric8 / Pod 侧 exec+tar文档侧亦描述 agent-sandbox WarmPool 演进) | 快照 Spec集群侧还可结合 PVC/模板 |
| **E2B** | extension | E2B HTTP + envd支持 TAR / NATIVE_SNAPSHOT 等持久化模式 | 平台快照或 tar |
| **Daytona** | extension | Control Plane HTTP API | 快照 Spec不应用 host bind-mount有则 WARN |
| **AgentRun** | extension | 阿里云 AgentRun API可配 NAS/OSS mount、MCP URL | 云侧空闲超时 + 快照 Spec |
公共能力均来自 `SandboxFilesystemSpec``isolationScope``snapshotSpec``executionGuard``workspaceProjection*`
## 架构对比
### agentscope
Workspace + Backend + Gateway
```
WorkspaceManager (服务侧缓存 / TTL / IsolationPolicy)
SandboxedWorkspaceBase.initialize()
├─ _provision_backend() ← Docker/E2B/K8s/Daytona/OpenSandbox 各实现
├─ _ensure_workspace_layout() (/workspace、skills、sessions、data、.mcp)
└─ _setup_mcp_gateway() ← 容器内 FastAPI MCP Gateway
BackendBase (exec_shell / read_file / write_file)
└─ 内置工具 Bash/Read/Write/Edit/Grep/Glob 透明落到沙箱内
```
关键设计点:
1. **模板方法**:子类只实现 `_provision_backend` / `_teardown_backend` / `_bootstrap_commands`
2. **容器内 MCP Gateway**:宿主机通过 `GatewayClient` + `backend.exec_shell` 驱动网关(一般不依赖宿主机到沙箱的端口映射)。
3. **WorkspaceManager**`PER_AGENT` / `PER_SESSION` / `PER_USER`,空闲 TTL 驱逐;云后端可按 metadata/label 跨节点重连。
### agentscope-java
Filesystem Spec + SandboxManager
```
HarnessAgent.Builder.filesystem(DockerFilesystemSpec / …)
SandboxFilesystemSpec.toSandboxContext(hostWorkspaceRoot)
└─ SandboxContext(client, options, snapshotSpec, workspaceSpec, isolationScope)
SandboxLifecycleHook
PreCall → SandboxManager.acquire → Sandbox.start() (四分支恢复)
PostCall → Sandbox.stop() (tar 快照) → persist state → release
SandboxBackedFilesystem + ShellExecuteTool
└─ 文件工具 / execute 全部转发到沙箱
```
关键设计点:
1. **声明式 Spec**`DockerFilesystemSpec` 等只描述「如何创建」,不是运行时文件系统本身。
2. **Call 边界生命周期**:每次推理前后自动 acquire/start/stop适合多租户按次计费与快照恢复。
3. **快照与执行后端正交**:换 Docker/K8s/E2B 不影响 `LocalSnapshotSpec` / `RedisSnapshotSpec` / `OssSnapshotSpec` 的选择。
4. **Workspace Projection**:启动时把宿主 `AGENTS.md``skills/``subagents/``knowledge/` 等打 tar 注入沙箱,按内容 SHA-256 增量跳过。
## 基于Docker的沙箱
双端对照表
| 对比项 | agentscope | agentscope-java |
| --- | --- | --- |
| API 形态 | aiodockerEngine API | docker CLI |
| 保活命令 | `sleep infinity` | `while :; do sleep 3600; done` |
| 镜像策略 | 自动构建并内容哈希缓存 | 用户指定现成镜像 |
| 默认网络 | Docker 默认(通常有网) | **`none`** |
| 持久化 | Bind-mount可选 | Tar 快照为主 + 可选 bind-mount |
| 生命周期 | Workspace 长生命周期 | 按 Agent `call` 借还 |
| MCP | 容器内 Gateway | Harness 侧注册;沙箱只做 FS/Shell |
| 资源限制 | 较弱(构造参数少) | memory / cpu / ports / network |
| 水平扩展 | 不适合 | 需外置快照/状态存储 |
### agentscope
#### 实现原理
1. **镜像构建(内容哈希缓存)**
- `prepare_build_context()` 渲染 Dockerfile打包 gateway 脚本、`requirements.txt`、glob helper。
- Tag 形如 `agentscope-workspace:<12hex>`,对 Dockerfile + COPY 文件做 SHA-256本地已有则跳过 build。
- 默认基础镜像 `python:3.11-slim`,镜像内预装 gateway venv + agentscopeDocker 路径**不做**首次 bootstrap
- 可选 `node_version` 从官方 Node slim 镜像拷贝 `node`/`npm`(供 npx MCP
2. **容器启动**
- 通过 **aiodocker** `containers.create_or_replace`
- `Cmd: ["sleep", "infinity"]`,工作目录 `/workspace`
- Label`agentscope.workspace=true``agentscope.workspace.id=<id>`
- **Gateway 端口仅容器内监听,不做 host port 映射**;宿主经 `DockerBackend.exec` 访问。
3. **持久化**
- 可选 `host_workdir` bind-mount → `/workspace``is_persistent`)。
- 无 mount 则为 ephemeral 容器文件系统。
- Linux 上 teardown 时尝试 `chown` 把 bind-mount 文件所有权还给宿主用户。
4. **I/O 原语(`DockerBackend`**
- `exec_shell`:容器 `exec` API直传 argv无中间 shell需要时包 `sh -c`)。
- `read_file` / `write_file``get_archive` / `put_archive`tar
5. **服务侧**
- `DockerWorkspaceManager``basedir` 下为每个 workspace 建宿主目录并 bind-mountTTL sweeper 回收空闲容器。
#### 使用限制
| 限制 | 说明 |
| --- | --- |
| 依赖 Docker daemon | 需本机/远端可达的 Docker Engine + aiodocker |
| 基础镜像须含 `python3` | Gateway 与工具链假设 Python 可用 |
| **单节点** | 官方文档明确Docker/Local/Bubblewrap 不适配水平扩容;跨节点请用 E2B/Daytona/OpenSandbox/K8s |
| 首次镜像构建成本 | 缓存未命中时 build 较慢;构建失败需解读 docker stream 日志 |
| 无细粒度 CPU/内存 API | 构造参数侧重镜像与环境变量,资源限额不如 Java Spec 直接 |
| Linux bind-mount 权限 | 容器内 root 写文件可能留下错误 uid框架仅在 teardown 做 chown 尽力修复 |
#### 好处
- 镜像内预置 gateway**冷启动无需 apt/uv/pip bootstrap**(对比 E2B/K8s/OpenSandbox
- 内容哈希镜像缓存Dockerfile 不变则秒级复用。
- Workspace 长期存活MCP / skills / sessions 与服务模型一致。
- Bind-mount 可把工作区落在宿主磁盘,便于调试与备份。
-`WorkspaceManager` 隔离策略PER_AGENT 等)无缝衔接。
#### 弊端
- 强依赖本机 Docker水平扩展与多副本亲和困难。
- 常驻 `sleep infinity` 容器占用资源,依赖 TTL 清扫。
- Gateway 健康检查失败时排查需看容器内日志路径。
- 与 Java 版相比,缺少一等公民的「跨 call tar 快照后端」抽象。
### agentscope-java
#### 实现原理
1. **配置层Spec**
Fluent API`image``workspaceRoot`(默认 `/workspace`)、`memorySizeBytes``cpuCount``exposedPorts``network``environment``additionalRunArgs``snapshotSpec``workspaceSpec`
2. **创建与客户端**
- `DockerSandboxClient.create(...)` 生成 `DockerSandboxState`sessionId、镜像、资源参数、快照句柄
- **不引入 docker-java**:一律 `docker run` / `exec` / `inspect` / `stop` / `rm` CLI。
- 要求宿主 `PATH` 上有 `docker`,且 daemon 可达。
3. **容器命令**
```text
docker run -d --name agentscope-sandbox-<sessionId>
[--memory] [--cpus] [-p] [--network=none|...] [-v bind...]
<image> sh -c "while :; do sleep 3600; done"
```
- 默认 **`--network=none`**(未配置 network 时),比 Python 版更偏「默认断网隔离」。
- 支持 `WorkspaceSpec` 中的 `BindMountEntry` → `-v host:container:ro|rw`。
- `exec``docker exec -w <workspaceRoot> <id> sh -c <command>`。
4. **工作区 tar 快照**
- Persist`docker exec tar -cf - -C /workspace .`(并对 bind-mount 路径 `--exclude`)。
- Hydrate`docker exec -i tar -xf - -C /workspace`。
- `AbstractBaseSandbox` **四分支恢复**:容器是否仍保留目录 × 是否有可恢复快照。
5. **编排**
- `start()`:确保容器 running → 四分支初始化 → workspace projection。
- `stop()`:写快照,**容器可继续跑**。
- `shutdown()`:自管容器则 `docker stop` + `docker rm --force`。
#### 使用限制
| 限制 | 说明 |
| --- | --- |
| 依赖 Docker CLI | 无嵌入式 Engine APIWindows/远程 Docker 场景需确保 CLI 行为一致 |
| 默认无网络 | `network` 未设时为 `none`;需要拉包/访问外网必须显式配置 |
| 镜像需自备 | 不像 Python 那样自动构建含 gateway 的专用镜像;由用户指定(如 `ubuntu:24.04` |
| 输出截断 | stdout/stderr 单流约 512KB 上限 |
| 并发语义 | 同一 IsolationScope 并发 call 可起多个容器stop 时 **last-write-wins** 覆盖快照 |
| 多副本 | 本地 Docker + 本地快照会成单点;生产需 Redis/OSS 快照 + 分布式 `AgentStateStore` |
| AgentRun/K8s 等扩展 | Docker 在 harness 核心;其它后端在 extension 模块,需单独依赖 |
#### 好处
- **零额外 Java Docker 库依赖**,部署简单。
- 资源限额CPU/内存)、端口、网络、额外 run args 一等配置。
- 快照体系成熟,可跨 call / 跨副本恢复 `node_modules` 等重状态。
- Workspace projection 把静态资产与运行态分离,宿主改 skills 可增量注入。
- `IsolationScope`SESSION/USER/AGENT/GLOBAL覆盖多租户 SaaS 常见模型。
- `executionGuard` 可对 AGENT/GLOBAL 做串行化,缓解快照互踩。
#### 弊端
- 每次 call 的 start/stop/snapshot 有固定开销(尤其大工作区 tar
- CLI 进程模型:高并发时大量 `docker exec` 子进程与线程池开销。
- 无内置 MCP GatewayMCP 走 Harness 侧 `tools.json` 注册,与沙箱内进程模型不同。
- 默认断网 + 裸镜像,冷启动后常需 agent 自己装依赖(靠快照摊销)。