agentrun
agentrun 用一条命令在沙箱里运行 claude-code、codex、pi 和 dsh,支持 macOS、Linux、Cloud Managed 容器和 docker 容器。
Motivation
在脚本或 CI 里让 claude-code、codex、pi 或 dsh 去改代码,每次都要处理同样的事:agent 能写哪些文件、能不能联网、会不会读到你自己的配置和账号;各运行时的参数、输出格式和成败判定各不相同;同一段脚本换到 docker 或 Cloud Managed 容器里,可能因为缺少沙箱工具或登录而失败,报错也看不出原因。
agentrun 把这些事放进一条命令。它在当前环境能提供的沙箱里启动运行时,把运行时的输出转换成同一种事件流,按统一的规则给出退出码;agentrun doctor 在启动前检查环境,失败时说明原因和改法。选哪个模型、失败后是否重试、怎么安装运行时,仍由调用方决定。
Get Started
给使用 agentrun 的人:怎么安装、怎么调用、出了问题怎么查。
-
$ agentrun doctor claude-code$ agentrun claude-code --prompt "..."[end] finished 9.9s快速开始安装 agentrun,检查环境,在沙箱里运行第一个任务,再把它放进脚本。
-
--network custom --allow-host pypi.org-e AGENTRUN_SANDBOX=off--timeout 600使用指南访问网络、传入密钥、限制时间、接着上一次运行继续、在 docker 里运行、在 CI 里判断成败、常见问题。
Environment
开发者文档从这一节开始。下图是源代码里各模块的关系,每个页面开头的「代码位置」列出对应的源文件。
可见性按目录限定:每个目录下的文件都是私有子模块,外部只能用 mod.rs re-export 的项:tests/ 或 main.rs 用到的写 pub use,只有 crate 内其他目录用到的写 pub(crate) use。私有子模块里的项可以保持 pub,能不能从外部访问由 mod.rs 是否 re-export 决定。唯一的例外是 runtime/ 的 claudecode、codex、pi 三个子模块声明为 pub mod,因为每个适配器有自己的集成测试。理由:编译器只对外部访问不到的项报告未使用,可见性按目录限定后,新的死代码才会被报出来。run/ 把 doctor 子命令分派给 doctor.rs,doctor.rs 复用 run/ 的 Caller 与临时目录函数,这一处是有意保留的分派关系。
平台相关的代码按平台分文件:process_tree/ 的 linux.rs 与 macos.rs、sandbox/ 的 bubblewrap.rs 与 seatbelt.rs,同一目录的两个文件提供同一组项,由 mod.rs 按操作系统选择;包裹命令与 Seatbelt 配置在两个平台都编译。理由:单元测试在 Linux 上也能检查 macOS 的包裹参数。
agent 在什么样的环境里运行:会话环境变量、临时目录、凭据与进程,沙箱与网络限制,以及在四种环境里怎么调用。
-
Sessionauth--env-file prod.env会话环境环境变量、PATH、会话临时目录、凭据、进程组、信号与超时、多个运行同时进行。
-
Isolation--sandbox on|relax|off--network none|full|custom沙箱与网络--sandbox on|relax|off、--network、--deny-read、各运行时怎么关进沙箱、剩余风险。
在四种环境里怎么调用
工具不探测自己运行在哪种环境里。它只看操作系统,并在启动前实际启动一次沙箱来判断沙箱能不能用。理由:按环境探测一旦误判,本机会话就会在没有沙箱的情况下运行;实际启动一次沙箱则能直接回答「能不能隔离」这个问题。
| 环境 | 沙箱 | 调用方的写法 |
|---|---|---|
| 本机 macOS | Seatbelt,系统自带 | 不用写 --sandbox |
| 本机 Linux | bubblewrap(bwrap,claude-code、pi 与 dsh 另需 socat);codex 用它自己的沙箱 | 不用写;没装 bwrap 时 agentrun 报错并给出安装命令 |
| Cloud Managed 容器(Claude 云端、Codex 云端) | 同本机 Linux,要求容器里装了 bwrap 与 socat,且能创建用户命名空间 | 不用写。在 Claude 云端验证过;Codex 云端没有验证过 |
| docker 容器 | 默认的 docker 容器不能创建用户命名空间,沙箱无法启动 | 启动方写 --sandbox off 或设 AGENTRUN_SANDBOX=off,隔离边界是容器本身 |
Cloud Managed 容器有两种:Claude 云端只运行 claude-code、pi 与 dsh,Codex 云端只运行 codex 与 pi。工具不区分这两种容器,由启动方选择运行时。
Event and Output
agentrun 输出的统一事件流与三种输出格式。后两页是运行时原始输出的字段参考。
-
{"type":"tool",...}[explore#1] tool Grep[end] finished事件与输出统一事件流、subagent 与用量、end.status、text 与 rich 格式。
-
$claude -p --output-format stream-json{"type":"system","subtype":"init"}{"type":"result","is_error":false}claude-code 事件流stream-json 输出的每种事件、字段、运行顺序、subagent 嵌套、错误与退出码。
-
$pi -p --mode json{"type":"session","version":3}{"type":"agent_settled"}pi 事件流--mode json 输出的每种事件、消息角色、内容块、usage、错误与退出码。
Runtime
怎么调用 agentrun:命令行选项、启动前检查、doctor 与退出码,以及 agentrun 怎么启动每个运行时、怎么判定成败。
Testing and Release
怎么测试 agentrun、四种环境的验收由谁执行、怎么发布。
不支持的功能
以下功能目前没有需求支撑,agentrun 不提供,表中写了现在的替代做法:
| 功能 | 内容 |
|---|---|
--skill DIR | 把技能目录复制到各运行时的技能位置(.claude/skills/、.codex/skills/、.pi/skills/)。替代做法:调用方自己把技能文件放进工作目录,并在提示词里写出路径 |
| 配置文件 | 固定的追加目录与运行时可执行文件路径。替代做法:追加目录用 --path,运行时从 PATH 查找 |
agentrun exec -- <命令> | 用同样的会话环境、凭据与沙箱启动任意命令,只提供退出码与 start、end 事件。替代做法:任意命令由调用方自己启动 |
| 额外的可写目录 | 在工作目录与会话临时目录之外再开放一个可写目录 |
--allow-host-file | 从文件读主机列表。替代做法:调用方需要长列表就在脚本里展开成多个 --allow-host |
| 按请求内容过滤网络 | 需要解密 HTTPS。过滤代理只按目标主机与端口判断 |
| 命令与 Python 包的黑名单 | 运行时的权限规则只匹配命令文字,容易绕过;沙箱拒绝指定路径只在沙箱运行时生效 |