`sandbox.yao` 与 `package.yao` 并排放在助手目录下。其存在即激活 CLI Agent 模式。框架在加载时读取它,创建容器,并将执行路由给 Claude Code。
## 最小配置
```json
{
"version": "2.0",
"computer": {
"image": "yaoapp/tai-sandbox-claude:latest"
},
"runner": {
"name": "claude"
}
}
```
`version: "2.0"` 为必填项 —— 用于区分 v2 格式与旧版 `package.yao` 中的 `sandbox` 字段(v1 写法)。
## 完整参考
```json
{
"version": "2.0",
"computer": {
"image": "yaoapp/tai-sandbox-claude:latest",
"memory": "4GB",
"cpus": 2,
"ports": [3000, 8080],
"user": "sandbox",
"work_dir": "/workspace",
"mount_path": "/workspace",
"mount_mode": "rw",
"vnc": {
"enabled": true,
"password": "$ENV.VNC_PASSWORD",
"resolution": "1920x1080",
"view_only": false
}
},
"runner": {
"name": "claude",
"mode": "cli",
"options": {
"max_turns": 50,
"permission_mode": "bypassPermissions"
}
},
"lifecycle": "session",
"idle_timeout": "30m",
"max_lifetime": "24h",
"stop_timeout": "5s",
"filter": {
"kind": "box"
},
"prepare": [
{ "action": "exec", "cmd": "npm install -g typescript", "once": true },
{ "action": "exec", "cmd": "pip install ruff", "ignore_error": true }
],
"environment": {
"MY_VAR": "value",
"GOPATH": "$ENV.GOPATH"
},
"secrets": {
"GITHUB_TOKEN": "$ENV.GITHUB_TOKEN",
"NPM_TOKEN": "$ENV.NPM_TOKEN"
}
}
```
---
## `computer` 块
声明执行环境需求。框架在可用的 Tai 节点上创建符合这些规格的容器。
| 字段 | 类型 | 说明 |
|------|------|------|
| `image` | string | 容器镜像。`box` 类型时必填。 |
| `memory` | string | 内存限制,如 `"4GB"`、`"512MB"`。 |
| `cpus` | number | CPU 限制,同 Docker `--cpus`。 |
| `ports` | array | 要暴露的端口。整数数组或对象数组。 |
| `user` | string | 容器内用户。 |
| `work_dir` | string | 工作目录。默认 `/workspace`。 |
| `mount_path` | string | Workspace 卷在容器内的挂载路径。默认同 `work_dir`。 |
| `mount_mode` | string | 挂载模式:`"rw"`(默认)或 `"ro"`。 |
| `vnc` | bool 或 object | 启用 VNC / 桌面。`true` 是 `{ "enabled": true }` 的简写。 |
**端口格式** —— 两种写法均有效:
```json
"ports": [3000, 8080]
"ports": [
{ "port": 3000, "host_port": 9000, "protocol": "tcp" }
]
```
**VNC 对象字段:** `enabled`、`password`、`resolution`(如 `"1920x1080"`)、`view_only`。
---
## `runner` 块
选择负责执行的 Runner。
| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | Runner 名称。当前可用:`"claude"`(也可写 `"claude/cli"`)。 |
| `mode` | string | `"cli"`(默认)或 `"service"`。 |
| `options` | object | Runner 专有参数。 |
**Claude Runner 选项:**
| 选项 | 说明 |
|------|------|
| `max_turns` | Claude Code 自主执行的最大轮次。 |
| `permission_mode` | `"bypassPermissions"` 跳过 Claude 的交互式权限提示。 |
| `disallowed_tools` | 要禁用的工具名称数组(如 `["WebSearch"]`)。 |
| `allowed_tools` | 仅启用的工具名称数组。 |
---
## `lifecycle` 字段
控制容器在请求之间的管理方式。默认值:`"oneshot"`。
| 值 | 行为 | 适用场景 |
|----|------|---------|
| `oneshot` | 每次请求创建新容器。 | 无状态任务、CI 风格运行。 |
| `session` | 同一 `chatID` 内复用同一容器;chatID 变化则创建新容器。 | 交互式开发、多轮对话任务。 |
| `longrunning` | 容器在同一用户 + 助手 + Workspace 下跨会话共享;超过 `idle_timeout` 后销毁。 | 长期项目、持久开发环境。 |
| `persistent` | 容器永不自动销毁。 | 共享环境、永久工作区。 |
`idle_timeout`、`max_lifetime`、`stop_timeout` 均接受 Go duration 格式:`"30m"`、`"2h"`、`"24h"`。`stop_timeout` 默认值为 `"2s"`。
---
## `prepare` 步骤
容器启动后、Create Hook 运行前执行。用于复制配置文件或安装工具。
> **Skills 会自动复制。** 若助手目录下存在 `skills/` 文件夹,框架在 `Runner.Prepare` 期间会自动将其复制进容器,无需添加 `prepare` 步骤。
所有步骤共享三个公共字段:
| 字段 | 默认值 | 说明 |
|------|--------|------|
| `once` | `false` | 若本次配置 hash 与上次相同则跳过。所有 `once: true` 的步骤作为整体判断 —— hash 匹配时全部跳过,配置变更时全部重新执行。 |
| `ignore_error` | `false` | 该步骤失败时继续执行后续步骤。 |
**`copy`** —— 将文件或目录从助手目录复制进 Workspace:
```json
{ "action": "copy", "src": "config/settings.json", "dst": ".config/settings.json" }
```
- `src` 相对于宿主机上的助手目录
- `dst` 相对于容器内的 workspace 根目录(`~/` 展开为 workspace 根)
**`exec`** —— 在容器内执行 shell 命令:
```json
{ "action": "exec", "cmd": "npm install -g typescript", "once": true }
```
`exec` 的额外字段:
| 字段 | 默认值 | 说明 |
|------|--------|------|
| `background` | `false` | 后台运行(非阻塞)。适合启动服务。 |
---
## `environment` 和 `secrets`
两者都向容器注入环境变量。使用 `$ENV.KEY` 引用宿主机环境变量。
```json
"environment": {
"NODE_ENV": "production",
"API_BASE": "$ENV.API_BASE_URL"
},
"secrets": {
"GITHUB_TOKEN": "$ENV.GITHUB_TOKEN"
}
```
`secrets` 中的键会覆盖 `environment` 中同名的键。实践上,敏感值放 `secrets`,非敏感值放 `environment`。
> **规划中:** 未来版本中,`secrets` 的值将在静止状态下受到保护 —— Agent 无法以明文读取,但容器运行时可以使用。
---
## `filter` 块
限定容器在哪些 Tai 节点上运行。所有字段均为可选。
```json
"filter": {
"kind": "box",
"min_cpus": 4,
"min_mem": "8GB",
"os": "linux",
"arch": "amd64"
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `kind` | string 或 array | `"box"`(Docker/K8s)、`"host"`(裸机)或 `["box", "host"]`(任意)。 |
| `image` | string | 要求节点已缓存该镜像。 |
| `vnc` | bool | 要求节点支持 VNC。 |
| `os` | string | 目标操作系统,如 `"linux"`、`"windows"`。 |
| `arch` | string | CPU 架构,如 `"amd64"`、`"arm64"`。 |
| `min_cpus` | number | 最低可用 CPU 数。 |
| `min_mem` | string | 最低可用内存,如 `"8GB"`。 |
| `labels` | object | 按自定义标签匹配节点。 |
---
## 镜像参考
| 镜像 | 桌面 | VNC | 适用场景 |
|------|------|-----|---------|
| `yaoapp/tai-sandbox-claude:latest` | 无 | 无 | 代码生成、文件操作 |
| `yaoapp/tai-sandbox-claude-desktop-lite:latest` | XFCE(精简版)+ Chromium | 有 | Web 自动化、轻量 GUI 任务 |
| `yaoapp/tai-sandbox-claude-desktop:latest` | XFCE4(完整版)+ Chromium + CJK 字体 | 有 | 重度 GUI 任务、视觉验证 |
使用 VNC 镜像时,设置 `computer.vnc: true` 以在容器内启动显示服务器。
---
## 下一步
容器已就绪。了解"Computer"的含义,以及如何在 Hook 中与它交互。
→ **[Computer](./computer)**