Safe autonomy for destructive cloud actions. Airlock is an agent that finds wasteful cloud resources and cleans them up, but the point is not the cleanup. The point is the gate: every destructive action passes through a human approval the agent structurally cannot bypass or re-target.
Approval buttons in most agent workflows are theater. The agent proposes "delete resource X," a human clicks approve, and nothing binds that approval to X. The agent can then execute a different action, or hit a different target, and the click still counts. Airlock closes that gap: an approval is an Ed25519 signature over the exact action, single-use and time-limited. Change any field and the signature no longer matches, so the write is refused.
Today Airlock targets Alibaba Cloud (ECS + RDS). The gate itself is provider-agnostic; see CONTRIBUTING.md for adding a provider.
The approval kernel enforces the core property: an approved action executes, a replay is refused, and a swapped target is refused. These behaviors are covered end to end by the test and conformance suites, so you can verify the guarantee without a cloud account.
uv sync --dev
uv run pytest # unit, integration, and property testsConformance vectors for the shared canonicalizer (signer and verifier) live in eval/.
bash infra/scripts/gen-keys.shgenerates the Ed25519 keypair into.airlock/.bash infra/scripts/setup-ram.shcreates two RAM users: a read-only one and a write-only one. This separation is the enforcement boundary.- Copy
.env.exampleto.envand fill it in; put the RAM creds in.airlock/read.envand.airlock/write.env. docker compose up --buildbrings up the checkpoint, the read-only agent, the write-only executor, the two credentialed MCP servers, and the web approval app.
Review and approve proposals at http://localhost:3000.
Four components, each with the least capability it needs. Run them as separate processes or containers so the split is a deployment boundary, not just a convention. See docs/architecture.md for the full diagram and trust boundaries.
Component (airlock ...) |
Capability | Role |
|---|---|---|
agent |
read-only cloud | Discovers idle instances, applies the idle policy, submits a proposal. Never writes. |
checkpoint |
signing key | Hashes the proposal (RFC 8785 JCS) and issues an Ed25519 approval bound to that hash. The only signer. |
executor |
write cloud | Re-verifies the approval, re-reads live state, rebuilds args from trusted fields, writes once. The only writer. |
| web app | operator token | The human review surface; type-to-confirm on high-risk actions. |
- Reads and metrics go through a self-hosted
alibaba-cloud-ops-mcp-serverunder the read RAM credential:CommonAPICallerfor instance discovery andCMS_GetMetricListfor a windowed CPU/mem/disk time series (a small vendored tool; seeinfra/mcp/). - Writes go through a second MCP server under the write RAM credential, exposing only
ECS_StopInstances,ECS_DeleteInstances,RDS_StopDBInstance. - Planning is deterministic by default: the idle policy makes the judgment and the
planner just formats the canonical action (no API key, cannot hallucinate a target). An
optional Qwen arbiter (
QwenPlanner, DashScope chat-completions) can be layered on.
- The agent submits a
ProposedAction({account, region, resource_id, action, precondition, evidence, ...}). - The checkpoint canonicalizes it (JCS), hashes it, and on operator approval signs an envelope binding the hash, account, audience, key id, a nonce, and an expiry.
- The executor, before any write: verifies the signature, re-hashes the presented action and compares, checks account/audience/key/expiry, atomically consumes the approval (single use), re-reads live state against the precondition, and only then calls the write MCP tool with arguments reconstructed from trusted fields.
The signer and verifier share one canonicalizer; conformance vectors live in eval/.
airlock checkpoint [--host --port] serve the approval checkpoint
airlock agent [--loop] one read-only discovery + proposal pass
airlock executor [--once] the write-only executor daemon
airlock approvals list|approve|reject operator surface
All settings are environment variables read in one place (src/common/env.py); see
.env.example. CLOUD_REGION is a single knob (defaults to ap-southeast-1); if you change
it, update the RAM policy ARNs in infra/ram/ to match.
Airlock is early and honest about its edges. The approval kernel is well-tested (tests/ and
eval/); the surrounding product is maturing. Notable current limits: Alibaba Cloud only;
operator auth is a single shared bearer (no per-user auth yet); the signing key is a local
file by default (use a KMS in production); the approval store is SQLite. Read
SECURITY.md before trusting it with a real account.
See CONTRIBUTING.md. The one rule that never bends: the planner never holds a write capability or the signing key, and the executor never holds the private key.
MIT. See LICENSE.