Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions .github/workflows/crabbox.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
name: crabbox

# Validates the openclaw/crabbox integration (https://crabbox.sh).
# - Installs a pinned, checksum-verified upstream Crabbox release.
# - Loads config/crabbox.example.yaml through Crabbox itself.
# - Exercises E2B lifecycle, archive sync, and process streaming against a strict mock.
# - Builds mdBook so the Crabbox integration page stays linked.
# - Optional Islo smoke when repository secret ISLO_API_KEY is set
# (mint with: islo api-key create …). Forks without the secret no-op cleanly.

on:
workflow_dispatch:
push:
branches: [main]
paths:
- "README.md"
- "config/crabbox.example.yaml"
- "docs/src/integration/crabbox.md"
- "docs/src/integration/e2b.md"
- "docs/src/SUMMARY.md"
- "docs/src/configuration/env-vars.md"
- "docs/src/getting-started/**"
- "docs/src/troubleshooting/common-issues.md"
- "scripts/tests/crabbox-e2b-contract-server.py"
- ".github/workflows/crabbox.yml"
pull_request:
paths:
- "README.md"
- "config/crabbox.example.yaml"
- "docs/src/integration/crabbox.md"
- "docs/src/integration/e2b.md"
- "docs/src/SUMMARY.md"
- "docs/src/configuration/env-vars.md"
- "docs/src/getting-started/**"
- "docs/src/troubleshooting/common-issues.md"
- "scripts/tests/crabbox-e2b-contract-server.py"
- ".github/workflows/crabbox.yml"

permissions:
contents: read

env:
CRABBOX_VERSION: "0.40.0"
CRABBOX_LINUX_AMD64_SHA256: "3bcd7c48b9866e3ac05b35bb67afa3282e831d1b9f749c5998c102944c1a5cfe"

concurrency:
group: crabbox-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
integrate:
runs-on: ubuntu-latest
Comment thread
zozo123 marked this conversation as resolved.
Outdated
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install openclaw/crabbox
run: |
set -euo pipefail
install_dir="${RUNNER_TEMP}/crabbox/bin"
archive="crabbox_${CRABBOX_VERSION}_linux_amd64.tar.gz"
mkdir -p "${install_dir}"
curl --fail --location --silent --show-error \
"https://github.com/openclaw/crabbox/releases/download/v${CRABBOX_VERSION}/${archive}" \
--output "${RUNNER_TEMP}/${archive}"
(
cd "${RUNNER_TEMP}"
printf '%s %s\n' "${CRABBOX_LINUX_AMD64_SHA256}" "${archive}" | sha256sum --check -
)
tar -xzf "${RUNNER_TEMP}/${archive}" -C "${install_dir}" crabbox
echo "${install_dir}" >> "${GITHUB_PATH}"
"${install_dir}/crabbox" --version

- name: Validate AgentENV E2B control and data-plane contract
env:
CRABBOX_E2B_API_URL: http://127.0.0.1:18080
CRABBOX_E2B_API_KEY: agentenv-ci-placeholder
run: |
set -euo pipefail
config_path="${RUNNER_TEMP}/crabbox.example.yaml"
install -m 600 config/crabbox.example.yaml "${config_path}"
export CRABBOX_CONFIG="${config_path}"
export XDG_CONFIG_HOME="${RUNNER_TEMP}/crabbox-xdg"

cert_dir="${RUNNER_TEMP}/crabbox-contract-tls"
mkdir -p "${cert_dir}"
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout "${cert_dir}/key.pem" \
-out "${cert_dir}/cert.pem" \
-days 1 \
-subj "/CN=*.localhost" \
-addext "subjectAltName=DNS:*.localhost" \
>/dev/null 2>&1
export SSL_CERT_FILE="${cert_dir}/cert.pem"

python3 scripts/tests/crabbox-e2b-contract-server.py \
--cert "${cert_dir}/cert.pem" \
--key "${cert_dir}/key.pem" \
>"${RUNNER_TEMP}/crabbox-contract-server.log" 2>&1 &
server_pid=$!
cleanup() {
kill "${server_pid}" 2>/dev/null || true
wait "${server_pid}" 2>/dev/null || true
cat "${RUNNER_TEMP}/crabbox-contract-server.log"
}
trap cleanup EXIT

