First Edge¶
An end-to-end walkthrough using the AutonomyOps ADK demo stack. You will:
Start the demo stack
Push a test OCI artifact
Build and attach a policy bundle and lock file
Sign and verify through the four-step pipeline
Load the bundle into the runtime
Submit tool calls and observe allow/deny enforcement
Drain telemetry and query events from the control plane
Estimated time: 20–30 minutes.
Prerequisites¶
Build completed —
bin/autonomybuiltRun prerequisites met (Docker Compose V2, cosign)
Demo keys available at
demo/keys/cosign.{key,pub}(pre-committed, no passphrase)
Installed: the install script puts autonomy on PATH (no build step
needed) and the bundle at ~/.autonomyops/quickstart/ ships
demo/policies/, demo/locks/example.lock.json, demo/agent_py/, and
demo/keys/generate.sh at the same relative paths. cd ~/.autonomyops/quickstart
once at the start of this walkthrough; every demo/... argument
below resolves identically to the in-repo case. Generate the demo
keypair locally with bash demo/keys/generate.sh (the bundle ships
only the generator, never the private key).
Private GHCR Access (Beta)¶
During Stage 1 beta, AutonomyOps images are private in GHCR under ghcr.io/autonomyops/*.
Your GitHub user must be granted package access in the AutonomyOps org.
Authenticate with one of the following:
PAT (read:packages):
echo "$TOKEN" | docker login ghcr.io -u "$USER" --password-stdin
GitHub App installation token:
echo "$TOKEN" | docker login ghcr.io -u x-access-token --password-stdin
If pulls fail with 403 or denied, package access has not been granted yet.
Add the binary to PATH for this walkthrough:
export PATH="$PWD/bin:$PATH"
Step 1 — Start the Demo Stack¶
In-repo:
make demo-up-build
Installed:
bash demo/scripts/demo_up.sh
(make demo-up-build rebuilds local images first; demo_up.sh skips
the rebuild because the bundle pins prebuilt GHCR images.)
Wait for all services to be running:
In-repo:
make demo-preflight
Installed:
bash demo/scripts/preflight.sh
Step 2 — Push a Test OCI Artifact¶
autonomy oci push-test-artifact --image localhost:5000/agent:v1
Expected:
==> pushed test subject: localhost:5000/agent:v1
Step 3 — Build and Attach a Policy Bundle¶
autonomy policy build \
--in demo/policies \
--out bundle.tar.gz \
--version 1.0.0 \
--name demo
Installed: identical command (the bundle ships demo/policies/ at
the same relative path).
Expected: ==> bundle written: bundle.tar.gz
Attach it to the image as an OCI sidecar:
autonomy oci attach-policy \
--image localhost:5000/agent:v1 \
--bundle bundle.tar.gz
Step 4 — Attach a Lock File¶
The lock file captures the behavioral fingerprint of the agent image:
autonomy oci attach-lock \
--image localhost:5000/agent:v1 \
--lock demo/locks/example.lock.json
Installed: identical command (the bundle ships
demo/locks/example.lock.json at the same relative path).
Step 5 — Sign the Artifact¶
autonomy sign \
--image localhost:5000/agent:v1 \
--key demo/keys/cosign.key \
--lock demo/locks/example.lock.json
Installed: identical command, AFTER you have run
bash demo/keys/generate.sh (the bundle ships only the generator).
When prompted for the cosign key password, press Enter (demo keys have no passphrase).
Step 6 — Verify the Artifact¶
autonomy verify \
--image localhost:5000/agent:v1 \
--pub-key demo/keys/cosign.pub \
--lock demo/locks/example.lock.json
Installed: identical command (uses the cosign.pub produced by
bash demo/keys/generate.sh in Step 5’s prereq).
All four verification steps must pass:
[verify] Step 1: cosign signature — PASS
[verify] Step 2: agent digest match — PASS
[verify] Step 3: fingerprint match — PASS
[verify] Step 4: policy semver compat — PASS
!!! info “What the four steps verify”
- Step 1 — cosign signature on the image matches the public key
- Step 2 — the agent artifact digest in the lock matches the OCI manifest digest
- Step 3 — the behavioral_fingerprint in the lock (BLAKE3) matches recomputed fingerprint
- Step 4 — the policy bundle version satisfies the semver constraint in the lock
Step 7 — Load the Policy Bundle into the Runtime¶
autonomy policy load --bundle bundle.tar.gz
Verify:
autonomy policy status
Expected: current: demo@1.0.0 lkg: none
Step 8 — Submit an Allowed Tool Call¶
With the runtime running (In-repo: make demo-up;
Installed: bash demo/scripts/demo_up.sh), submit a tool call:
curl -s http://localhost:7777/v1/tool \
-H 'Content-Type: application/json' \
-d '{"kind":"tool.echo","params":{"message":"hello from first-edge"}}' \
| python3 -m json.tool
Expected (allowed):
{
"decision": "allow",
"output": "hello from first-edge",
"policy_ref": "demo@1.0.0"
}
Step 9 — Submit a Denied Tool Call¶
curl -s -o /dev/null -w '%{http_code}' \
http://localhost:7777/v1/tool \
-H 'Content-Type: application/json' \
-d '{"kind":"tool.shell","params":{"command":"id"}}'
Expected: 403 — tool.shell is blocked by the demo policy bundle
(demo/policies/shell_deny.rego; same path in both audiences — the
bundle ships demo/policies/ identically).
Installed: identical 403 response from the same tool call.
!!! danger “Deny cannot be overridden”
No adapter code path can flip Deny to Allow. This invariant is enforced by the
runtime and tested in TestInterceptorDenyCannotBeOverridden.
Step 10 — Drain Telemetry and Query Events¶
In-repo:
make demo-offline-drain
Installed:
bash demo/scripts/04_offline_then_drain.sh
This drains the runtime WAL to the OTel collector, which forwards events to the control plane via the otel-sink bridge.
Query the ingested events:
curl -s 'http://localhost:8888/v1/events?limit=10' | python3 -m json.tool
You should see ai.policy.decision events for both the allow and deny calls above.
To view traces in Jaeger: http://localhost:16686
Step 11 — Tear Down¶
In-repo:
make demo-down
Installed:
docker compose -f demo/docker-compose.yml down
What You Accomplished¶
Built and attached an OCI policy bundle and lock file as content-addressed sidecar artifacts
Signed the artifact with cosign and verified all four pipeline steps
Observed the runtime enforcing policy:
tool.echoallowed,tool.shelldeniedDrained WAL telemetry and queried
ai.policy.decisionevents from the control plane
Evidence¶
demo/docker-compose.ymldemo/scripts/01_build.shdemo/scripts/02_push_attach_sign.shdemo/scripts/03_verify_and_run.shdemo/scripts/04_offline_then_drain.shdemo/scripts/05_failure_drills.shruntime/server.go,runtime/interceptor.godocs/_generated/test-outputs/demo-output.txt
Failure Drills¶
For scenarios that test what happens when things go wrong — tampered digests, revoked certificates, offline collectors — see the Demo Runbook.
Do Not Do¶
❌ Do NOT use the demo cosign keys (
demo/keys/cosign.{key,pub}) in production❌ Do NOT skip Step 6 (verification) before loading a bundle — an unverified bundle may not match the signed lock
Installed: the same warning applies to keys generated by
bash demo/keys/generate.sh from the bundle — they have an empty
passphrase and are demo-only.
See Also¶
Run — how to start and operate the demo stack
Demo Runbook — detailed failure drills and expected outputs