The permission layer for AI agents. Controls what passes through.
Project description
Aperture
The permission layer for AI agents.
AI agents can run shell commands, read your files, call APIs, and modify databases. Today, you're the only thing standing between an agent and rm -rf /. Every action gets a yes/no popup. You either approve everything blindly or slow your workflow to a crawl.
Aperture fixes this. It sits between your agent runtime and the outside world, learns your permission preferences over time, and auto-approves the safe stuff — so you only get asked about things that actually matter.
Setup guides: Claude Code | OpenClaw | REST API | Python library
How it works
┌──────────────────────────────────────────────────────────────────┐
│ Your Agent Runtime │
│ (Claude Code, OpenAI Agents, LangChain, etc.) │
└──────────────────────┬───────────────────────────────────────────┘
│
│ "Can this agent run `npm test`?"
▼
┌──────────────────────────────────────────────────────────────────┐
│ APERTURE │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
│ │ Permission │ │ Risk Scoring │ │ Learning Engine │ │
│ │ Engine │ │ │ │ │ │
│ │ │ │ tool danger │ │ You approved npm test │ │
│ │ RBAC rules │─▶│ × action │ │ 15 times in a row. │ │
│ │ Task grants │ │ severity │ │ Auto-approving now. │ │
│ │ Learned │ │ × scope │ │ │ │
│ │ patterns │ │ breadth │ │ You denied rm -rf / │ │
│ │ │ │ │ │ every time. │ │
│ └──────┬───┬──┘ └──────────────┘ │ Auto-denying now. │ │
│ │ │ └───────────────────────┘ │
│ │ │ ┌──────────────┐ ┌───────────────────────┐ │
│ │ │ │ Audit Trail │ │ Artifact Store │ │
│ │ └────▶│ Every │ │ SHA-256 verified │ │
│ │ │ decision │ │ immutable storage │ │
│ │ │ logged │ │ for agent outputs │ │
│ │ └──────────────┘ └───────────────────────┘ │
└──────────┼───────────────────────────────────────────────────────┘
│
▼
┌─────────────┐
│ ALLOW │ ← auto-approved (learned pattern)
│ DENY │ ← auto-denied (learned pattern)
│ ASK │ ← no pattern yet, ask the human
└─────────────┘
No LLM calls. Every decision is deterministic — glob matching, statistics, and pattern lookup. Aperture never phones home, never calls an API, and adds zero latency from model inference.
What you experience
Day 1 — Aperture asks you about everything, just like today. But it's recording your decisions.
Day 3 — You've approved npm test, git status, and cat README.md a dozen times each. Aperture stops asking about those. You still get prompted for rm, curl, and anything touching production.
Day 7 — The only popups you see are for genuinely new or risky actions. Everything routine is auto-approved. Everything dangerous is auto-denied. Your agent moves faster and you have a full audit trail of every decision.
Quick start
pip install aperture-ai # Install from PyPI
aperture init-db # Initialize the database
aperture serve # Start the API server on localhost:8100
That's it. Aperture is running. Now connect your agent runtime.
Connect your runtime
Claude Code (MCP)
Add to your .mcp.json:
{
"mcpServers": {
"aperture": {
"type": "stdio",
"command": "aperture",
"args": ["mcp-serve"]
}
}
}
This gives Claude Code 9 tools including check_permission, approve_action, deny_action, store_artifact, and get_audit_trail.
Full Claude Code setup guide →
OpenClaw
Add Aperture as OpenClaw's MCP permission server:
{
"mcpServers": {
"aperture": {
"command": "aperture",
"args": ["mcp-serve"],
"env": {
"APERTURE_DB_PATH": "./aperture.db"
}
}
}
}
Add a system prompt that tells the agent to call check_permission before every action, then openclaw chat.
REST API
Any agent runtime can use the HTTP API:
# Check a permission
curl -X POST localhost:8100/permissions/check \
-H "Content-Type: application/json" \
-d '{"tool": "shell", "action": "execute", "scope": "npm test"}'
# Record a human decision (feeds the learning engine)
curl -X POST localhost:8100/permissions/record \
-H "Content-Type: application/json" \
-d '{
"tool": "shell", "action": "execute", "scope": "npm test",
"decision": "allow", "decided_by": "user-1"
}'
Python library
from aperture.permissions import PermissionEngine
from aperture.models import PermissionDecision
engine = PermissionEngine()
# Check if an action is allowed
verdict = engine.check("shell", "execute", "npm test", rules=[])
# Record a human decision
engine.record_human_decision(
tool="shell", action="execute", scope="npm test",
decision=PermissionDecision.ALLOW, decided_by="user-1",
organization_id="my-org",
)
# After enough decisions, the engine auto-approves
verdict = engine.check("shell", "execute", "npm test", rules=[])
print(verdict.decision) # PermissionDecision.ALLOW
Features
| Feature | What it does |
|---|---|
| Permission Engine | RBAC rules + task-scoped grants (ReBAC) + auto-learning from human decisions |
| Risk Scoring | OWASP-inspired tool danger × action severity × scope breadth — flags rm -rf / as CRITICAL, cat README.md as LOW |
| Learning Engine | Tracks your approval/denial history per (tool, action, scope). After 10+ consistent decisions, auto-decides |
| Crowd Wisdom | Aggregates decisions across your org — surfaces what your team usually approves or denies |
| Artifact Store | SHA-256 verified, immutable storage for every agent output |
| Audit Trail | Append-only compliance log of every permission decision |
| MCP Server | 9 tools for Claude Code via Model Context Protocol |
| REST API | FastAPI server for any agent runtime |
| CLI | aperture serve, aperture init-db, aperture configure |
How decisions are made
Aperture resolves permissions in this order, stopping at the first match:
1. Session memory → Already decided this session? Reuse it.
2. Task grants (ReBAC) → Scoped permission for this specific task?
3. Learned patterns → 10+ consistent human decisions? Auto-decide.
4. Static RBAC rules → Glob-matched rules (most specific wins).
5. Default deny → No match? Deny.
When enrichment is enabled, each verdict also includes:
- Risk assessment — tier (LOW/MEDIUM/HIGH/CRITICAL), score, factors, reversibility
- Human-readable explanation — what the action does, in plain English
- Crowd signal — what your org has historically decided for this pattern
- Similar patterns — related decisions that might inform this one
- Recommendation — auto-approve, auto-deny, suggest a rule, or keep asking
Configuration
All settings via environment variables (prefix APERTURE_):
| Variable | Default | Description |
|---|---|---|
APERTURE_DB_BACKEND |
sqlite |
sqlite or postgres |
APERTURE_DB_PATH |
aperture.db |
SQLite file path |
APERTURE_POSTGRES_URL |
— | Postgres connection URL |
APERTURE_PERMISSION_LEARNING_ENABLED |
true |
Auto-learn from human decisions |
APERTURE_PERMISSION_LEARNING_MIN_DECISIONS |
10 |
Min decisions before auto-deciding |
APERTURE_AUTO_APPROVE_THRESHOLD |
0.95 |
Approval rate to trigger auto-approve |
APERTURE_AUTO_DENY_THRESHOLD |
0.05 |
Approval rate to trigger auto-deny |
APERTURE_INTELLIGENCE_ENABLED |
false |
Cross-org intelligence (opt-in) |
APERTURE_API_HOST |
0.0.0.0 |
API bind host |
APERTURE_API_PORT |
8100 |
API bind port |
Or run aperture configure for an interactive setup wizard.
Development
pip install -e ".[dev]"
python -m pytest tests/ -v
Requires Python 3.12+.
License
Apache 2.0 — see LICENSE.
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 aperture_ai-0.2.0.tar.gz.
File metadata
- Download URL: aperture_ai-0.2.0.tar.gz
- Upload date:
- Size: 82.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab57e64bc1276b06317ab9ac30aed2b73a36a1078a7f21b3c5a68a4cbe59394f
|
|
| MD5 |
c048bacf5b7e717ad3701afa8dbd027d
|
|
| BLAKE2b-256 |
73b44efb851ab1da96058f69d312c12c7e56a6bf04ac685554e9faa88f7530ed
|
File details
Details for the file aperture_ai-0.2.0-py3-none-any.whl.
File metadata
- Download URL: aperture_ai-0.2.0-py3-none-any.whl
- Upload date:
- Size: 55.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb5a6201fd2ee7ac26195a112b2ad2e2a6d9f6fe8c15d3ce479948a31acd0598
|
|
| MD5 |
f8f657f57ffa18e053508425e1ba50c2
|
|
| BLAKE2b-256 |
53cff586d99263ca0f318c0f3a14a405ef250a1a3882170cb77e37125b8d10ec
|