Skip to main content

ApproveKit

Human approval gates for risky AI agent actions.

ApproveKit

ApproveKit is a lightweight, framework-agnostic Python package that wraps tool calls, evaluates simple policy rules, pauses risky actions for human review, and records every outcome in SQLite audit history.

It is built for agent builders, platform engineers, and teams who need a practical local-first approval layer before giving agents access to tools like email, production writes, record deletion, or PII access.

Reviewers

Browser reviewer — approve or reject pending requests from a local web UI:

Web reviewer UI showing two pending approval requests with approve and reject buttons

Terminal reviewer — inspect, approve, and reject from the command line:

Terminal reviewer showing list output and approve/reject commands

What It Does

  • Wrap any Python callable with @kit.guard.
  • Auto-approve low-risk tools while still writing audit entries.
  • Hold risky tool calls until a reviewer approves or rejects them.
  • Default-deny on timeout.
  • Redact configured payload fields before persistence.
  • Review pending requests in a browser with approvekit-web.
  • Keep a durable SQLite audit trail.

Install

pip install approvekit

For local development:

python3 -m pip install -e ".[dev]"

Quick Start

from approvekit import ApproveKit, Policy, Storage

policy = Policy.from_dict({
    "default_timeout": 60,
    "rules": [
        {
            "tool": "send_email",
            "require_approval": True,
            "risk_level": "high",
            "redact_fields": ["body"],
        },
        {
            "tool": "read_record",
            "require_approval": False,
            "auto_approve": True,
            "risk_level": "low",
        },
    ],
})

storage = Storage(db_path="/tmp/approvekit.db")
kit = ApproveKit(policy=policy, storage=storage)

@kit.guard
def send_email(to: str, subject: str, body: str) -> dict:
    return {"status": "sent", "to": to, "subject": subject}

send_email(
    to="ceo@example.com",
    subject="Quarterly report",
    body="Sensitive content that will be redacted in storage.",
)

In a second terminal:

approvekit-web --db /tmp/approvekit.db --port 8765

Open http://127.0.0.1:8765 to approve or reject the pending request.

Guided Demo

Terminal 1:

python3 demo/agent.py --db /tmp/approvekit_demo.db --reset

Terminal 2:

approvekit-web --db /tmp/approvekit_demo.db --port 8765

The demo walks through:

  • auto-approved read
  • approval-required email
  • PII access with redacted fields
  • rejected delete
  • production write that times out unless reviewed

The terminal reviewer is still available:

approvekit-review --db /tmp/approvekit_demo.db

Policy Reference

default_timeout: 60

rules:
  - tool: send_email
    require_approval: true
    timeout: 45
    risk_level: high
    redact_fields: [body]

  - tool: read_record
    require_approval: false
    auto_approve: true
    risk_level: low

  - tool: "*"
    require_approval: true
    risk_level: medium
Field Type Description
tool string Exact tool name, or * for fallback.
require_approval bool Whether a human decision is required before execution.
timeout int Seconds to wait before default-deny timeout.
auto_approve bool Execute immediately and write an approved audit entry.
risk_level string Informational label shown in reviewer UI and audit metadata.
redact_fields list Dict field names to mask before request/audit persistence.

Architecture

Agent tool call
  -> ApproveKit guard
  -> Policy evaluation
  -> Auto-approved path OR pending request in SQLite
  -> Web/CLI reviewer decision
  -> Approved tool execution OR rejected/timeout block
  -> Audit entry

Only approved risky requests execute the wrapped tool body. Rejected and timed-out requests are persisted and audited without executing the action.

Project Structure

approvekit/
  core.py       # guard decorator and approval wait loop
  policy.py     # policy rules, YAML/JSON loading, redaction settings
  storage.py    # SQLite request and audit persistence
  reviewer.py   # terminal reviewer
  web.py        # local browser reviewer
demo/
  agent.py      # guided two-terminal demo
tests/
  test_*.py     # approve, reject, timeout, storage, policy, web tests
docs/
  MVP_IMPLEMENTATION_PLAN.md

Development

python3 -m pip install -e ".[dev]"
python3 -m pytest -q

Maintainer Release Flow

The repository supports one-command patch/minor/major releases via release.py.

Prerequisites:

  • gh CLI is installed and authenticated (gh auth login).
  • GitHub repository secrets are set for Actions publishing:
    • TEST_PYPI_API_TOKEN
    • PYPI_API_TOKEN

One-command patch release:

python3 release.py patch

What it does:

  • bumps version in pyproject.toml and approvekit/__init__.py
  • scaffolds a new CHANGELOG.md release section
  • runs tests + build + twine checks
  • commits, tags, and pushes (vX.Y.Z)
  • creates a GitHub Release (gh release create)

Publishing is then handled automatically by .github/workflows/publish-pypi.yml when the release is published.

Documentation

License

MIT

Metadata

Release files for approvekit 0.1.2

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

Source distribution (sdist)

Source distribution for approvekit 0.1.2
File Size Uploaded
approvekit-0.1.2.tar.gz 24.6 kB Details

Built distribution (wheel)

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

Total release size: 46.0 kB

Release files / approvekit-0.1.2.tar.gz

Download URL approvekit-0.1.2.tar.gz
Size 24.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b534da99238aef280bcbed7a3d680831ddbccd15533ef2efcd22e8ad52439c82
BLAKE2b-256 checksum
How to use checksums
d969cbab57637f375ca26891dc3b8ab21a12a8b07a2e52844e8f9665df8c61e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / approvekit-0.1.2-py3-none-any.whl

Download URL approvekit-0.1.2-py3-none-any.whl
Size 21.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2da1cbad89ad82ba3be9c09c09f8c70347b2194f74af46ba755775270c2840a9
BLAKE2b-256 checksum
How to use checksums
d317eefda64c520a61f33fb25be514bf291bf1c9edffb63e02c5a84dea4f0fe3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

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