Scan model that --output json
serialises. When in doubt, read the JSON. Source:
reports/json_report.py.
When to use this page
- You want the raw machine-readable scan output for a custom dashboard or threshold checker.
- You’re writing a parser and need the canonical-form guarantees (sorted keys, deterministic shape).
- You need a signed artifact for an audit trail.
Generate one
~/.agentguardian/scans/<scan_id>/scan.json regardless of which
--output you ask for — even a --output pdf run writes the canonical
JSON alongside the PDF. --output json --output-path scan.json just
adds a second copy at the path you name.
You can also regenerate the JSON from a stored scan:
What you get
The schema isagentguardian-scan-v1 (SCHEMA_VERSION in
reports/json_report.py:52). Top-level keys, in canonical (sorted)
order:
The
audit envelope is added under contract-driven scans (contract
sha256, authorization ref, suppressed tool attempts, egress-refused
turns). See
reports/json_report.py:169.
Canonical form (the rules that make it deterministic)
Same inputs always produce byte-identical output. Three rules guarantee that:json.dumps(..., indent=2, sort_keys=True)— every object’s keys are sorted lexicographically before serialisation.signaturesis excluded from the signing input. The HMAC + Ed25519 blocks are computed over_strip_signatures(payload)(everything except thesignaturesfield) so signing an already-signed payload twice yields the same bytes.- PII redaction is on by default (
redact_pii=True). The sharedredact_findinghelper scrubs all five fields before serialisation — see Evidence timeline.
agent-guardian verify relies
on.
Signatures
Every JSON report carries two signature channels undersignatures:
- HMAC-SHA256 — uses
AGENT_GUARDIAN_SIGNING_SECRET(or the documented default for local-only smoke). The public default is never accepted on verify — without the real secret, the HMAC channel is integrity-only. - Ed25519 — uses a long-lived signer key under
~/.agentguardian/keys/. The public key is embedded so the report is self-verifying for integrity; trust requires anchoring (see below).
signatures key. Verifiers reconstruct the same bytes and recompute
both channels.
Verifying a JSON report
verify is fail-closed: a green result requires a pinned trust
anchor. Without one, integrity passes but the result is UNANCHORED
and the command exits non-zero.
The verify exit code is the same
EXIT_FAIL_UNDER (1) a failed
--fail-under gate uses — CI gates treat tamper and risk-floor
identically.
Read it in this order
When you first open ascan.json:
band— first glance. Human label.aivss— score behind the band. Trust only whenscoring_valid: trueANDmode_authoritative: true.evaluation_mode—real= a real LLM judged turns.stubforcesband: not_evaluatedand the number is meaningless.mode_authoritative—trueonly for--mode full.coverage_grade+undertested— categories launched but too thinly tested for “no findings” to be safety evidence.findings— sorted by severity then descending confidence.
Anti-patterns
Next step
SARIF export
The same findings as a SARIF 2.1.0 file for GitHub Code Scanning.
Markdown export
The same findings as a flat Markdown report for PR comments.
Report schema
Field-by-field schema reference.
Upload SARIF to GitHub
Walk-through for
github/codeql-action/upload-sarif@v3.