Guides · CI/CD
Make privacy a required status check
A deterministic score means a regression in CI is a real signal: the same trace always produces the same number, so when it moves, the agent changed. Use the official Action on GitHub, or the CLI’s exit code anywhere else. No AgentLeak account, no telemetry.
The official GitHub Action
One step. It installs the pinned version, runs the analysis, annotates the pull request, writes a job summary a reviewer can read without opening logs, and exits non-zero when the run crosses your policy.
name: privacy-gate
on: [pull_request]
jobs:
agentleak:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: yagobski/agentleak@v1
with:
trace: traces/latest.json
fail-under: 80Mark the job as a required status check in branch protection and a leaking change cannot merge.
Three things it can gate on
Point the Action at a captured trace, at a scenario from a bundled pack, or at your source tree. The first two score a run; the third catches the leak before the agent even executes.
# 1. a captured trace
- uses: yagobski/agentleak@v1
with: { trace: traces/latest.json, fail-under: 80 }
# 2. a scenario from a bundled pack
- uses: yagobski/agentleak@v1
with: { pack: privacylens_ci, scenario: main1 }
# 3. a static scan of the agent's own source
- uses: yagobski/agentleak@v1
with: { scan: ./src, fail-under: 90 }traceA run you captured with the SDK or an OTel exporter. The full 8-channel analysis.pack + scenarioA bundled research scenario. Omit scenario to run the whole pack as a suite.scanStatic analysis of the agent’s own code: hardcoded secrets, PII in logs, sensitive values sent to third parties.fail-underThe privacy score below which the job fails. Defaults to 80.What lands on the pull request
Findings become workflow annotations graded by severity — L4 and L3 are errors, L2 a warning, L1 a notice. A code scan anchors them to file:line like a linter; a trace analysis names the channel the data escaped through. Step outputs let later jobs branch on the result.
- uses: yagobski/agentleak@v1
id: privacy
with: { trace: traces/latest.json }
- run: echo "score=${{ steps.privacy.outputs.score }} verdict=${{ steps.privacy.outputs.verdict }}"
if: always()scorePrivacy score, 0 to 100.risk-indexAgentRisk, 0.0000 to 1.0000.verdictPass, Conditional pass, High risk or Fail.findingsNumber of findings in the report.reportPath to the JSON report, ready to upload as an artifact.Every report states which detection tiers actually ran. A Pass produced by the regex tier alone is a weaker claim than one from the full pipeline, and the job summary says so rather than letting silence imply strength.
Define the release contract
pip install agentleak
agentleak run --trace traces/latest.json --config agentleak.yaml --fail-under 80 --output reports/agentleak.jsonPin the version so the gate is reproducible, then pin the vault scope, detectors, assertions, plugins and strategies in agentleak.yaml. Keep the JSON report even when the job fails — it is the evidence.
Any CI: the raw CLI
The Action is a convenience wrapper. The gate itself is the exit code, so the same contract works in any runner — here spelled out for GitHub without the Action.
name: agent-privacy
on: [pull_request]
jobs:
agentleak:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "3.12"}
- run: pip install agentleak
- run: mkdir -p reports && agentleak run --trace traces/latest.json --config agentleak.yaml --fail-under 80 --output reports/agentleak.json
- if: always()
uses: actions/upload-artifact@v4
with: {name: agentleak-evidence, path: reports/}GitLab CI
agentleak:
image: python:3.12-slim
script:
- pip install agentleak
- mkdir -p reports
- agentleak run --trace traces/latest.json --config agentleak.yaml --fail-under 80 --output reports/agentleak.json
artifacts:
when: always
paths: [reports/]
expire_in: 30 daysJenkins
pipeline {
agent { docker { image 'python:3.12-slim' } }
stages {
stage('Agent privacy gate') {
steps {
sh 'pip install agentleak'
sh 'mkdir -p reports && agentleak run --trace traces/latest.json --config agentleak.yaml --fail-under 80 --output reports/agentleak.json'
}
}
}
post { always { archiveArtifacts artifacts: 'reports/**', allowEmptyArchive: true } }
}Evidence and secret handling
JSONCanonical machine artifact with findings, policy, compliance evidence and digest.SARIFUse static-scan SARIF for code annotations; retain runtime evidence as JSON.Provider keysNot needed for scripted tests. Use CI secrets and synthetic data for live targets.RetentionSet an explicit artifact lifetime because source traces may contain private context.Troubleshooting
- Unpinned versionPin both the Action tag and the package version, or a gate can change under you between runs.
- Missing failed artifactCreate the directory first and upload with
always()orwhen: always. - Unstable live scoreRun scripted controls first, pin the target model and compare multiple live runs.
- False compliance passInspect assurance and controls_not_assessed; missing governance evidence is not compliance.