Tutorial: CI headless governance flow
Documented for Akmon 2.2.0.
Time estimate: 25-35 minutes
Complexity: Intermediate
Who this is for
Platform and release teams running Akmon non-interactively in CI who want the pipeline to fail unless a session produced a signed, independently verifiable evidence bundle. The own-agent audit, evidence, and SLO checks still run, but here they feed a single artifact a reviewer or auditor can verify offline.
What you will have at the end
- A reproducible headless run command with a budget cap.
- Own-agent integrity gates (
audit,evidence,verify) and SLO and trend gates. - A signed
.akmonbundle, exported from the session and verified in CI withakmon bundle verify --verify-key --require-signature, so the gate that matters is provenance, not just that the agent ran.
Prerequisites
- CI runner has
akmoninstalled. - Runner has provider credentials (for example
ANTHROPIC_API_KEY) or a local model setup. - Repository has write access to
.akmon/output paths. - A signing key is available to CI as a secret. Generate it once with
akmon bundle keygen --out signer.pk8 --public-out signer.pub.hex, keepsigner.pk8secret (inject it from your CI secret store at runtime), and commit or publish onlysigner.pub.hex.
Steps
- Execute a headless run with JSON output and a budget cap.
akmon --yes --output json \
--max-budget-usd 2.00 \
--task "run cargo test and summarize failures" \
| tee run.json
- Extract the session ID and run the own-agent integrity checks.
SESSION_ID="$(jq -r '.session_id' run.json)"
akmon audit verify ".akmon/audit/${SESSION_ID}.jsonl"
akmon evidence verify ".akmon/evidence/${SESSION_ID}.json"
akmon verify "${SESSION_ID}"
- Enforce per-run SLO thresholds and the trend gate.
akmon slo verify ".akmon/evidence/${SESSION_ID}.json" \
--thresholds .github/akmon/slo.toml \
--strict
akmon slo trend ".akmon/evidence/${SESSION_ID}.json" \
--baseline-dir .akmon/evidence/history \
--window 20 \
--strict
- Export the session as a bundle and sign it offline.
akmon bundle export "${SESSION_ID}" --output "session.akmon"
akmon bundle sign "session.akmon" --key signer.pk8
- The governance gate: require a present, valid signature against the published public key.
akmon bundle verify "session.akmon" \
--verify-key signer.pub.hex \
--require-signature \
--require-capture full
akmon bundle verify exits 0 only when the bundle's objects, event chain, and manifest head are internally consistent and the head signature verifies against signer.pub.hex. With --require-signature, a missing or stripped signature is a hard failure (exit 1) rather than a quiet pass. A reference-agent run is full capture, so --require-capture full passes here; it would correctly fail on a structural OTEL import. Exit 3 indicates an I/O or environment error. This is the gate that proves a verifiable record exists, not merely that the agent finished.
- Wire the same sequence into CI. The bundle verification step is the one that blocks the merge.
- name: Run Akmon headless
run: akmon --yes --output json --max-budget-usd 2.00 --task "run tests and summarize failures" | tee run.json
- name: Extract session ID
run: echo "SESSION_ID=$(jq -r '.session_id' run.json)" >> $GITHUB_ENV
- name: Verify audit, evidence, and session integrity
run: |
akmon audit verify ".akmon/audit/${SESSION_ID}.jsonl"
akmon evidence verify ".akmon/evidence/${SESSION_ID}.json"
akmon verify "${SESSION_ID}"
- name: Enforce SLO and trend guardrails
run: |
akmon slo verify ".akmon/evidence/${SESSION_ID}.json" --strict
akmon slo trend ".akmon/evidence/${SESSION_ID}.json" --baseline-dir .akmon/evidence/history --window 20 --strict
- name: Export and sign the evidence bundle
run: |
printf '%s' "${AKMON_SIGNING_KEY_B64}" | base64 -d > signer.pk8
akmon bundle export "${SESSION_ID}" --output session.akmon
akmon bundle sign session.akmon --key signer.pk8
rm -f signer.pk8
- name: Gate on a signed, verified bundle
run: akmon bundle verify session.akmon --verify-key signer.pub.hex --require-signature --require-capture full
- name: Upload the signed evidence bundle
uses: actions/upload-artifact@v4
with:
name: akmon-evidence
path: session.akmon
AKMON_SIGNING_KEY_B64 is the base64 of signer.pk8, stored as a CI secret. The private key is written only for the signing step and removed immediately.
What gets recorded in evidence
- Reliability metrics used by
slo verifyandslo trend. - Replay metadata hashes, including the policy and tool-registry hashes, for deterministic validation context.
- Provider resolution and session-level run status.
The same content is what the exported bundle commits to and the head signature seals, so the artifact CI uploads is exactly what a reviewer verifies later.
How a reviewer validates this
- Confirm all own-agent integrity commands exit
0. - Confirm
akmon bundle verify session.akmon --verify-key signer.pub.hex --require-signatureexits0with averifiedsignature outcome. - Confirm
--require-capture fullpasses for the reference-agent run. - Confirm CI artifacts include the signed
session.akmonandrun.jsonfor retained runs.
A reviewer who does not run Akmon can verify the uploaded bundle with the standalone agef-verify or with plain openssl; see Verify evidence on an air-gapped machine.
Verification
jq '{session_id,status,reliability_metrics}' run.json
Expected result: non-empty session_id, an explicit status, and a reliability metrics object.
Troubleshooting
- If CI fails before Akmon starts, verify provider credentials in the runner environment.
- If
akmon bundle signrejects the key, regenerate it withakmon bundle keygen;openssl genpkeyemits PKCS#8 v1, which the signing path rejects. - If
bundle verify --require-signaturefails, the signature is missing, stripped, or does not matchsigner.pub.hex. Confirm the signing step ran and the public key matches the private key in CI. - If
slo verifyfails, inspect the threshold file and theviolationsoutput. - If policy denials block the run, inspect
policy_denials_totalin metrics and reconcile with the configured profile and packs. - Failure behavior is intentional: non-zero exits from
audit,evidence,verify,slo, andbundle verifyshould fail pipeline gates.