Human-in-the-loop approval middleware for risky AI agent actions
Project description
ApproveKit
Human approval gates for risky AI agent actions.
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.
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:
ghCLI is installed and authenticated (gh auth login).- GitHub repository secrets are set for Actions publishing:
TEST_PYPI_API_TOKENPYPI_API_TOKEN
One-command patch release:
python3 release.py patch
What it does:
- bumps version in
pyproject.tomlandapprovekit/__init__.py - scaffolds a new
CHANGELOG.mdrelease 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
- Landing page: http://approvekit.theajaykumar.com
- Developer docs: http://approvekit.theajaykumar.com/docs.html
- MVP tracker:
docs/MVP_IMPLEMENTATION_PLAN.md - Changelog:
CHANGELOG.md
License
MIT
Project details
Release history Release notifications | RSS feed
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 approvekit-0.1.1.tar.gz.
File metadata
- Download URL: approvekit-0.1.1.tar.gz
- Upload date:
- Size: 24.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d88a3f0bff4b202ee473e1a39a36968f2a9477661fe7ac43a42c88b8ee4d1fe5
|
|
| MD5 |
2f6ecd2ebd087a72a9f84495c9e4df31
|
|
| BLAKE2b-256 |
4dbbe32c402d576e68f1fcd414b68d30fff4ad4d11159c659cb51ce0dd564f5e
|
File details
Details for the file approvekit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: approvekit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbbd04b18e095b51cbc12f396d1f07815338c6df18b790386d5b1032abe8c455
|
|
| MD5 |
512c326d49a8990f3aa6f43e6c7512ff
|
|
| BLAKE2b-256 |
f687e4e955c0dd5a368e405ac9b9e9b24e332724ed2c7c305d53b33e2065b923
|