Blueprint-SDK-native Rust implementation for orchestrating OpenClaw instances on the Tangle network.
This is a blueprint-sdk blueprint — a Rust workspace that compiles to a
Tangle-compatible binary. The runner listens for on-chain JobSubmitted events,
executes the matching handler, and submits results back to the chain.
Cargo.toml # workspace root
openclaw-sandbox-blueprint-lib/ # library: sol! types, jobs, state, router
openclaw-sandbox-blueprint-bin/ # binary: runner entry point (main.rs)
openclaw-tee-sandbox-blueprint-lib/ # TEE variant library wrapper
openclaw-tee-sandbox-blueprint-bin/ # TEE variant runner binary
config/templates/ # template packs (SOUL/USER/TOOLS presets)
ui/ # React source UI (blueprint-ui + agent-ui)
control-plane-ui/ # embedded operator-served UI build artifacts
docs/ # architecture notes
| ID | Name | Description |
|---|---|---|
| 0 | create |
Provision a new OpenClaw instance |
| 1 | start |
Start a stopped instance |
| 2 | stop |
Stop a running instance |
| 3 | delete |
Mark an instance as deleted |
Instances support these built-in claw_variant values in config_json:
openclawnanoclawironclaw
Each instance record persists claw_variant plus ui_access metadata so
operators can route to the correct runtime profile without changing job ABI.
See docs/VARIANT-REFERENCE.md for verified source references and naming-collision notes.
Read-only operations are not on-chain jobs. They are served via the operator HTTP API:
GET /(serves the built-in control-plane UI shell)GET /assets/*(serves code-split UI chunks for the control-plane shell)GET /healthGET /templatesGET /instances(requires bearer auth)GET /instances/{id}(requires bearer auth)GET /instances/{id}/access(requires scoped bearer auth; returns per-instance UI bearer token)POST /instances/{id}/setup/start(requires scoped bearer auth)GET /instances/{id}/tee/public-key(requires scoped bearer auth; TEE-only instances)POST /instances/{id}/tee/sealed-secrets(requires scoped bearer auth; forwards encrypted secrets, TEE-only instances)GET /instances/{id}/tee/attestation(requires scoped bearer auth; fetches current TEE attestation, TEE-only instances)POST /instances/{id}/ssh(requires scoped bearer auth; provision SSH public key)DELETE /instances/{id}/ssh(requires scoped bearer auth; revoke SSH public key)POST /instances/{id}/terminals(requires scoped bearer auth; create terminal session)GET /instances/{id}/terminals/{terminalId}/stream(SSE terminal stream; bearer via header or?token=)POST /instances/{id}/terminals/{terminalId}/execute(requires scoped bearer auth)DELETE /instances/{id}/terminals/{terminalId}(requires scoped bearer auth)GET /instances/{id}/session/sessions(requires scoped bearer auth; list chat sessions)POST /instances/{id}/session/sessions(requires scoped bearer auth; create chat session)PATCH /instances/{id}/session/sessions/{sessionId}(requires scoped bearer auth; rename session)DELETE /instances/{id}/session/sessions/{sessionId}(requires scoped bearer auth)GET /instances/{id}/session/sessions/{sessionId}/messages(requires scoped bearer auth)POST /instances/{id}/session/sessions/{sessionId}/messages(requires scoped bearer auth)POST /instances/{id}/session/sessions/{sessionId}/abort(requires scoped bearer auth)GET /instances/{id}/session/events(SSE chat stream; querysessionId, bearer via header or?token=)
Session endpoints:
POST /auth/challenge(wallet-signature challenge)POST /auth/session/wallet(challenge verify -> bearer token)POST /auth/session/token(access-token auth -> bearer token)
Operator API runtime defaults:
- disabled unless
OPENCLAW_OPERATOR_HTTP_ENABLED=true(or1) - bind address defaults to
127.0.0.1:8787viaOPENCLAW_OPERATOR_HTTP_ADDR
Pre-configured SOUL/USER/TOOLS presets in config/templates/:
discord— community support and moderationtelegram— customer outreach and bot workflowsops— operational runbook and incident responsecustom— bring your own configuration
cargo check --all-features
cargo build --release
cd ui && pnpm install && pnpm run build:embedded && cd -cargo test --all
./scripts/ci/run-docker-integration-tests.sh
./scripts/ci/run-real-variant-runtime-tests.sh # real OpenClaw + IronClaw + NanoClaw (upstream build)./scripts/deploy-local.shKeplr note: Keplr requires https:// RPC URLs when adding/switching EVM chains.
For local chain 31338, run:
ENABLE_HTTPS_RPC_TUNNEL=1 ./scripts/deploy-local.shThis starts a Cloudflare quick tunnel (https://*.trycloudflare.com) that fronts
your local Anvil RPC and writes it into .env.local + ui/.env.local.
SERVICE_ID=<id> HTTP_RPC_ENDPOINT=<url> KEYSTORE_URI=<uri> \
cargo run --release --bin openclaw-sandbox-blueprintcreate_instance keeps ABI compatibility (name, template_pack_id,
config_json) and reads optional profile settings from config_json:
{
"claw_variant": "openclaw",
"ui": {
"expose_public_url": true,
"subdomain": "team-assistant",
"auth_mode": "wallet_signature"
}
}Supported values:
claw_variant:openclaw|nanoclaw|ironclawui.auth_mode:wallet_signature|access_tokenui.expose_public_url: defaults totrue- when
ui.auth_mode=access_token, session login uses operator-sideOPENCLAW_UI_ACCESS_TOKEN(notconfig_json)
Tunnel/public URL behavior:
- If
OPENCLAW_UI_BASE_DOMAINis set, URL is generated ashttps://<subdomain>.<OPENCLAW_UI_BASE_DOMAIN>and tunnel status isactive. - If unset, tunnel status is
pendingand URL remains unset until ingress is provisioned by runtime infrastructure. owner_onlydefaults totruefor secure-by-default routing.
Execution target behavior:
- Default execution target is
standard. - Set
OPENCLAW_EXECUTION_TARGET=teeto mark new instances as TEE-targeted. - The dedicated
openclaw-tee-sandbox-blueprintbinary sets this automatically.
This blueprint is a product layer over sandbox runtime contracts. It does not implement VM/Firecracker orchestration directly. It does implement a real Docker execution backend for lifecycle operations. The runtime adapter boundary is defined and wired in the lib crate:
InstanceRuntimeAdaptertrait = product/runtime integration contractLocalStateRuntimeAdapter= in-memory/file projection adapter used for testsDockerRuntimeAdapter= lifecycle execution through Docker CLI (create/start/stop/rm)
Job handlers call the adapter, not storage internals directly. A future sandbox-runtime-backed adapter (for microVM/Firecracker) can be injected without rewriting job handlers.
Enable Docker-backed lifecycle execution:
export OPENCLAW_RUNTIME_BACKEND=docker
export OPENCLAW_IMAGE_OPENCLAW=ghcr.io/<org>/<openclaw-image>:<tag>
export OPENCLAW_IMAGE_IRONCLAW=ghcr.io/<org>/<ironclaw-image>:<tag>
export OPENCLAW_DOCKER_PULL=true # optional, default trueNanoClaw image options:
- prebuilt image:
OPENCLAW_IMAGE_NANOCLAW=<image:tag>
- or build on demand during adapter init:
OPENCLAW_NANOCLAW_BUILD_CONTEXT=/path/to/nanoclaw- optional
OPENCLAW_NANOCLAW_BUILD_SCRIPT=container/build.sh - optional
OPENCLAW_NANOCLAW_BUILD_IMAGE_NAME=nanoclaw-agent - optional
OPENCLAW_NANOCLAW_BUILD_TAG=latest
Behavior:
createcreates a container from the variant-mapped image.- UI port mapping defaults:
- OpenClaw:
18789 - IronClaw:
18789 - NanoClaw: none by default (terminal-first profile), or explicit env override
- OpenClaw:
- per-variant UI port override:
OPENCLAW_VARIANT_<OPENCLAW|NANOCLAW|IRONCLAW>_UI_PORT - per-variant startup command override (runs as
sh -lc <command>):OPENCLAW_VARIANT_<OPENCLAW|NANOCLAW|IRONCLAW>_CONTAINER_COMMAND
- per-variant shell entrypoint override (when image has restrictive
ENTRYPOINT):OPENCLAW_VARIANT_<OPENCLAW|NANOCLAW|IRONCLAW>_FORCE_SHELL_ENTRYPOINT
- per-variant host env passthrough allowlist (comma-separated):
OPENCLAW_VARIANT_<OPENCLAW|NANOCLAW|IRONCLAW>_CONTAINER_ENV_KEYS- values are read from the runner host env and injected as container env
- startup stabilization check:
OPENCLAW_DOCKER_STARTUP_STABILIZE_MS(default1000)- if container exits immediately after
start, lifecycle now fails fast with recent logs
startrunsdocker start.stoprunsdocker stop.deleterunsdocker rm -f.- query surfaces include runtime metadata (
backend, image, container status, local UI URL, setup status, last error). - canonical UI auth env is unified across variants:
SANDBOX_UI_BEARER_TOKEN(SANDBOX_UI_AUTH_MODE=bearer). - per-instance token retrieval for owner-scoped sessions:
GET /instances/{id}/access. - canonical env naming + token generation come from
sandbox-runtime::ingress_access_control(re-exported byopenclaw-sandbox-blueprint-lib). - compatibility aliases are still injected for existing images (
CLAW_UI_BEARER_TOKEN,OPENCLAW_GATEWAY_TOKEN,NANOCLAW_UI_BEARER_TOKEN,GATEWAY_AUTH_TOKEN). - setup bootstrap can be triggered with
POST /instances/{id}/setup/start(scoped session required). - default setup commands:
- OpenClaw:
openclaw onboard - NanoClaw: no default setup command (owner drives setup via terminal/chat flow)
- IronClaw:
ironclaw onboard
- OpenClaw:
- command override per variant:
OPENCLAW_VARIANT_<...>_SETUP_COMMAND - setup env allowlist per variant:
OPENCLAW_VARIANT_<...>_SETUP_ENV_KEYS(comma-separated) - optional chat command per variant:
OPENCLAW_VARIANT_<OPENCLAW|NANOCLAW|IRONCLAW>_CHAT_COMMAND- command runs inside the container and receives prompt through env var
OPENCLAW_CHAT_PROMPT
This repository does not publish or bundle the variant images. You must provide valid image references for your environment.
Real-image runtime notes:
- official OpenClaw image (
ghcr.io/openclaw/openclaw) is loopback-bound by default. The runtime applies a host-reachable startup command automatically for this image. - official IronClaw worker image requires non-interactive auth env to avoid startup prompts.
Provide
NEARAI_API_KEYorNEARAI_SESSION_TOKENin the runner host env. - NanoClaw upstream
container/build.shimage is a one-shot agent-runner image. The runtime defaultsnanoclaw-agent:*to a long-lived terminal-first profile (tail -f /dev/nullwith shell entrypoint override) so owners can complete canonical setup (claudethen/setup) through scoped terminal/chat surfaces. You can override this viaOPENCLAW_VARIANT_NANOCLAW_CONTAINER_COMMAND.
Agent UI compatibility:
@tangle-network/agent-uiterminal/session hooks are compatible when usingapiUrl=http://<operator>/instances/<instance-id>with scoped session bearer token.
- Containers are bound to loopback only (
127.0.0.1port mapping), not exposed directly on public interfaces. - Each Docker instance receives a unique bearer token under canonical env key
SANDBOX_UI_BEARER_TOKEN. - Operator API setup execution is restricted to instance-scoped sessions (owner flow), not operator-wide tokens.
- UI token retrieval is restricted to instance-scoped sessions (owner flow), not operator-wide tokens.
- Setup env keys are validated and only injected for the setup execution call; they are not persisted in instance state.
- UI ingress should still be fronted by authenticated tunnel/reverse proxy before internet exposure.
Instance state persists at:
$OPENCLAW_INSTANCE_STATE_DIR/instances.json(preferred)- fallback:
$OPENCLAW_STATE_DIR/instances.json(compatibility path) - default:
/tmp/openclaw-sandbox-blueprint/instances.json
Run the dedicated TEE variant binary:
SERVICE_ID=<id> HTTP_RPC_ENDPOINT=<url> KEYSTORE_URI=<uri> \
cargo run --release --bin openclaw-tee-sandbox-blueprint- State-changing operations are jobs only (
create,start,stop,delete). - Read-only operations stay in query surfaces (operator HTTP API).
- Ship in small, composable PRs with explicit validation evidence.
- CI runs Rust checks plus synthetic Docker integration tests in
.github/workflows/ci.yml. - Use
scripts/ci/run-real-variant-runtime-tests.shbefore releases to verify official OpenClaw/IronClaw runtime images plus NanoClaw upstream build path.
See CONTRIBUTING.md for branch, commit, and PR standards. See docs/ARCHITECTURE.md for detailed architecture notes.
