Skip to main content

vulnify

Runtime authorization for AI agents. Before the agent exports or sends customer records, your app asks Vulnify. The decision is ALLOW, REVIEW, or BLOCK. The score is an integer from 0 to 100 and comes back with reasons.

Vulnify sees action metadata — agent, action, resource, destination, and record count — not the records. In monitor mode the event is stored and not enforced: obey decision. evaluated_decision is what enforcement would have returned, and monitored is True. If Vulnify cannot be reached, the default is fail-closed.

Standard library only. Python 3.9+.

Production API: https://api.vulnify.io

Install

pip install vulnify

Production scenario

An agent is about to export customer records to an external destination. Call check() first.

  • ALLOW runs the export.
  • REVIEW stops and tells the caller a human must approve. The export does not run.
  • BLOCK does not run the export.
  • If Vulnify cannot be reached, check() returns BLOCK with degraded=True. The export does not run.

Set VULNIFY_API_KEY. VULNIFY_BASE_URL overrides the host; when it is unset this example uses https://api.vulnify.io. Omitting base_url in the constructor falls back to http://localhost:3000.

import os
import sys

from vulnify import Vulnify


def export_customer_records() -> None:
    """Replace the body with the real export. It runs only after ALLOW."""
    print("exporting customer records to the external destination")


def main() -> None:
    api_key = os.environ.get("VULNIFY_API_KEY")
    if not api_key:
        raise SystemExit("Set VULNIFY_API_KEY")

    vulnify = Vulnify(
        api_key=api_key,
        base_url=os.environ.get("VULNIFY_BASE_URL", "https://api.vulnify.io"),
    )

    decision = vulnify.check(
        agent="SalesBot",
        action="EXPORT_DATA",
        resource="Customer Database",
        destination="EXTERNAL_EMAIL",
        records_affected=12000,
    )

    if decision.decision == "ALLOW":
        export_customer_records()
        return

    reasons = "; ".join(decision.reasons) or "no reason given"

    if decision.decision == "REVIEW":
        score = "unknown" if decision.risk_score is None else str(decision.risk_score)
        event_id = decision.id or "none"
        raise SystemExit(
            f"A human must approve this export before it runs (event {event_id}, score {score}). {reasons}"
        )

    if decision.degraded:
        raise SystemExit(f"Vulnify could not be reached. The export was not run. {reasons}")

    raise SystemExit(f"Export blocked. The export was not run. {reasons}")


if __name__ == "__main__":
    try:
        main()
    except Exception as err:
        print(err, file=sys.stderr)
        raise SystemExit(1)

A REVIEW is approved on the Vulnify server (Slack, an MFA step-up, or a separate approver). This process does not approve it and does not poll. A separate MCP or HTTP gateway injects secrets only after ALLOW.

guard(fn, **action) runs fn only for ALLOW and raises VulnifyBlockedError for REVIEW and BLOCK. Pass wait={"timeout": 300} only when you mean to poll until someone approves. protect(**action) is the same check as a decorator. Retries reuse the same Idempotency-Key, so a retry does not create a second event.

Decisions

  • ALLOW — run the action. risk_score is 0–100. reasons explains the score.
  • REVIEW — do not run the action. review["status"] starts as PENDING. Tell the caller a human must approve.
  • BLOCK — do not run the action.

Follow decision in monitor mode as well. An invalid API key, an unknown agent or resource, or a rejected payload raises VulnifyError. fail_mode="open" does not swallow those errors.

Optional content is scanned for sensitive data and is not stored. Matches return on dlp_findings.

Fail-closed

fail_mode defaults to "closed". A timeout or a network error becomes decision="BLOCK", degraded=True, and a reason beginning with Vulnify unavailable. The scenario above does not call export_customer_records(). Set fail_mode="open" only when an outage should let the action through.

Audit events are hash-chained. SIEM export is JSON or CEF. Evidence in the product maps to LGPD, ISO/IEC 42001, NIST AI RMF, and the EU AI Act. That mapping is not a certification.

vulnify.adapters guards CrewAI and LangGraph tools without importing either framework. Samples are in examples/.

Development

pip install -e ".[dev]"
pytest

License

MIT. Copyright 2026 Vulnify.

Metadata

Release files for vulnify 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vulnify 0.1.1
File Size Uploaded
vulnify-0.1.1.tar.gz 10.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vulnify 0.1.1
File Interpreter ABI Platform
vulnify-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 19.5 kB

Release files / vulnify-0.1.1.tar.gz

Download URL vulnify-0.1.1.tar.gz
Size 10.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b55a06cd30a142bec99efe92923940d007d08c8398b0ff911eb0c1aaa595ba0b
BLAKE2b-256 checksum
How to use checksums
690c40ee0b752706c76f382084bdd94f2b3180e80ff4de87799fa3b3a1b78366
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Release files / vulnify-0.1.1-py3-none-any.whl

Download URL vulnify-0.1.1-py3-none-any.whl
Size 9.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0457218fe8959b9257b8f81421937e80e34cfc193e70593f773702ce10e76d6
BLAKE2b-256 checksum
How to use checksums
0ba0db74a541cda9f4c7d8fbf00895e9bfc06af150d6213c0a577291a5afde13
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page