sandbox-agent
把 LLM agent CLI(opencode / codex / claude / pi / dsh)关进一次性 Docker 容器里跑,
用完即毁,产出安全地取回宿主机。零运行时依赖,宿主机只需要 docker。
from sandbox_agent import SandboxAgent, OpenCodeDriver
driver = OpenCodeDriver(provider="zhipuai-coding-plan", api_key=API_KEY)
with SandboxAgent(driver=driver, model="zhipuai-coding-plan/glm-5.3") as agent:
print(agent.ask("用 Python 写个快排, 存到 /tmp/qs.py"))
code, out = agent.container.exec(["python", "/tmp/qs.py"]) # 验收产出
agent.container.download("/tmp/qs.py", "./qs.py") # 取回宿主机
# 退出 with 块 -> 容器销毁
安装
uv add sandbox-agent # 或 pip install sandbox-agent
还需要装好了 agent CLI 的镜像,见 docker/ 与 .ci/build_docker.sh。
镜像 tag 由包内的 versions.json 唯一推导,格式
{repo}:{cli}-{cli版本}-{image_date},不用 latest。装好的包指向哪个镜像,直接问它:
python -c "from sandbox_agent import versions; print(versions.CLAUDE_IMAGE)"
镜像优先级:显式 image= > SANDBOX_AGENT_IMAGE_NAME(换私有 registry 用)>
driver.default_image > 内置默认值。
能干什么
| 对话 | chat() 拿可迭代的流式事件,推进主线;ask() 开旁支问一句,问完即扔 |
| 会话 | sessions.list() / .fork() / .dump() / .load() —— 会话能跨容器搬 |
| 容器操作 | container.upload() / .download() / .read() / .write() / .exec() —— 取回时只落普通文件和目录,链接不落地 |
| 能力注入 | skills.add() / .add_many() / .list(),rules.install() |
| 可观测 | token_usage、AgentEvent 流、按 tag 筛容器(list_containers) |
| 可审计 | 每次会话自动归档到 /tmp/sandbox-agent-<uid>/,默认开 |
扩展点
- 新 agent CLI:继承
BaseDriver,实现 11 个抽象成员。driver 只通过ContainerOps的三个原语(run/read_file/write_file)碰容器,单测伪造这三个方法即可。 - 新容器后端(podman、远程执行器):实现
ContainerRuntime协议,传给SandboxAgent(runtime_factory=...)。
完整 API 见 docs/sandbox_agent.md。
端到端冒烟
main.py 对真 CLI 跑一遍主要行为(容器 I/O、工具事件、ask、续接、fork 隔离、
skill / rules、delete / dump、审计、跨容器 load、假 key 抛 DriverError),多个 driver 并行:
uv run python main.py # 默认只跑 opencode
uv run python main.py claude codex # 指定若干个 (opencode|codex|claude|pi|dsh)
uv run python main.py all # 五个全跑
opencode 直连智谱,要 ZHIPUAI_CODING_TOKEN;其余四个走 runtime/litellm/
网关(GATEWAY_URL / GATEWAY_KEY 有默认值),网关怎么起见那边的 README。
会话审计
/tmp/sandbox-agent-<uid>/<YYYYMMDD>/<session_id>/
events.jsonl 归一后的 AgentEvent,一行一个;line 字段回指 session.jsonl 的行号
session.jsonl CLI 原始 stdout,逐字节照抄,不过滤
status.json 元数据 + 每一轮的结果
同一 session_id 的多轮落进同一目录,流式追加,可直接 tail -f。thinking 事件只在
后端返回推理正文时才有内容。归档失败只发 RuntimeWarning,不影响 chat。
jq -r '"\(.kind)\t\(.payload.command // .payload.path // .payload.text)"' events.jsonl
SandboxAgent(driver=driver, audit=False) # 关闭
from sandbox_agent import audit
audit.AUDIT_ROOT = "/data/sandbox-audit"
audit.RETENTION_DAYS = 30 # 默认 7; 0 = 永不清理, 按日期目录整个删
容器生命周期
close() / 退出 with 即销毁。兜底:容器闲置 keepalive_seconds(默认 3600s)后自杀,
有命令在跑就持续续期。
配置
优先级:环境变量 > ~/.config/sandbox-agent/config.json > 内置默认值。
| 环境变量 | JSON key | 默认值 |
|---|---|---|
SANDBOX_AGENT_IMAGE_NAME |
image |
driver 自己的 default_image |
SANDBOX_AGENT_RESOURCE_PREFIX |
prefix |
sandbox-agent |
SANDBOX_AGENT_CONTAINER_MEMORY |
memory |
1g |
SANDBOX_AGENT_CONTAINER_CPUS |
cpus |
1.0 |
SANDBOX_AGENT_KEEPALIVE_SECONDS |
keepalive_seconds |
3600(0 = 不自杀) |
SANDBOX_AGENT_MAX_CONTAINERS |
max_containers |
20 |
SANDBOX_AGENT_START_TIMEOUT |
start_timeout |
120 |
SANDBOX_AGENT_STOP_TIMEOUT |
stop_timeout |
30 |
SANDBOX_AGENT_EXEC_TIMEOUT |
exec_timeout |
60 |
SANDBOX_AGENT_CHAT_TIMEOUT |
chat_timeout |
300 |
SANDBOX_AGENT_SESSION_TIMEOUT |
session_timeout |
120 |
SANDBOX_AGENT_TRANSFER_TIMEOUT |
transfer_timeout |
300 |
方法参数 timeout=None 即用对应类别的配置值。
开发
uv sync --all-extras
uv run pytest # 单元测试, 全 mock, 不碰 docker
uv run pytest -m integration # 集成测试, 起真容器
docker pull debian:stable-slim # 集成测试用的镜像, 要事先拉好 (不会自动 pull, 没有则跳过)
集成测试镜像可用 SANDBOX_AGENT_TEST_IMAGE 替换,别用 alpine(busybox 的 timeout
超时不返回 124)。fixture 快照见 tests/fixtures/README.md。
已知限制见 TODO.md,变更历史见 CHANGELOG.md。
发布
先镜像后包:包里的 versions.json 指向镜像。改了 CLI 版本或 Dockerfile.base 时,
先手动 bump versions.json 的 image_date(YYYYMMDD,不会自动生成)。
./.ci/build_docker.sh --push # 1. 镜像; tag 已存在会拒绝, --force 覆盖
./.ci/build_pypi.sh --push # 2. 包; registry 上缺镜像会拒绝
License
GPL-3.0-or-later
Metadata
Release files for sandbox-agent 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sandbox_agent-0.2.2.tar.gz | 81.2 kB | Without provenance | Details for sandbox_agent-0.2.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sandbox_agent-0.2.2-py3-none-any.whl | Python 3 | none | any | Details for sandbox_agent-0.2.2-py3-none-any.whl |
Total release size: 183.8 kB
Release files / sandbox_agent-0.2.2.tar.gz
| Download URL | sandbox_agent-0.2.2.tar.gz |
|---|---|
| Size | 81.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e9e0e7c9e55b182bc7f9c6b1d48b171ece0a5e11fd8c15ef579d5050a2f7031
|
|
BLAKE2b-256 checksum How to use checksums |
bf7dd092553651ca7e30bce43d6db76ce2d5beccbd4f24320ab93b97bb172bbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / sandbox_agent-0.2.2-py3-none-any.whl
| Download URL | sandbox_agent-0.2.2-py3-none-any.whl |
|---|---|
| Size | 102.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dcfcaa3a8ef0a47603f8b82f1cd41eb124ae423d14e14360e22453fb03378ced
|
|
BLAKE2b-256 checksum How to use checksums |
1e95e573ceed8eadc72d6fa27345d063b6d5621eaf5feddcb223e6c5335902a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for sandbox-agent 0.2.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.