for _ in {1..50}; do
if curl --fail --silent --output /dev/null http://127.0.0.1:18080/health; then
break
fi
sleep 0.1
done
curl --fail --silent --output /dev/null http://127.0.0.1:18080/health

crabbox providers | grep -E '^e2b$'
crabbox config show --json > "${RUNNER_TEMP}/crabbox-config.json"
python3 - "${RUNNER_TEMP}/crabbox-config.json" <<'PY'
import json
import sys

with open(sys.argv[1], encoding="utf-8") as handle:
config = json.load(handle)
assert config["provider"] == "e2b", config["provider"]
assert config["target"] == "linux", config["target"]
assert config["e2b"]["template"] == "ubuntu", config["e2b"]
assert config["e2b"]["workdir"] == "crabbox", config["e2b"]
assert config["e2b"]["apiUrl"] == "http://127.0.0.1:18080", config["e2b"]
PY
crabbox doctor --provider e2b

contract_repo="${RUNNER_TEMP}/crabbox-contract-repo"
git init --quiet "${contract_repo}"
git -C "${contract_repo}" config user.name "AgentENV CI"
git -C "${contract_repo}" config user.email "ci@agentenv.invalid"
printf 'archive-sync-contract\n' > "${contract_repo}/contract.txt"
git -C "${contract_repo}" add contract.txt
git -C "${contract_repo}" commit --quiet -m "test fixture"
(
cd "${contract_repo}"
crabbox run --provider e2b -- echo crabbox-agentenv-contract-ok
) 2>&1 | tee "${RUNNER_TEMP}/crabbox-run.log"
grep -Fx "crabbox-agentenv-contract-ok" "${RUNNER_TEMP}/crabbox-run.log"

curl --fail --silent http://127.0.0.1:18080/contract-state \
> "${RUNNER_TEMP}/crabbox-contract-state.json"
python3 - "${RUNNER_TEMP}/crabbox-contract-state.json" <<'PY'
import json
import sys

with open(sys.argv[1], encoding="utf-8") as handle:
state = json.load(handle)
assert state["errors"] == [], state
assert state["list"] >= 1, state
assert state["create"] == 1, state
assert state["connect"] == 1, state
assert state["upload"] == 1, state
assert state["process"] >= 3, state
assert state["marker_commands"] == 1, state
assert state["delete"] == 1, state
PY

- uses: taiki-e/install-action@mdbook
Comment thread
zozo123 marked this conversation as resolved.
Outdated

- name: Build docs (mdBook)
run: |
set -euo pipefail
ln -sf ../../src/api/openapi.yml docs/src/openapi.yml
mdbook build docs

- name: Guard — optional Islo smoke
id: guard
env:
ISLO_API_KEY: ${{ secrets.ISLO_API_KEY }}
Comment thread
zozo123 marked this conversation as resolved.
Outdated
run: |
if [ -z "${ISLO_API_KEY}" ]; then
echo "ISLO_API_KEY not configured — skipping islo smoke."
echo "run=false" >> "$GITHUB_OUTPUT"
else
echo "run=true" >> "$GITHUB_OUTPUT"
fi

- name: crabbox run --provider islo
if: steps.guard.outputs.run == 'true'
env:
ISLO_API_KEY: ${{ secrets.ISLO_API_KEY }}
run: |
set -euo pipefail
# Prefer Islo tenant defaults (omit --islo-image); keep the lease small.
crabbox run \
--provider islo \
--islo-vcpus 2 \
--islo-memory-mb 2048 \
--islo-disk-gb 10 \
--no-sync \
-- echo crabbox-islo-ok
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Temporary Items
env/
.env

# Local openclaw/crabbox project config (copy from config/crabbox.example.yaml)
.crabbox.yaml

# OpenAPI Generator
.openapi-generator/

