Adversarial verification for AI-generated work.
The worker and the verifier are always separate agents. Self-verification is not verification.
AI agents generate code that breaks in production. They hallucinate package versions. They make security claims that fall apart under scrutiny. And when you ask them to verify their own work? They rationalize the mistakes instead of catching them.
Self-verification doesn't work because the same model that made the error will defend it.
Proof Agent enforces separation:
- Worker agent makes changes
- Verifier agent (separate, independent) checks the work
- Verifier runs commands, checks facts, assigns a verdict
The verifier has no access to the worker's self-assessment. It must verify with evidence.
Verdicts:
- PASS — All checks passed with evidence
- FAIL — Issues found. Report specifics. Retry up to 3 times if auto-fixable.
- PARTIAL — Some checks passed, others couldn't be verified
What It Checks
- Security Vulnerabilities — SQL injection, hardcoded secrets, authentication bypasses, XSS/CSRF
- Correctness — Does the code match the stated purpose? Logical errors?
- Code Quality — Bugs, error handling, race conditions, edge cases
- Static Analysis — Reviews code changes directly from git diff
Review method: Static code review (reads diff output, does NOT execute code or run tests)
Rule: Verifier must cite specific files, line numbers, and code snippets in verdict.
Add this workflow to your repo:
.github/workflows/proof-agent.yml:
name: Proof Agent
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
copilot-requests: write
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: AndreaGriffiths11/proof-agent@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
base-ref: origin/main
block-on-fail: true
post-comment: trueThat's it. Every PR gets automatic verification.
Uses the GitHub Copilot SDK. No GitHub Models token is required. In GitHub Actions, the built-in GITHUB_TOKEN needs copilot-requests: write, and the organization must allow Copilot CLI usage from Actions.
Use your own model providers for verification.
jobs:
verify:
runs-on: ubuntu-latest
env:
PROOF_AGENT_PROVIDER_BASE_URL: https://api.anthropic.com
PROOF_AGENT_PROVIDER_TYPE: anthropic
PROOF_AGENT_PROVIDER_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
PROOF_AGENT_MODEL: claude-sonnet-4-20250514
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: AndreaGriffiths11/proof-agent@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}jobs:
verify:
runs-on: ubuntu-latest
env:
PROOF_AGENT_PROVIDER_TYPE: azure
PROOF_AGENT_PROVIDER_BASE_URL: https://mycompany.openai.azure.com
PROOF_AGENT_PROVIDER_API_KEY: ${{ secrets.AZURE_OPENAI_KEY }}
PROOF_AGENT_MODEL: gpt-4-turbo
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: AndreaGriffiths11/proof-agent@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}jobs:
verify:
runs-on: ubuntu-latest
env:
PROOF_AGENT_PROVIDER_BASE_URL: http://localhost:11434/v1
PROOF_AGENT_MODEL: qwen2.5-coder:3b # Good balance of size/performance
# Also works: qwen2.5:0.5b, gemma2:2b, deepseek-coder:6.7b
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: AndreaGriffiths11/proof-agent@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}Supported providers: Anthropic, Azure OpenAI, OpenAI-compatible endpoints (OpenAI, Ollama, vLLM, etc.).
Cost optimization: Use a different model for the verifier step with PROOF_AGENT_VERIFIER_MODEL.
clawhub install proof-agentTalk to your agent:
"I added OAuth login. Verify it's safe."
The agent spawns a verifier subagent and runs checks.
git clone https://github.com/AndreaGriffiths11/proof-agent.git
cd proof-agent
# Generate verification prompt
bash scripts/verify.sh > verification_prompt.txt
# Send to your LLM
cat verification_prompt.txt | your-llm-cliAction Inputs
- uses: AndreaGriffiths11/proof-agent@main
with:
# GitHub token (use built-in GITHUB_TOKEN)
github-token: ${{ secrets.GITHUB_TOKEN }}
# Optional token used for Copilot SDK requests
# Falls back to github-token when omitted
copilot-token: ${{ secrets.COPILOT_TOKEN }}
# Git ref to compare against
base-ref: origin/main
# Force verification even when thresholds are not met
force: false
# Block PR merge if FAIL
block-on-fail: true
# Post verdict as PR comment
post-comment: true
# Comment format: collapse (default), summary, or full
comment-mode: collapse
# Max comment length in characters
max-comment-length: 2000Comment modes:
collapse— First paragraph visible, rest in expandable sectionsummary— Verdict + key findings onlyfull— Everything visible (truncates at max-comment-length)
Proof Agent Config (proof-agent.yaml)
Customize thresholds and patterns:
thresholds:
min_files_changed: 3
always_verify:
- "**/*auth*"
- "**/*secret*"
- "**/*permission*"
- "**/Dockerfile"
- "**/*.env*"
never_verify:
- "**/.gitignore"
retry:
max_attempts: 3
escalate_on_max: trueWhen Verification Triggers
Auto-verify when:
- ≥3 files changed
- ANY file matches:
*auth*,*secret*,*permission*,Dockerfile,*.env* - You explicitly force verification with
force: trueorbash scripts/verify.sh <base-ref> --force
Skip for:
- Formatting-only changes
.gitignorechanges
When thresholds are not met, the action exits successfully and reports SKIP in its action output/comment.
Scenario: AI agent writes authentication code
- Worker agent generates
src/auth.py,tests/test_auth.py, updatesrequirements.txt - Proof Agent detects: 3+ files changed +
*auth*pattern → triggers verification - Verifier agent spawns, receives:
- Original request
- Files changed (list)
- Approach taken (git diff output)
- Verifier reviews the code changes:
- Scans
src/auth.pyfor hardcoded secrets, SQL injection, auth bypasses - Checks
tests/test_auth.pyfor edge case coverage - Reviews
requirements.txtfor suspicious dependencies
- Scans
- Verifier finds:
- Hardcoded API key in
src/auth.py:42(API_KEY = "sk-1234...") - SQL query uses string interpolation (injection risk)
- Missing input validation on username parameter
- Hardcoded API key in
- Verdict: FAIL — Security issues (hardcoded secret + SQL injection + missing validation)
- Proof Agent posts comment, blocks merge
- Developer fixes issues → pushes new commit → re-verifies → PASS
Action fails with Copilot SDK authentication or access errors
Check workflow permissions:
permissions:
contents: read
pull-requests: write
copilot-requests: write # ← Required for Copilot SDK requestsVerify Copilot requests are enabled:
- The organization must allow Copilot CLI usage from GitHub Actions.
- If your repository or organization requires a dedicated token, pass
copilot-token.
PR comment not posted (403/404 error)
Check workflow permissions:
permissions:
pull-requests: write # ← Required for posting comments
contents: read
copilot-requests: writeFor private repos, use secrets.GITHUB_TOKEN (already has correct permissions).
SKIP on every PR
Proof Agent skips if <3 files changed AND no sensitive files detected.
To force verification:
- Change 3+ files, OR
- Touch a sensitive file:
*auth*,*secret*,Dockerfile,*.env*
Single-agent limitations vs. Adversarial separation
Single-agent limitations:
- Same model that made the mistake will rationalize it
- Confirmation bias in self-review
- No incentive to find flaws
Adversarial separation:
- Verifier has no stake in worker's success
- Forced to provide evidence
- Different prompts catch different issues
Real-world analogy:
- Code review (separate developer)
- Security audit (external team)
- Peer review (different researcher)
MIT — Andrea Griffiths, 2026