第30章 云沙箱配置指南
第30章 云沙箱配置
服务器可以通过多种沙箱提供商来开通远程 runner 主机。安装、提供商认证和启动步骤参见云沙箱主机文档;如需从独立 Python 包接入提供商,参见社区沙箱提供商。
通用设置
在服务器配置中添加顶层 `sandbox` 块:
```yaml sandbox: provider: modal server_url: https://your-server.example.com ```
| 字段 | 必填 | 说明 | |---|---|---| | provider | 是 | 提供商 id:modal、daytona、islo、blaxel、gensee、openshell、boxlite 或 microsandbox | | server_url | 是 | 远程 runner 回连的 Omnigent 服务器公网 URL | | host_config | 否 | 安装到每个沙箱内部的 Omnigent 配置,参见主机配置 | | git_clone | 否 | 新建仓库检出时的克隆策略,参见 Git 克隆选项 |
各提供商专属的配置块都是可选的,省略即使用该提供商的默认值。
Git 克隆选项
可选的 `git_clone` 映射用于减少托管沙箱创建仓库检出时下载的 Git 历史。对短周期编码会话来说,下面是个不错的起点:
```yaml sandbox: provider: kubernetes server_url: https://your-server.example.com git_clone: depth: 50 single_branch: true ```
这会在选定分支上检出所有文件,并保留最多 50 条提交历史。它适用于每个被请求的仓库,包括在领取 warm-pool Pod 后才克隆的仓库,且无需预先准备的工作区镜像。修改后需重启服务器,再创建新沙箱才能生效。
| 设置 | 默认值 | 行为 | |---|---|---| | depth | null | 完整历史。设为正整数则进行浅克隆,只取相应条数的提交 | | single_branch | null | 保持现有规则:指定了仓库分支则只取该分支,否则取所有分支。设为 true 只取被请求(或默认)分支;设为 false 取所有分支 | | filter | null | `blob:none` 启用部分克隆:保留提交历史,文件内容按需获取。首次检出仍包含所有文件。需要远端支持 filter;不支持时 Git 可能会警告并退回完整克隆 | | tags | true | 正常跟踪 tag。设为 false 等于传入 `--no-tags`,且对后续 fetch 持续生效。设为 true 并不保证每个远端 tag 都被获取 |
只接受这四个键,出现其他键或非 null、非映射的值都会导致服务器启动失败。省略 `git_clone` 则沿用现有的克隆命令。
只设置 `depth` 会保持现有的分支选择逻辑——Omnigent 会显式覆盖 Git 对浅克隆默认的单分支行为。对一个分支众多的仓库拉取全部分支,可能抵消大部分提速效果;如果适合你的工作负载,就设 `single_branch: true`。
该策略只在需要新建检出时生效。已保留的检出在会话唤醒时不会被重置、截断或重新配置;丢失临时工作区的 agent-sandbox 唤醒会按当前策略重新创建。`sandbox.providers` 列表中的每一项都可以整体覆盖共享的 `git_clone` 映射;对某一项使用 `git_clone: {}` 可恢复默认值。
Kubernetes(含 agent-sandbox warm pools)以及使用标准 exec 克隆实现的提供商支持这些选项。Gensee、Islo 和自定义工作区 materializer 必须显式实现支持;在非默认设置下,任何启动、替换或恢复操作都会在任何沙箱开通之前被拒绝,并指明提供商名称。第三方提供商通过 `SandboxCapabilities.git_clone_options=True` 声明支持,并遵守 `RepoWorkspace.git_clone`;覆盖了 `materialize_workspace` 的 exec 提供商在接入时必须接受其可选的 `git_clone` 参数。在默认设置下,旧的覆盖实现不会收到新的关键字参数。
克隆设置不携带任何凭据。初始克隆仍使用绑定所有者的 GitHub broker,后续 Git 操作使用主机已有的凭据助手。对私有仓库进行加深(deepen)或懒加载获取 blob,都需要对远端的持续访问权限。
之后补充更多历史
在浅检出中:
```bash git fetch --deepen=100 origin # 或恢复已配置分支选择的完整历史: git fetch --unshallow origin ```
这两个命令都不会扩大单分支 fetch refspec,也不会重新启用 tag。要获取另一个分支(比如用于 PR 对比),需显式指定其远程跟踪目标:
```bash git fetch origin '+refs/heads/main:refs/remotes/origin/main' # 如果两个分支都需要更多历史,同时包含两个 refspec: git fetch --deepen=100 origin \ '+refs/heads/main:refs/remotes/origin/main' \ '+refs/heads/feature:refs/remotes/origin/feature' git fetch --tags origin # 需要时显式获取 tag ```
当本地 PR diff 因历史过浅或基分支从未被拉取而找不到合并基时,Omnigent 会返回包含上述命令的可操作错误,而不是给出有误导性的分支末端对比。懒加载文件获取失败同样报错,缺失的内容永远不会被当作新增或删除的文件。
如果开发依赖大量历史、需要离线工作,或使用的工具期望完整历史,请保留全历史默认值。`blob:none` 是可选功能,因为它把开销转移到了后续读取:首次执行 `git show` 或 `git blame` 可能需要获取更多数据、耗时更长。Sparse checkout、子模块递归和 LFS 行为均不受影响。
Modal
```yaml sandbox: provider: modal server_url: https://your-server.example.com modal: image: ghcr.io/omnigent-ai/omnigent-host:latest secrets: [omnigent-llm] ```
`image` 默认为官方 Omnigent host 镜像。`secrets` 指定注入 runner 的 Modal secrets,其值仍保存在 Modal 的 secret 存储中。
Daytona
```yaml sandbox: provider: daytona server_url: https://your-server.example.com daytona: image: docker.io/you/omnigent-host:latest env: [OPENAI_API_KEY, ANTHROPIC_API_KEY] ```
`image` 默认为官方 Omnigent host 镜像。`env` 列出要复制到每个沙箱的服务器环境变量,列出的变量若未设置会导致启动失败。
Daytona 没有平台生命周期上限。Omnigent 在开通沙箱时会禁用 Daytona 的 15 分钟空闲自动停止,让主机在会话回合之间保持存活,并在会话删除时删除沙箱。如果托管沙箱在带外被停止或归档,下一条消息会原地恢复同一沙箱,保留其文件系统和工作区;归档状态的沙箱可能需要先 restore,因此唤醒最多等待 15 分钟(与冷启动创建的预算相同)。处于中间状态(启动中、停止中或归档中)的沙箱会被等待而不是被替换。只有沙箱已被删除时,Omnigent 才会创建带全新工作区的替代沙箱;沙箱仍在删除过程中,或唤醒期间发生提供商错误,则该回合以可重试错误失败,现有沙箱绑定保持不变。
Daytona Tier 1 和 2 组织将出站流量限制在固定白名单内。`server_url` 和模型端点必须能从 Daytona 访问;Tier 3 及以上解除该限制。在免费层上,可以使用白名单 `*.workers.dev` 域上的 Cloudflare Worker 中继,仓库在 `deploy/daytona/` 下提供了示例。Modal 在其入门层就提供完整出站能力。
Islo
```yaml sandbox: provider: islo server_url: https://your-server.example.com islo: image: ghcr.io/omnigent-ai/omnigent-host:latest env: [OPENAI_API_KEY, ANTHROPIC_API_KEY] idle_pause_after_s: 900 ```
`image` 默认为官方 Omnigent host 镜像。`env` 列出要复制到每个沙箱的服务器环境变量,列出的变量若未设置会导致启动失败。`idle_pause_after_s` 默认 900,设为 null 可禁用空闲暂停。
暂停的 Islo 主机收到新消息时,Omnigent 会恢复同一沙箱并重启 runner。修改 `idle_pause_after_s` 只影响新沙箱,不影响已有的。删除会话仍会删除沙箱。该提供商使用 `ISLO_API_KEY`,可用 `ISLO_BASE_URL` 和 `ISLO_COMPUTE_URL` 覆盖其服务端点。
Blaxel
```yaml sandbox: provider: blaxel server_url: https://your-server.example.com blaxel: image: blaxel/omnigent-host:latest env: [OPENAI_API_KEY, ANTHROPIC_API_KEY] region: us-was-1 memory_mb: 4096 ttl: 24h ```
`image` 默认为 `blaxel/omnigent-host:latest`。`env` 列出要复制到每个沙箱的服务器环境变量。`region` 默认为 `BL_REGION` 或 Blaxel 默认值。`memory_mb` 默认 4096。`ttl` 默认 24h,接受 `w`、`d`、`h`、`m`、`s` 单独或组合使用,如 `1h30m`。
`ttl` 是沙箱自创建起的最大存活时长,不是空闲超时。到期时 Blaxel 会删除沙箱,即使会话仍在活跃。启动 token 的有效期为 ttl + 1h;提供商命令输出上限为 4 MiB。
默认镜像将 Omnigent host 运行时与 Blaxel 必需的 sandbox-api 打包在一起。如果部署需要跨版本保持稳定,请用 `image` 固定某个已发布的 tag。
托管沙箱使用服务器进程的 Blaxel 工作区和凭据,Omnigent 用户不会映射到各自的 Blaxel 工作区。可设置 `OMNIGENT_BLAXEL_HOST_IMAGE` 覆盖默认镜像,无需修改配置文件。Blaxel SDK 的遥测已被禁用;请在服务器上保持 `DO_NOT_TRACK=1` 以维持该行为。
OpenShell
```yaml sandbox: provider: openshell server_url: https://your-server.example.com openshell: image: ghcr.io/omnigent-ai/omnigent-host:latest env: [OPENAI_API_KEY, ANTHROPIC_API_KEY] cluster: my-gateway workspace: team-alpha ```
`image` 默认为官方 Omnigent host 镜像。`env` 列出要复制到每个沙箱的服务器环境变量。`cluster` 默认取 `$OPENSHELL_GATEWAY` 或 `~/.config/openshell/active_gateway` 中当前活跃的 OpenShell 网关。`workspace` 默认先取 `$OMNIGENT_OPENSHELL_WORKSPACE`,再取 `default`。
服务器管理的 OpenShell 沙箱进入休眠后,其持久卷会被保留,会话报告为可唤醒的"asleep"状态。下一条消息会原地恢复同一沙箱,保留其名称和卷,并在继续之前等待其就绪。
原地恢复依赖 `SandboxClient.start`(openshell 0.0.105 新增)。使用旧版 SDK 时,主机将保持离线,而不会宣告一个不被支持的唤醒动作;请通过 `uv pip install --upgrade 'omnigent[openshell]'` 升级。目前的恢复是冷重启,而非热快照还原。
Microsandbox
microsandbox 提供商在与服务器同一台机器上的 micro-VM 中运行每个托管会话。由于 guest 中运行的是不可信的 agent 代码,其默认主机网络模式只暴露显式允许的 TCP 端口,而非整个主机。
```yaml sandbox: provider: microsandbox server_url: http://host.microsandbox.internal:8317 microsandbox: host_ports: [8317] ```
`host.microsandbox.internal` 是运行 microsandbox 的机器在 guest 侧的稳定主机名。在主机网络模式下:
只有当 `server_url` 指向 `host.microsandbox.internal` 时,其端口才会加入主机白名单;公网的 `server_url` 不会隐式开放主机上的对应端口。
guest 需要访问的其他主机本地服务,请在 `host_ports` 中以 1–65535 的整数端口列出。主机上其余一切均不可达。
Boxlite
```yaml sandbox: provider: boxlite server_url: https://your-server.example.com boxlite: image: docker.io/me/omnigent-host:latest env: [OPENAI_API_KEY, GIT_TOKEN] disk_size_gb: 100 cloud: endpoint: https://boxlite.example.com:8100 ```
`image` 默认为官方 Omnigent host 镜像。`env` 列出要复制到每个沙箱的服务器环境变量。`disk_size_gb` 必须是正整数,省略则使用 SDK 默认值。
只需提供一种模式:`cloud.endpoint` 选择云模式并使用 `BOXLITE_API_KEY`;`local.home_dir` 和 `local.registry` 配置本地模式。两个块都未设置时使用本地模式。
Gensee
Gensee 仅作为托管主机提供商。服务器通过 HTTPS 与 Gensee 控制平面通信,Omnigent 中不安装任何云提供商凭据或 Gensee 实现包。创建托管会话时会分配一个沙箱,由其控制平面启动 omnigent host,并等待该主机回连。Gensee 不实现 `omnigent sandbox create`、远程 exec/文件复制原语、已停止沙箱的恢复,以及工作区 fork/merge。
生产端点和标准 token 变量都是默认值,因此最小配置只需 provider + server_url:
```yaml sandbox: provider: gensee server_url: https://your-server.example.com ```
使用专用或开发环境端点时,请显式配置:
```yaml sandbox: provider: gensee server_url: https://your-server.example.com gensee: endpoint: https://sandbox.gensee.ai api_token_env: GENSEE_CONTROLLER_API_TOKEN workspace_root: /mnt/gensee-tclone/workspaces operation_timeout_s: 900 poll_interval_s: 2 request_timeout_s: 40 retry_timeout_s: 60 env: [] ```
| 设置 | 默认值 | 用途 | |---|---|---| | endpoint | `https://sandbox.gensee.ai` | Gensee HTTPS 控制平面基础 URL | | api_token_env | `GENSEE_CONTROLLER_API_TOKEN` | 存放 API token 的服务器环境变量名 | | workspace_root | `/mnt/gensee-tclone/workspaces` | 每个沙箱内的工作区绝对根路径 | | operation_timeout_s | 900 | 主机启动提交、重试和轮询的共享截止时间;迟到的响应会被拒绝 | | poll_interval_s | 2 | 操作状态请求的轮询间隔 | | request_timeout_s | 40 | HTTP I/O 超时;主机启动期间受剩余操作预算限制 | | retry_timeout_s | 60 | 传输错误和 HTTP 500/502/503/504 的重试预算;0 表示禁用重试 | | env | `[]` | 要复制进沙箱 secret 的服务器环境变量名 |
endpoint 必须使用 HTTPS,且不能包含凭据、查询串或 fragment。未知设置或格式错误的值会阻止服务器启动,而不是在首个用户会话时才失败。
直接构造 launcher 时可用 `GENSEE_CONTROLLER_URL` 覆盖默认端点;在服务器托管配置中,显式的 `sandbox.gensee.endpoint` 优先。
Gensee API token 保存在服务器端,用于授权生命周期请求。每个沙箱会通过 Gensee 的短期 secret 存储收到一个由服务器签发的独立 Omnigent host token(有效期七天),它不包含在持久的操作请求中。默认不注入任何模型或 Git 凭据——`env` 中只列出允许服务器上所有沙箱接收的变量,或者留空,让每个用户从自己的沙箱终端自行登录。
原生 harness 桥接服务器
原生 harness(如 claude-native)会在沙箱主机上运行小型 HTTP 服务器,供 harness 的 hook 和辅助子进程回调:
工具中继,默认只绑定回环地址(127.0.0.1),普通主机上它不会出现在其他任何网络接口上。
MCP 控制入口,默认监听 harness socket 根目录下的 Unix domain socket(`/tmp/omnigent-
如果沙箱的 SSRF 加固无条件拒绝回环目标(openshell 提供商就是这类后端),就无法访问以回环地址宣告的中继,导致每次 prompt 都失败。此时可在沙箱主机环境中设置 `OMNIGENT_BRIDGE_BIND_HOST=0.0.0.0` 选择绑定所有接口:两台服务器将监听所有接口(回环消费者不受影响),并宣告主机的可路由地址,使沙箱内的 hook 可以访问它们。
| 环境变量 | 默认值 | 说明 | |---|---|---| | OMNIGENT_BRIDGE_BIND_HOST | 中继仅回环,MCP 入口用 Unix socket | 选择绑定方式。未设置时,工具中继仅绑定回环(127.0.0.1),MCP 控制入口使用 Unix domain socket。设为 `0.0.0.0` 时两台服务器绑定所有接口,并宣告检测到的可路由地址(主机没有可路由地址时退回回环)。设为其他值时,两台服务器都用该精确主机进行绑定和宣告。设为任意非空值还会让 MCP 入口改用端口池中的 TCP 端口 | | OMNIGENT_BRIDGE_PORT_POOL | 28700–28715 | 覆盖服务器端口池。接受逗号分隔的端口和闭区间范围,如 `28700-28703,29000` |
TCP 绑定的桥接服务器从一个小而固定的端口池(默认 28700–28715)取端口,这样沙箱网络策略可以按精确的主机和端口设置白名单。一台主机上可同时运行多台服务器——每个会话一个工具中继,设置 `OMNIGENT_BRIDGE_BIND_HOST` 后还有 MCP 入口——因此请把整个端口池加入白名单,而不是单个端口。端口池耗尽时,服务器会退回 OS 分配的临时端口,这种端口无法被精确端口策略覆盖。
这些服务器上的所有端点(`GET /health` 除外)都需要各中继独立的 bearer token,因此将它们的主机和端口加入白名单不会暴露任何未认证的功能。
主机配置
与提供商无关的 `host_config` 块对应安装到每个沙箱内、`omnigent host` 启动前的 `~/.omnigent/config.yaml` 内容:
```yaml sandbox: provider: modal server_url: https://your-server.example.com host_config: providers: litellm: kind: gateway default: [pi] openai: base_url: http://litellm.litellm.svc.cluster.local/v1 api_key_ref: env:LITELLM_API_KEY wire_api: chat ```
在启动或恢复时,服务器会替换或删除之前由它注入的条目;沙箱内以其他名称创建的配置不受影响。
不要把 secrets 写进 `host_config`。请使用 `api_key_ref: env:VAR`,该变量会在沙箱内部由其提供商专属的凭据来源解析。内联的 `api_key` 值会被拒绝。服务器会在启动时校验该块。