The harness runs fully local by default. When you want a release gate, add
--upload: the harness POSTs the completed evaluation to the ProofAgent
Governance API, the API runs its gate engine against your governance profile,
and the harness exits with a code your pipeline can act on.
Every --upload run goes to ProofAgent Cloud (https://app.proofagent.ai)
by default; set PROOFAGENT_API_BASE_URL to point the CLI at an
Enterprise / on-prem backend instead.
On-prem / Enterprise? The same CLI works — export
PROOFAGENT_API_BASE_URL=https://proofagent.acme.internal(or passupload_run(api_url=…)from Python).
Terminology: the model that reviews the agent under test is the harness LLM. The Governance API never sees your harness-LLM credentials — only the resulting
Report.
No network, no account, no data leaves your machine. This is the plain harness:
proof run my_agent.py \
--role "airline customer support agent" \
--turns 12Exit code: 0 unless the certification is NOT_READY (then 1). Use this for
local iteration.
Run locally and push the result to the Governance API to see it on the
dashboard. You only need an API key — the base URL defaults to ProofAgent
Cloud (https://app.proofagent.ai):
export PROOFAGENT_API_KEY="pa_live_..." # the only thing required for Cloud
proof run my_agent.py \
--role "airline customer support agent" \
--upload --source manual --fail-on block \
--agent airline-support --agent-version "$(git rev-parse --short HEAD)" \
--profile airline_customer_supportThe same command with --source ci_cd (the default). The process exit code is
the gate decision — let it fail the job. See the GitHub Actions example below.
| Variable | CLI flag | Purpose |
|---|---|---|
PROOFAGENT_API_KEY |
--api-key |
API key for the Governance API. Required for --upload. |
PROOFAGENT_EVIDENCE |
none | 0 disables evidence-driven findings (on by default). |
PROOFAGENT_EVIDENCE_LLM |
none | Model used to structure finding evidence (default gpt-4.1-mini). |
PROOFAGENT_COMPLIANCE |
--assess-compliance |
Truthy (1) opts in to the compliance assessment without the flag. Off by default. |
PROOFAGENT_COMPLIANCE_FRAMEWORKS |
--frameworks |
Comma-separated framework ids to assess (same scope override as --frameworks). |
The CLI flag wins over the environment variable when both are set. The base URL
defaults to ProofAgent Cloud, so only the API key is required. If --upload
is given with no key, the harness prints a clear error and exits non-zero (it
does not silently skip the gate).
On upload, each finding is enriched into actionable, evidence-driven bullets instead of prose. For every finding the harness produces:
- a one-line summary of the concrete failure,
- bullets of
claim → artifact line ref → contradicting source + line, and - a fix recommendation.
The governance dashboard renders these natively (claim, "Claimed at" line, a red "Contradicts" line with the source ref, and a green Recommendation callout).
This runs as one LLM call per finding (capped at 8) at upload time, using the artifact text + knowledge corpus (artifact mode) or the transcript (multi-turn) as grounding. It is best-effort and no-op-safe: if the model is unavailable or a call fails, the finding keeps its existing prose — the gate decision is never affected.
- On by default. Set
PROOFAGENT_EVIDENCE=0to skip it (e.g. air-gapped runs where the evidence model isn't reachable). - Model:
PROOFAGENT_EVIDENCE_LLM(defaultgpt-4.1-mini). Use a small, cheap model — this is structuring, not scoring.
A post-jury compliance-assessor node maps the finished evaluation to the
regulatory frameworks that govern the agent — a per-control status (met /
partial / attention / not_evaluated) plus a why-not-compliant / proof /
fix per control, using the jury's findings as evidence — and attaches it to the
report (report.compliance). It travels in the report and the upload payload,
so the governance platform only displays it and never calls a model.
- Opt-in, off by default. Enable with
--assess-compliance(orPROOFAGENT_COMPLIANCE=1). One harness-LLM call covering all selected frameworks; it never affects the metric scores, certification, or the gate. No-op-safe: if no harness LLM is configured or the call fails, the frameworks simply render as a neutral "not assessed". - Scope resolution (which frameworks are assessed):
--frameworks a,b,calways wins (fully local); otherwise the Agent Governance Profile's frameworks (below), when one is loaded; otherwise the platform profile's selection, fetched viaGET /compliance/selectionwhen an API key is present; otherwise the local default core set (pure open source, no network call). - Rendered in the report Markdown and shown on the governance Compliance page (with each framework's coverage %, control statuses, and rationale).
The gate does not require the cloud. An Agent Governance Profile — one YAML
block declaring the agent's risk context (use case, autonomy level, data
sensitivity, region, human oversight, consequential actions) — is run through the
same deterministic risk classifier the dashboard uses, and the derived tier
guardrails gate the release locally with the same exit codes as the table
below: score floor per tier, block on finding severity, sign-off tiers stop at
review, prohibited use cases always block.
# governance as code: the profile lives in your repo, the gate runs on your machine
proof run my_agent.py --governance-profile governance.yaml --fail-on blockPrecedence: a --governance-profile file wins; --assess-governance instead
pulls the profile bound to --agent NAME from the dashboard (best-effort — an
offline run proceeds without it); with neither, the evaluation runs exactly as
before. With a profile attached the whole run is governed by the classification:
the adversarial evaluation targets the declared risk, --assess-context is held
to the tier's bar, and --assess-compliance is scoped to the profile's
frameworks (see the README's Agent Governance Profile section for the full
YAML anatomy and tier guardrails).
With --upload, the profile travels in the payload as
agent_governance_profile and fills the agent's risk classification on the
dashboard.
| Flag | Default | Meaning |
|---|---|---|
--upload/--no-upload |
--no-upload |
Turn the gate on. |
--api-key |
$PROOFAGENT_API_KEY |
API key. Required for --upload. |
--agent |
falls back to --role |
Logical agent name — groups runs and powers regression checks. |
--agent-version |
none | Version / git ref of the agent under test. |
--profile |
none | Governance profile slug to evaluate against. |
--fail-on |
block |
Which decision fails the build: pass | review | block. |
--source |
ci_cd |
Run origin: local | ci_cd | manual | api | scheduled. |
--environment / --env |
none | Deployment environment recorded on the run: development | staging | production. Governance uses it for release decisions + workflow matching. |
The Governance API returns a gate_status; the harness maps it to a process
exit code so CI can gate on it:
| Gate decision | Exit code | Meaning |
|---|---|---|
pass |
0 | Release allowed. |
review |
1 | Soft gate — needs a human. Exit 1 only with --fail-on review; with the default --fail-on block a review is informational (exit 0). |
block |
2 | Hard gate — release blocked. Always exit 2, regardless of --fail-on. |
--fail-on controls strictness:
--fail-on block(default): only ablockfails the build.--fail-on review: bothreviewandblockfail the build.--fail-on pass: never fails onreview; ablockstill exits2.
When --upload succeeds, the harness prints the decision, the final score and
grade, any failed_rules, and the dashboard_url.
The same gate works on a finished artifact — generated code, a BRD, a
technical spec, a report, a plan — with proof artifact --upload. Score the
deliverable against a knowledge corpus and gate on the result:
export PROOFAGENT_API_KEY="pa_live_..." # base URL defaults to Cloud
proof artifact ./proposal.md \
--type BRD \
--knowledge-dir ./docs \
--llm gpt-4.1-mini \
--upload --source ci_cd --fail-on block \
--agent analyst-brd --agent-version "$(git rev-parse --short HEAD)" \
--profile artifact_governance_defaultbuild_governance_payload detects the mode from the Report, so the payload
carries the artifact section (section scores, unsupported claims, missing
requirements) instead of a turn-by-turn transcript. Everything else — flags,
exit codes, gate semantics, the Cloud/Enterprise URL switch — is identical to a
multi-turn run.
--upload is sugar over three public functions in
proofagent_harness.governance. Call them directly when you run the harness
from Python — the mechanism is the same for both modes:
import os, sys
from proofagent_harness import Harness
from proofagent_harness.governance import (
build_governance_payload, upload_run, gate_exit_code, GovernanceUploadError,
)
# 1. Run the eval (multi-turn shown; artifact mode is identical from step 2 on —
# Harness(mode="artifact").evaluate(artifact=..., knowledge_corpus=...)).
report = Harness(llm="gpt-4.1-mini", turns=12).evaluate(
my_agent, role="airline customer support agent",
)
# 2. Map the Report to the governance run-upload contract.
payload = build_governance_payload(
report,
agent_name="airline-support", # groups runs + powers regressions
agent_version="1.4.0", # git ref of the agent under test
profile="airline_customer_support",
source="ci_cd", # local | ci_cd | manual | api | scheduled
)
# 3. Upload + gate. api_url defaults to ProofAgent Cloud — pass it only for an
# Enterprise / on-prem endpoint (api_url="https://proofagent.acme.internal").
try:
decision = upload_run(payload, api_key=os.environ["PROOFAGENT_API_KEY"])
except GovernanceUploadError as exc:
print(f"upload failed: {exc}")
sys.exit(2)
print(decision["gate_status"], "→", decision.get("dashboard_url"))
sys.exit(gate_exit_code(decision["gate_status"], fail_on="block"))Every runnable example does this in one line via the bundled
examples/_dashboard.py helper, which is env-gated
and no-op-safe (the run stays fully offline until you set PROOFAGENT_API_KEY):
from _dashboard import push_to_dashboard
push_to_dashboard(report, agent_name="my-agent", profile="my_profile")name: Agent governance gate
on:
pull_request:
branches: [main]
jobs:
governance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
- name: Install the harness
run: |
python -m pip install --upgrade pip
pip install proofagent-harness
- name: Evaluate + gate on the governance decision
env:
PROOFAGENT_API_KEY: ${{ secrets.PROOFAGENT_API_KEY }}
# The harness LLM credentials (kept on the runner, never uploaded).
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
proof run my_agent.py \
--role "airline customer support agent" \
--turns 12 \
--upload \
--source ci_cd \
--fail-on block \
--agent airline-support \
--agent-version "${GITHUB_SHA::7}" \
--profile airline_customer_supportA block decision exits 2 and fails the job; pass exits 0 and the merge
proceeds. Switch --fail-on review once your team is ready to also gate on
soft-review decisions.