agent-guardian command surface. Every flag listed here is
sourced from src/agent_guardian/cli.py (Typer decorators) — no documented
flag is invented.
Global flags
.env / .env.local from the current working
directory (project-local, never $HOME or ancestors) when python-dotenv
is installed. Existing shell exports always win over .env values.
Commands
The top-level command set:CI integrations (
comment, code-insights) and benchmark/maintainer tools
(agentdojo, suite, calibrate) are still installed and callable — they
are driven by the composite Action / GitLab template or gated behind extras,
so they are kept off the default --help to foreground the core workflow.suite runs many independent scans in parallel from one YAML file and
aggregates a cross-scan summary. See
Parallel suites & bulk scanning for the full guide
and examples/suite.yaml for a commented reference file.version
Print the installed agent-guardian version and exit.
doctor
Verify install, available LLM keys, and runtime prerequisites.
doctor --check-connectivity before a paid scan to confirm your keys
actually authenticate against each provider’s API.
gate
Apply pass/fail thresholds to a stored scan, decoupled from scan — re-gate
a completed scan without re-running it. The same gate comment uses.
report output format:
last-score
Print the AIVSS of the most recent scan (read from ~/.agentguardian/state.json).
serve
Start the local dashboard at http://<host>:<port>.
--token or
--insecure-no-auth is refused with EXIT_CONFIG (2) so a misconfigured
deploy can’t silently expose findings.
report
Regenerate a report from a stored scan.
json / sarif / junit / md / gitlab) print to stdout by
default, or to --output-path when given. PDF is binary and always
requires --output-path.
verify
Verify HMAC-SHA256 + Ed25519 signatures on a JSON report.
UNANCHORED and the command exits non-zero
(EXIT_FAIL_UNDER, 1).
config
Inspect and scaffold the AgentGuardian config file. Distinct from the
scan --config flag (which points a single run at an explicit file).
scan
Run an adversarial swarm scan against a target. The big one — every flag
is documented below.
Target selection (exactly one required)
--framework KIND accepts: adk, autogen, crewai, langgraph,
openai_agents, strands.
LLM model wiring
Model specs:
stub, openai:gpt-4o, anthropic:claude-haiku-4-5,
gemini:gemini-2.5-flash, ollama:llama3.1,
bedrock:us.anthropic.claude-haiku-4-5-20251001-v1:0.
Scan shape
Budget + gating
Output + reports
Scan plan panel (QA-011)
Before the first LLM call, AgentGuardian prints a one-screen “scan plan” panel summarising everything it just verified: target reachability, per-role model validation, budget caps, output engine availability, dashboard server status, and the safety guards in play. This catches the failure modes that used to surface only after 6 minutes of LLM spend — missing PDF engine, unreachable target, dashboard server down, model id typo.
What you’ll see on an interactive scan:
WARNINGS footer with one line per ✗. The
5-second timer keeps interactive use frictionless; scripted use opts
out via --yes or one of the implicit skips:
--yes/-y(CLI)--no-plan(CLI; suppresses the panel itself)$AGENT_GUARDIAN_NO_PLAN_CONFIRM=1(env)$CI=true(env)- stdout is not a TTY (e.g.
agent-guardian scan ... | cat) - stdin is not a TTY
Phase composition (QA-012)
Once the scan starts, the Rich Live region renders three phase-locked panels composed inside a singlerich.console.Group so the QA-002
“one Live region per scan” invariant holds — there is one Live frame,
three panel sections, and Rich repaints them in place each tick.
findings_count > 0 projects rows into the severity-grouped list
(CRITICAL → HIGH → MEDIUM → LOW → INFO). The --debug attack feed
(QA-005) flows ABOVE the Live frame as scrollback, so panel borders
never tear.
Network + reachability
Observability
Debug stream
Dashboard URL emission + auto-serve
Minimal example
grep for them. When stdout is a TTY, the URLs are wrapped in
an OSC 8 hyperlink escape so Warp / iTerm2 / Terminal.app / VS Code
render them cmd-clickable.
Commander invocation gate
The SwarmCommander LLM (which decomposes a high-level goal into per-agent briefs with custompriority_weight + n_scenarios_requested allocations)
only runs when the scan has a goal anchor. There are three ways to
supply one:
--goal "..."on the CLI.--operator-profile path/to/profile.yaml(the profile’sdescriptionbecomes the goal).- An inferred goal from recon — the recon agent reads the target’s declared intent + tools and writes one when confident.
priority_weight=0.5 and the default
n_scenarios_requested for its ASI category. This is correct (you can’t
plan adaptively without a goal anchor), but it’s a quieter failure than
operators sometimes expect.
To audit which mode a scan ran in:
- The report.json carries
planner_fallback: "adaptive" | "uniform" | nullat the headline level —nullmeans the commander wasn’t invoked (no goal anchor and no profile),"uniform"means it was invoked but refused or errored and the swarm fell back,"adaptive"means a successful per-agent plan landed. - The events.jsonl stream emits a
phase_doneevent forcommander-decomposewithsummary.skipped=Truewhen the gate short-circuits. - The run.log carries a
phase commander-decompose: skipped (no operator or inferred goal)INFO line at the gate point.
--goal for any scan where you want an adaptive plan,
or rely on recon’s inferred-goal write-through for goal-less invocations.
--goal cost band
--goal triggers a 3.5x median spend surge vs the no-goal baseline on fast
mode. The Commander allocates many more scenarios per specialist (top-
aligned agents typically get n_scenarios_requested=15 instead of the
default 5-10), roughly doubling the attacker token spend at the same
agents_planned / attempts_total headline.
Reference cost bands on the finbot testbench (a 5-tool HTTP target,
seed=42, gemini:gemini-3.5-flash):
Recommended CI configuration: when wiring
--goal into a CI gate, set
--budget-usd to at least 3.5x your no-goal fast-mode default. A
canonical fast-mode --budget-usd 0.02 (no goal) → --budget-usd 0.07
(with goal). Without the bump, the soft-stop fires at 80% and you get a
budget-truncated scan with mode_authoritative=false even though the
swarm completed cleanly.
The surge is the feature working as designed — the Commander pays for
diversity-of-scenario per agent, which is what lets --goal find
goal-specific exploits a uniform sweep wouldn’t. Budget for it.
Sub-apps
telemetry
Opt-in usage telemetry. Disabled by default.
contract
Work with target contracts.
scans
Manage stored scans (list, delete, purge --older-than). Scans live
under $AGENT_GUARDIAN_HOME/scans (default ~/.agentguardian/scans).
validate
Run the payload-free pre-flight against a contract (Stage 1B).
Walks the seven non-adversarial stages (resolve, connect, probe,
round-trip, session, capability, RoE) and stops at the first failure.
Exits with the failing stage’s exit code.
init
Author a new target contract, then pre-flight it.
calibrate
Calibrate a judge model against the packaged calibration set (Brier
score + accuracy). Uses the same AGENT_GUARDIAN_<PROVIDER>_API_KEY
(then standard) env precedence as scan.
comment
Upsert an AgentGuardian summary comment on the current PR / MR. The gate
verdict embedded in the comment uses the same --fail-under / --max-*
thresholds as the scan gate, so a green/red comment matches the CI exit
code.
code-insights
Publish a Code Insights report for a scan (Bitbucket). The platform poster
must implement post_code_insights(scan).
agentdojo
AgentDojo benchmark adapter. Install the full upstream corpus with
pip install 'agent-guardian[agentdojo]'; without it, a vendored smoke
corpus is used unless --require-upstream is set.
agentdojo run
Run an AgentDojo benchmark suite against an HTTP target.
Exit codes
Defined insrc/agent_guardian/cli.py:
CI gates should branch on the exit code rather than parsing stdout. The
--fail-under N flag turns “scan finished but below N” into a non-zero
exit so the job fails the build.
State + config locations
See Configuration for the full schema and
precedence rules. See Error codes for the LLM
exception taxonomy.