2026年8月26日 2 分钟阅读

把团队 Agent 放进可控边界:OneCLI 自托管部署、凭据网关与 Sandbox 运维要点

tinyash 0 条评论

当团队把 Claude Code、Codex 一类编码 Agent 从个人电脑带进日常协作,问题很快不再是「能不能跑起来」,而是:每个人的 Agent 应拿到哪些连接权限?密钥能否避免进入 Agent 的环境?一个后台任务卡住后,会不会占满全部执行槽位?

OneCLI 是一个面向团队的 Agent 平台。它的重点不是再包装一个聊天窗口,而是为每位成员创建独立 Agent,把控制面、运行器、隔离 Sandbox 与凭据网关拆开。仓库的主许可证为 Apache-2.0;不过 apps/web/src/ee/packages/api/src/ee/apps/gateway/src/ee/apps/gateway/src/ee.rs 属于单独的 Enterprise License,生产使用这些企业功能需要订阅。部署或二次分发前,应先按仓库中的授权路径确认实际使用范围。

本文以官方仓库当前的自托管路径为准,讲清楚如何建立一个可验证的本地环境,以及上线前最容易被忽略的边界。

先理解:它把什么放在了哪里

OneCLI 的架构可以分成六个角色。

  • Web Dashboard:创建 Agent、编辑记忆与技能、管理连接、密钥和授权。
  • API Server:控制面,保存会话状态、工作队列与数据库数据。
  • Rust Gateway:拦截 Agent 的出站请求,并按规则注入凭据;Agent 使用 Proxy-Authorization 访问网关。
  • Runner:轮询控制面,启动、暂停和回收 Agent Sandbox;它不直接访问数据库。
  • Sandbox Supervisor:运行在每个 Sandbox 内,通过与供应商无关的 harness 接口承接 Agent runtime。
  • Channel Adapter:用于 Slack 渠道,每个 Agent 可对应自己的 Slack App。

这套拆分最关键的意义,是把「Agent 能发起请求」与「Agent 能看到密钥」分离。官方说明中,密钥在服务端以 AES-256-GCM 静态加密保存,只在请求时按 host/path 规则解密,再注入 header 或 query parameter。换言之,授权要以连接和请求匹配规则为单位设计,而不是把一串长期 API Key 写进 Agent 的环境变量或 Skill 文件。

最小可运行环境:先用开发栈验证链路

官方文档列出的前置条件是 mise、Rust 与 Docker:mise 用于安装 Node.js、pnpm 等工具;Docker 既承载 PostgreSQL,也承载 Agent Sandbox。仓库的 package.json 指定 Node.js 22 及以上、pnpm 9。

先获取代码并启动完整开发栈:

git clone https://github.com/onecli/onecli.git
cd onecli
mise install
pnpm install
pnpm dev

pnpm dev 会生成缺失的 .env 项、启动 PostgreSQL、执行迁移、生成 Prisma Client,并启动 Web、API、Gateway 与 Runner 相关进程。开发 Dashboard 默认监听 http://localhost:10254,Gateway 默认是 http://localhost:10255。不要把这组本地端口直接当成生产网络设计;生产部署应使用官方的自托管安装向导和配置文档,而不是照搬开发默认值。

如果 Docker 尚未运行,文档说明开发命令仍会启动除 Runner 外的组件并提示缺失状态。这很适合先核对控制面与界面,但不等价于验证了隔离执行。要让本机真正生成 Agent Sandbox,还需先构建镜像:

pnpm agent:build
pnpm dev

此命令构建 onecli-agent:dev。然后在 Dashboard 中创建一个测试 Agent,先保存模型密钥或服务连接,再把它授予该 Agent,最后才发送消息。官方实现明确要求:没有被授予的模型 Key 时,Sandbox 不会启动。这条顺序也应成为运维检查项:遇到「Agent 无响应」时,先查 grant,而不是先扩大网络权限或重复配置 Key。

出站唯一通路,才是 Sandbox 的安全边界

OneCLI 的 Runner 采取 outbound-only 模式:Runner 主动长轮询控制面获取工作并上报事件,不需要为 Runner 开放入站端口。因此笔记本、家庭实验室或 NAT 后的 VPC 都可以承载运行器,而无须为了让控制面回连去暴露端口或另建隧道。

但「没有入站端口」并不自动等于 Agent 被隔离。真正的边界在于 Sandbox 所在网络应保持 internal,且允许通过 Gateway 这一条通路离开。开发环境会把 RUNNER_NETWORK_INTERNAL=false 作为方便本机访问 Gateway 的默认行为;官方文档特别指出这只是开发设置。生产中应保留 RUNNER_NETWORK_INTERNAL=true,让 Gateway 同时连接 Sandbox 内网与需要访问的外部网络。

这意味着上线前要验证两件互补的事:

  1. Sandbox 能通过已获准的连接完成所需请求;
  2. Sandbox 不能绕过 Gateway 直连任意目标,也不能读取未授予的凭据。

