First Edge

An end-to-end walkthrough using the AutonomyOps ADK demo stack. You will:

  1. Start the demo stack

  2. Push a test OCI artifact

  3. Build and attach a policy bundle and lock file

  4. Sign and verify through the four-step pipeline

  5. Load the bundle into the runtime

  6. Submit tool calls and observe allow/deny enforcement

  7. Drain telemetry and query events from the control plane

Estimated time: 20–30 minutes.

Prerequisites

  • Build completed — bin/autonomy built

  • Run 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: 403tool.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.echo allowed, tool.shell denied

  • Drained WAL telemetry and queried ai.policy.decision events from the control plane

Evidence

  • demo/docker-compose.yml

  • demo/scripts/01_build.sh

  • demo/scripts/02_push_attach_sign.sh

  • demo/scripts/03_verify_and_run.sh

  • demo/scripts/04_offline_then_drain.sh

  • demo/scripts/05_failure_drills.sh

  • runtime/server.go, runtime/interceptor.go

  • docs/_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