What this gives you
A PR check that fails when the AgentGuardian AIVSS score drops below your floor (or any per-severity ceiling is exceeded), with every finding annotated inline in GitHub’s Security tab via the officialgithub/codeql-action/upload-sarif@v3 action, and a sticky summary comment posted on the PR.
When to add this
- The first time an LLM agent lands in
mainand needs a regression gate. - On every release branch, before tagging.
- Before any change that touches the agent’s system prompt, tool surface, or memory layer.
Wire it up
Drop in the workflow
Create Prefer the longhand
.github/workflows/agent-guardian.yml with the YAML below. Three
permissions are required: security-events: write for
github/codeql-action/upload-sarif@v3 (Code Scanning annotations),
pull-requests: write for the sticky AgentGuardian comment, and
contents: read for checkout..github/workflows/agent-guardian.yml
agent-guardian scan / upload-sarif steps? See the
composite action page
for when to hand-roll the steps. Ready-to-copy preset workflows
(minimal / standard / thorough) ship under
examples/ci/github/.Pick a target
Replace
my_app.graph:graph with the dotted reference to your real
framework-native object. Supported --framework values: adk,
autogen, crewai, langgraph, openai_agents, strands.For a hosted HTTP agent, swap the framework flags for
--endpoint https://my-agent.example.com/chat and set
AGENT_GUARDIAN_AUTH_BEARER from a repo secret.Add the provider secret
Repo Settings → Secrets and variables → Actions → New repository
secret. Add the key matching your
--model choice:
GEMINI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, or use
--model stub for an offline smoke check (note: stub runs are
non-authoritative — they always fail --fail-under, see below).The full flow
Expected output on a PR
A passing run prints the scan summary to the job log and exits0:
1:
if: always()),
so every finding shows up in the PR’s Files changed → Annotations lane
and under Security → Code scanning alerts.
How to interpret the exit code
The CLI uses six exit codes, defined verbatim incli.py:83–89.
The gate condition you wire into the workflow should care about exactly
two of them — 0 (pass) and 1 (gate failed). The rest are signals that
something else went wrong and the scan never produced a verdict.
| Exit code | Constant | Meaning | What to do in CI |
|---|---|---|---|
0 | EXIT_OK | Scan completed and AIVSS ≥ --fail-under. | Merge. |
1 | EXIT_FAIL_UNDER | Scan completed and AIVSS < --fail-under, or the scan was non-authoritative (--mode fast/smart, or --model stub). | Block merge. Read the SARIF annotations to triage. |
2 | EXIT_CONFIG | Bad invocation — unknown flag, conflicting target modes, malformed --contract. | Fix the workflow YAML. Not a security regression. |
3 | EXIT_TARGET_UNREACHABLE | The pre-scan reachability probe for --endpoint mode failed. | Check that the agent is up before the scan step (e.g. add a curl --retry health check). |
4 | EXIT_LLM_PROVIDER | The LLM provider returned an unrecoverable error (rate limit, auth, network). | Re-run the workflow. Check the provider secret. |
5 | EXIT_SANDBOX | The sandboxed code adapter refused to load the target. | Inspect the job log; fix the target reference. |
130 | EXIT_USER_INTERRUPT | The runner cancelled the job (timeout, manual cancel). | Re-run; consider raising --budget-usd if the scan is timing out. |
Tuning the floor
Start permissive on the first PR (--fail-under 60) and tighten as you
land mitigations. A reasonable progression:
- First two weeks —
--fail-under 60. Catches catastrophic regressions only; lets the team see what a real swarm finds without blocking every merge. - Steady state —
--fail-under 70. Matches thelow_riskband boundary; rejects merges that introduce a medium-severity ASI01/ASI02 finding. - Hardened release branch —
--fail-under 80. Matches thesafe/low_riskboundary; only ships when the agent has no high-severity open findings.
src/agent_guardian/models/severity.py
(function band_for_score).
Per-severity gates
The AIVSS floor is a single aggregate number — a scan can clearfail-under
while still introducing one nasty CRITICAL finding. The max-* inputs add
per-severity ceilings that are AND-combined with fail-under: the gate
fails if AIVSS drops below the floor or any severity count exceeds its
ceiling.
max-critical to "0", so an out-of-the-box
workflow blocks any merge that introduces a CRITICAL finding. Set any ceiling
to an empty string ("") to disable just that one. See
fail builds on critical findings
for the full matrix.
The sticky PR comment
Withcomment: "true" (the default) on a pull_request event, the action
upserts a single AgentGuardian summary comment on the PR after the scan. It is
keyed by a hidden HTML marker (<!-- agentguardian-pr-marker:scan -->) on the
first line, so every re-run edits the same comment in place instead of piling
up a new one per push. The embedded verdict uses the same fail-under /
max-* thresholds as the gate, so the comment’s PASSED/FAILED always matches
the check’s exit code.
A rendered comment body looks like this:
GITHUB_TOKEN lacks write scope) it logs a warning and the job
continues; it never changes the scan’s pass/fail outcome. Full detail and the
marker contract live on the PR comments page.
Fork PRs without secrets
GitHub does not expose repository secrets to workflows triggered by a PR from a fork. The preset workflows handle this with a model fallback:GEMINI_API_KEY is empty (a fork), the scan runs with --model stub — an
offline, non-authoritative smoke check that always fails fail-under by
design. The fork PR check stays red and the SARIF/comment still appear; a
maintainer re-runs the scan from a trusted branch (with the real provider key)
to produce an authoritative verdict before merge.
Next step
Reports
Open the
scan.sarif and the signed scan.json produced by every run.Upload SARIF
Walk-through for
github/codeql-action/upload-sarif@v3 and the
permissions block.Attack library
See the probes across 10 ASI categories the gate is exercising.
Fail builds on high risk
Add a finding gate on top of the score gate.
PR comments
The sticky summary comment, its marker contract, and a rendered sample.