AgentRun 沙箱后端¶
AgentRun(阿里云函数计算 FC 3.0 Sandbox API,版本 2025-09-10)是阿里云提供的托管沙箱服务。agentscope-harness 通过 io.agentscope.harness.agent.sandbox.impl.agentrun.AgentRunFilesystemSpec 接入该后端,与 Docker / Daytona / E2B / Kubernetes 并列,可在 HarnessAgent#filesystem(...) 中直接声明使用。
实现要点:
数据面优先:调用
https://{accountId}.agentrun-data.{region}.aliyuncs.com+X-API-Key+X-Acs-Parent-Id鉴权,不引入完整 Aliyun OpenAPI SDK;sandboxId由sessionId派生:使用 SHA-256 + Crockford Base32 输出 26 字符(ULID 形状)。利用 AgentRun 允许自定义 sandboxId 的特性,把「销毁后同 id 重建」等价于 resume;执行通道走 MCP:复用
io.agentscope.core.tool.mcp.McpClientBuilder.streamableHttpTransport(...),调用模板预先启用的process_exec_cmd/read_file/write_file;持久化默认 NAS-first:
workspaceRoot指向 NAS 挂载时,AbstractBaseSandbox的 4-分支起始命中 Branch A,doPersist/Hydrate退化为 no-op;无 NAS 时回退到 tar-via-MCP(与 Daytona/E2B TAR 同形)。
1. 何时选用 AgentRun¶
场景 |
推荐后端 |
|---|---|
已使用阿里云 / 业务侧资源在中国大陆区域、需要低延迟 |
AgentRun |
需要按沙箱实例独立挂载 NAS/OSS、文件自动持久、不想自己管 tar 快照 |
AgentRun(NAS-first) |
单进程开发、本地有 Docker daemon |
Docker |
多副本但暂无 K8s 集群、想要托管 sandbox-as-a-service |
Daytona / E2B / AgentRun |
已有自建 Kubernetes 集群 |
Kubernetes |
AgentRun 的差异化优势在于实例级 NAS/OSS 动态挂载,让工作区文件直接落到云上托管存储,省去手动管理 OssSnapshotSpec tar 包的开销;同时仍可叠加 harness 的 SandboxSnapshotSpec 做可移植冷备(见 §6)。
2. 前置准备(必读)¶
AgentRun 模板:在 AgentRun 控制台创建 Template,
containerConfiguration选择目标运行环境(默认基于 Ubuntu)。激活 MCP 工具:通过
ActivateTemplateMCP在模板上启用process_exec_cmd/read_file/write_file三件套——adapter 仅使用这三个工具。凭据:准备主账号 ID(
X-Acs-Parent-Id)和数据面 API Key(X-API-Key);adapter 不签名 ACS3,直接走 API Key。RAM 角色权限:模板执行角色需具备访问 NAS / OSS 的读写权限;具体策略参考阿里云文档「Sandbox 支持实例级别动态挂载 OSS」。
NAS 文件系统(推荐):准备一个与沙箱同地域、同 VPC 可达的 NAS 文件系统,记录
serverAddr;或准备标准存储、同地域的 OSS Bucket。
3. 最佳实践配置(NAS-first,核心推荐)¶
NAS 模式下,工作区文件落到 NAS 实例,沙箱销毁/重建之间天然持久,无需 Snapshot。
import io.agentscope.harness.agent.sandbox.impl.agentrun.*;
import io.agentscope.harness.agent.HarnessAgent;
import io.agentscope.harness.agent.sandbox.IsolationScope;
AgentRunNasMountConfig nas = new AgentRunNasMountConfig()
.setServerAddr("12345abc-xxx.cn-hangzhou.nas.aliyuncs.com")
.setMountDir("/mnt/nas") // 必须以 /home、/mnt 或 /data 开头
.setRemotePath("/")
.setEnableTLS(false);
AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec()
.setApiKey(System.getenv("AGENTRUN_API_KEY"))
.setAccountId(System.getenv("ALIYUN_ACCOUNT_ID"))
.setRegion("cn-hangzhou")
.setTemplateName("agentscope-default")
.setMcpServerUrl(System.getenv("AGENTRUN_MCP_URL")) // 必填,见 §8
.setNasConfig(nas)
.setWorkspaceRoot("/mnt/nas/workspace") // ★ 工作区落在 NAS 内
.setSandboxIdleTimeoutSeconds(1800)
.isolationScope(IsolationScope.SESSION);
HarnessAgent agent = HarnessAgent.builder()
.name("my-agent")
.model(model)
.filesystem(spec)
.build();
行为说明:
workspaceRoot以nasConfig.mountDir为前缀,adapter 自动判定workspaceOnNas=true,并对Sandbox#start()的探测分支返回 true(Branch A 常态命中)。默认
snapshotSpec=NoopSnapshotSpec,AbstractBaseSandbox.stop()内置 short-circuit,不会触发doPersistWorkspace,仅在 NAS 模式下显式mcp.exec("sync", 5)让 ossfs/NFS 落盘。sandboxIdleTimeoutSeconds(默认 1800)是 AgentRun 侧的闲置回收阈值,超时后实例自动销毁;adapter 在下次start()时通过同 id 重建恢复语义。sessionId与sandboxId的映射:AgentRunSandboxClient#deriveSandboxId对sessionId做 SHA-256 后截取 26 字符 Crockford Base32 输出,匹配 AgentRun 公开示例 ULID 形状,同 sessionId → 同 sandboxId。
4. 退路方案 A:无 NAS,纯 tar 快照¶
如果你尚未开通 NAS,或仅做 demo,可以省略 nasConfig/ossMountConfigs,工作区写到沙箱临时盘:
AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec()
.setApiKey(...)
.setAccountId(...)
.setRegion("cn-hangzhou")
.setTemplateName("agentscope-default")
.setMcpServerUrl(...)
.setWorkspaceRoot("/home/agentscope/workspace")
.snapshotSpec(new OssSnapshotSpec(...)); // ← 必须显式挂 SnapshotSpec
退路模式的代价:
doPersistWorkspace在stop()时通过 MCP 远程执行tar -cf - -C <root> . | base64 -w0,再走OssSnapshotSpec上传——大工作区(>100MB)上耗时显著;doHydrateWorkspace在start()时分块 base64 写入/tmp/agentscope-ws.b64后再python3 -c "tar xf -"解压,链路较长。
仅在 NAS/OSS 挂载暂时不可用时使用,生产环境优先选 §3。
5. 进阶方案 B:NAS 运行时 + OSS Snapshot 冷备¶
NAS 提供低延迟的实时读写,但备份/迁移/审计场景里仍可能希望工作区有版本化、跨集群可携带的 tar 归档。可以同时配置:
AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec()
.setApiKey(...).setAccountId(...).setRegion("cn-hangzhou")
.setTemplateName("agentscope-default")
.setMcpServerUrl(...)
.setNasConfig(nas)
.setWorkspaceRoot("/mnt/nas/workspace")
.snapshotSpec(new OssSnapshotSpec( // 与 NAS 不同的 bucket / key prefix
ossClient,
"agentscope-snapshots",
"agentrun/workspaces/"));
注意:
快照 bucket 必须与挂载 bucket 隔离(或至少 key prefix 错开),避免循环引用;
adapter 在
stop()时:先mcp.exec("sync", 5)让 NAS 落盘 → 再触发上层SnapshotSpec的 tar 持久化;next start() 优先走 NAS(Branch A);若 NAS 卷不可达(Branch B/C),从 OSS Snapshot 恢复。
6. AgentRun 原生持久化 vs SandboxSnapshotSpec¶
维度 |
AgentRun 原生 NAS/OSS 挂载 |
harness |
|---|---|---|
定位 |
运行时存储层(挂载到文件系统的 mount point) |
可移植归档接口(打包 tar 到外部 KV/对象存储) |
延迟 |
接近本地盘(NFS / ossfs FUSE) |
取决于 spec(OSS/Redis/Local) |
触发时机 |
每次写文件实时同步 |
仅在 |
粒度 |
文件级 |
工作区级 tar |
跨集群可携带 |
NAS 跨 region 受限;OSS 可跨 region 复制 |
tar 任何 spec 后端都能读取 |
依赖资源 |
NAS 文件系统 / OSS Bucket(同地域、同 VPC 可达) |
任何 KV/对象存储 |
耦合度 |
与 AgentRun 模板配置强耦合 |
adapter 无关、跨后端可复用 |
三种组合决策树:
question: 你需要工作区跨「沙箱销毁/重建」恢复吗?
├── 否(短时任务、CI 场景) → NoopSnapshotSpec, 无 NAS → §4 退路模式纯运行时
├── 是 + 单一 region/账号 + 低延迟优先 → §3 NAS-only
└── 是 + 需要跨 region 备份 / 审计 / 离线分析 → §5 NAS + OSS Snapshot
7. 限制清单¶
单实例 ≤ 5 个 OSS 挂载点(
AgentRunSandboxClientOptions.MAX_OSS_MOUNTS),超出 adapter 在validate()阶段抛SandboxConfigurationException;mountDir必须以/home/、/mnt/或/data/开头(AgentRun 模板侧约束),否则validate()失败;OSS Bucket 必须是标准存储,且与沙箱同地域;归档/低频存储不支持(平台限制,adapter 不主动校验);
沙箱实例最小内存 ≥ 512 MiB(AgentRun 模板侧;adapter 不校验);
StopSandbox在 AgentRun 侧是终态,不可恢复——adapter 不调用StopSandbox,而是通过DeleteSandbox+ 同sandboxId重建模拟 resume 语义;MCP URL 必填:adapter 不从
GetSandbox响应自动发现 MCP URL,需要从控制台/控制面查到完整 URL 后填入setMcpServerUrl(...)(后续若 AgentRun 暴露accessEndpoint,会升级为自动发现);SandboxIdleTimeoutSeconds:超时后实例被回收,任何未 sync 到 NAS 的临时文件丢失;NAS 模式下 adapter 在stop()显式sync,但建议把关键文件写到workspaceRoot子目录里。
8. 排错速查¶
现象 |
可能原因 |
处理 |
|---|---|---|
|
|
检查 |
|
|
从 AgentRun 控制台拷贝完整 MCP URL,填入 spec |
|
OSS/NAS 挂载点路径不合法 |
改为合规前缀 |
|
超出单实例 OSS 挂载点上限 |
合并或拆分多个 sandbox |
|
RAM 角色对 OSS/NAS 权限不足,或 API Key 失效 |
检查 RAM Policy / 重新签发 Key |
|
同 sandboxId 之前未清理(idle timeout 内仍存活) |
adapter 会自动复用,如人工误操作请等待 idle 超时或显式 DELETE |
|
模板冷启动 > 5 min(默认),或资源紧张 |
调大 |
MCP |
模板未激活 MCP 工具 |
通过 |
NAS 挂载点存在但 |
RAM 权限不全 / 跨 region / 跨 VPC 不可达 |
用阿里云控制台「沙箱诊断」+ |
观察沙箱状态:adapter 在 start() 时调用 GetSandbox 轮询,若需要在外部观察,可用同 sandboxId 直接调用:
GET https://{accountId}.agentrun-data.{region}.aliyuncs.com/2025-09-10/sandboxes/{sandboxId}
X-API-Key: ...
X-Acs-Parent-Id: {accountId}
返回的 status 字段包含 READY / RUNNING / FAILED 等。
9. 延伸阅读¶
Sandbox — 沙箱总体设计与隔离范围
Filesystem — 三种 filesystem 模式与选型