Expand Down
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,40 @@ see 📖 [Deployment](https://kvcache-ai.github.io/AgentENV/deployment/manual-co

---

## 🦀 Crabbox sandbox client

[Crabbox](https://crabbox.sh/) ([openclaw/crabbox](https://github.com/openclaw/crabbox))
is the recommended sandbox client for AgentENV: sync a checkout into a
Firecracker sandbox, run a command, stream output, and release.

```bash
brew install openclaw/tap/crabbox

export CRABBOX_E2B_API_URL=https://agentenv.example.com
export CRABBOX_E2B_API_KEY=e2b_000000
export CRABBOX_E2B_TEMPLATE=ubuntu # AgentENV template id or name
# optional: install -m 600 config/crabbox.example.yaml .crabbox.yaml

crabbox doctor --provider e2b
crabbox run --provider e2b -- make test-unit
```

`crabbox run` requires AgentENV to advertise an HTTPS wildcard sandbox proxy
domain; the control-plane URL alone is not sufficient. See the integration guide
for the server, DNS, and TLS setup.

See 📖 [Crabbox integration](https://kvcache-ai.github.io/AgentENV/integration/crabbox.html).
Verified with [Islo](https://islo.dev) via `crabbox --provider islo` while landing
this client path.

## 🔌 E2B compatibility

AgentENV exposes an E2B-compatible HTTP API. Point `E2B_API_URL` at your
server and use the standard E2B Python / TypeScript SDK without any code
changes. See 📖 [E2B integration](https://kvcache-ai.github.io/AgentENV/integration/e2b.html)
for setup details.
server and use the standard E2B Python / TypeScript SDK without any AgentENV
code changes. Crabbox’s `e2b` provider also works when host-based sandbox
routing is configured. See 📖
[E2B integration](https://kvcache-ai.github.io/AgentENV/integration/e2b.html)
for SDK setup details.

---

Expand Down
25 changes: 25 additions & 0 deletions config/crabbox.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Example openclaw/crabbox config for AgentENV.
# Install with mode 0600 at the repo root as `.crabbox.yaml`, or merge it into
# your user Crabbox config.
# Docs: https://crabbox.sh/ · Provider: https://crabbox.sh/providers/e2b.html
#
# Endpoint and auth stay in the environment (never commit destinations or keys):
# export CRABBOX_E2B_API_URL=https://agentenv.example.com
# export CRABBOX_E2B_API_KEY=e2b_000000
#
# `crabbox run` also requires AgentENV to advertise an HTTPS wildcard sandbox
# proxy domain. See docs/src/integration/crabbox.md before running this config.
#
# Then:
# brew install openclaw/tap/crabbox
# install -m 600 config/crabbox.example.yaml .crabbox.yaml
# crabbox doctor --provider e2b
# crabbox run --provider e2b -- make test-unit

provider: e2b
target: linux
e2b:
# AgentENV template id or name (aenv pull … / aenv template list)
template: ubuntu
# Dedicated subdirectory inside the sandbox (not /, /tmp, …)
workdir: crabbox
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

# Integration

- [Crabbox](./integration/crabbox.md)
- [E2B](./integration/e2b.md)

# Troubleshooting
Expand Down
19 changes: 17 additions & 2 deletions docs/src/configuration/env-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,24 @@ These variables are consumed by the repository's Docker Compose and Kubernetes h
| `AENV_FIRECRACKER_SERIAL_DIR` | `$AENV_HOME/logs/serial` | Override the directory for persistent Firecracker serial output. Files are grouped under `{serial_dir}/{sandbox_id}/`. |
| `AENV_PERSISTED_SANDBOX_STORE_PATH` | `$AENV_HOME/persisted-sandboxes` | Override the directory where paused sandbox state is persisted across server restarts. |

## E2B SDK / CLI
## E2B SDK / CLI / Crabbox

These variables configure the E2B SDK and CLI to point at an AgentENV server. Values depend on your deployment mode.
These variables configure the E2B SDK and CLI to point at an AgentENV server.
[Crabbox](../integration/crabbox.md)’s `e2b` provider shares some of them but
uses host-based sandbox URLs rather than `E2B_SANDBOX_URL`.

| Variable | Description |
|----------|-------------|
| `E2B_API_URL` | AgentENV server API base URL |
| `E2B_SANDBOX_URL` | Sandbox proxy URL (for WebSocket and process interaction) |
| `E2B_API_KEY` | API key for authentication |
| `E2B_ACCESS_TOKEN` | Access token (used by `e2b template` commands) |
| `CRABBOX_E2B_API_URL` | Crabbox override for `E2B_API_URL` (takes precedence) |
| `CRABBOX_E2B_API_KEY` | Crabbox override for `E2B_API_KEY` (takes precedence) |
| `CRABBOX_E2B_DOMAIN` | Fallback wildcard sandbox domain; AgentENV normally advertises `[sandbox_proxy].domains[0]` in its sandbox response |
| `CRABBOX_E2B_TEMPLATE` | AgentENV template id/name for `crabbox run --provider e2b` |
| `CRABBOX_E2B_WORKDIR` | Dedicated directory inside the sandbox used for repo sync and commands |
| `CRABBOX_E2B_USER` | Optional sandbox login name used for file ownership and commands |

### Values by Deployment Mode

Expand Down Expand Up @@ -73,6 +81,13 @@ export E2B_ACCESS_TOKEN=dummy

> For local development, any non-empty value works for `E2B_API_KEY` and `E2B_ACCESS_TOKEN` because the server only checks that the auth header is present.

> Crabbox does not read `E2B_SANDBOX_URL`. Its `e2b` provider connects to
> `https://{port}-{sandboxID}.{domain}`. Configure AgentENV's host-based sandbox
> routing, wildcard DNS, and TLS as described in the
> [Crabbox integration](../integration/crabbox.md). A plain loopback
> `E2B_API_URL` is sufficient for `crabbox doctor` and `list`, but not for
> `warmup` or `run`.

## Gateway and Scheduler

These variables apply to both the gateway and scheduler processes.
Expand Down
5 changes: 3 additions & 2 deletions docs/src/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The repository is available at <https://github.com/kvcache-ai/AgentENV>.
- **Pause and resume** with memory + disk snapshots for instant cold start
- **Layered block devices** via overlaybd + ublk for copy-on-write image sharing
- **Snapshot-backed template builder** for publishing reusable, pre-configured sandbox runtimes
- **E2B-compatible API** so existing E2B SDKs and CLIs work out of the box
- **E2B-compatible API** for existing E2B SDKs and CLIs, plus [Crabbox](../integration/crabbox.md) on deployments with host-based sandbox routing
- **Reverse proxy** to reach services running inside sandboxes via HTTP and WebSocket
- **Multi-node scaling** with a gateway + scheduler control plane (prototype)

Expand All @@ -26,11 +26,12 @@ AgentENV is built for teams running AI agents that need isolated execution envir

## Interacting with the Server

AgentENV exposes an HTTP API. There are four ways to use it:
AgentENV exposes an HTTP API. There are several ways to use it:

| Method | Best for |
|--------|----------|
| **[aenv CLI](./aenv-cli.md)** | Interactive use, scripting, local development |
| **[Crabbox](../integration/crabbox.md)** | Recommended sandbox client ([openclaw/crabbox](https://github.com/openclaw/crabbox)) — repo sync + remote run for agents and automation |
| **[E2B](../integration/e2b.md)** | Application code — existing E2B-based applications work with AgentENV without modification |
| **[HTTP API](../api/index.md)** | Direct control, other languages, automation |

Expand Down
1 change: 1 addition & 0 deletions docs/src/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,6 @@ aenv start ubuntu # starts a sandbox and attaches an interactive shel

- [Deployment](../deployment/manual-compile.md) — build from source, multi-node options
- [Core Concepts](../concepts/overview.md) — how sandboxes, templates, and snapshots work
- [Crabbox](../integration/crabbox.md) — openclaw/crabbox client for sync + remote run
- [E2B](../integration/e2b.md) — SDK and CLI compatibility
- [API Reference](../api/index.md) — full HTTP API
Loading
Loading