第二项经常被忽略。若为了调试把 Sandbox 网络改成可自由出网,即使 Gateway 的凭据注入仍在工作,策略也从强制边界退化成「建议使用」。对真实第三方 SaaS、生产数据库或云账号而言,这两种状态的风险完全不同。

容量别只看 CPU:先算长期占位的 Sandbox

Runner 支持通过环境变量设定最大并发、每个 Sandbox 的内存、CPU 与 PID 限制。例如默认配置为:

RUNNER_MAX_SANDBOXES=4
RUNNER_SANDBOX_MEMORY_MB=2048
RUNNER_SANDBOX_CPUS=1
RUNNER_SANDBOX_PIDS=512

官方 Runner 文档给出的容量思路是:最大 Sandbox 数 × 单 Sandbox 内存 + 基础栈。按默认值,仅 Sandbox 就可能使用约 8 GiB;还应为 PostgreSQL、Gateway、API 和 Web 留出余量,文档建议主机至少额外保有约 10 GiB 可用内存后再提高上限。

更隐蔽的问题是「保持唤醒」的任务。一个正在运行后台进程或 watch 的 Sandbox 不会被暂停,它会持续占据槽位,而不是只在峰值时消耗资源。因此不要按瞬时并发为 RUNNER_MAX_SANDBOXES 定容量;应按最坏情况下长期存活的任务数估算。平台还提供 MAX_HELD_AWAKE_SANDBOXES 这一控制上限,超过时会淘汰最久空闲的保持唤醒 Sandbox,并如实报告其后台进程已丢失。对有定时检查、长时间测试或日志 watch 的团队,这是比单纯加大并发更可靠的保护。

两个失败模式:嵌套容器与孤儿资源

第一个失败模式来自嵌套容器。Sandbox 镜像带有 rootless Podman 与 docker CLI shim,但在 Runner 的 Docker 后端上,这些能力被有意限制:Sandbox 使用 no-new-privileges、删除全部 Linux capabilities,并采用 Docker 默认 seccomp profile。官方文档强调,不应为了让 Agent 在共享内核中运行嵌套容器而关闭 seccomp 或放宽这些限制。需要 Docker-in-Docker 类能力时,应评估官方所述的 microVM substrate,而不是以牺牲租户边界为代价绕过限制。

第二个失败模式是孤儿容器和卷。Runner 会对照控制面回收已不存在 Agent 所属的资源;对于数据库重置或 Runner 注册轮换造成的孤儿资源,还会按安装指纹和宽限期进行清理。默认 RUNNER_ORPHAN_REAP=true,宽限期由 RUNNER_ORPHAN_GRACE_SECONDS 控制。生产环境应先观察日志、确认同一 Docker daemon 上没有把其他工作负载误标为 OneCLI 资源,再决定是否调整宽限期或关闭自动清理。

发布前的四项验收

不要把首次成功启动当成验收完成。可以按下面的顺序做一份小型演练记录:

  • 身份验收:用两个测试成员分别创建 Agent,确认 Dashboard、Slack 身份和记忆空间不会串用。
  • 凭据验收:给 Agent 只授予一个低权限连接;在允许的 host/path 上验证请求成功,在未授权路径上验证请求被拒绝,同时确认 Agent 输出和 Sandbox 文件中没有密钥原文。
  • 网络验收:从 Sandbox 发起一个应当经过 Gateway 的请求,再尝试访问不在策略内的地址。两者都要记录 Gateway 日志和最终结果,不能只看聊天窗口里的自然语言反馈。
  • 生命周期验收:启动一个短任务、一个失败任务和一个保持唤醒任务,检查 Runner 的轮询、事件回报、暂停/回收以及孤儿清理是否符合预期。

这组测试的价值在于把抽象的「安全」拆成可观察结果:谁创建了资源、哪个连接被授予、请求走了哪条路径、拒绝是否真的发生,以及任务结束后容器和卷是否还残留。若团队准备接入生产 Slack 或云服务账号,还应把这些结果纳入变更审批和回滚记录,而不是只保存一张部署成功截图。

适用边界:把它当成运行平台,而非密钥分发脚本

OneCLI 适合需要把多位成员、多份 Agent 身份、可审计授权和隔离计算统一管理的团队。它不替代你已有的身份提供商、网络分段、密钥轮换或数据分级制度;恰恰相反,IdP、连接授权、Gateway 规则与 Sandbox 网络必须一起设计。

建议先用一个低权限、无生产数据的测试连接完成完整演练:创建 Agent、授予连接、验证经 Gateway 的请求、验证拒绝路径、让任务结束后检查 Sandbox 回收。只有这条闭环通过,再逐步接入 Slack、服务账号和更敏感的外部系统。把「能跑」升级为「知道谁在何时以什么权限跑过什么」,才是团队部署 Agent 平台的价值。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。