Add your description here
Project description
PyIntents
pyintents
Declarative capability-based access control for Python functions.
Explore the docs »Getting Started · Basic Usage · Latest Documentation · License
📖 Overview
PyIntents brings capability-based security to Python. Functions declare what they are allowed to do via @intent decorators, and the runtime enforces these permissions at call time. Define namespaces with allow and disallow rules, propagate restrictions recursively, or selectively exempt trusted functions with without. Permissions are dynamic and layered — grant or revoke access at runtime without touching the original code. Ideal for plugin sandboxes, AI agent tool control, environment-specific security policies, and testing. Trust explicitly, fail safely. No more functions that quietly do whatever they want.
🚀 Getting Started
Installation
pip install pyintents
Quick Example
from pyintents import IntentNamespace
# Create a namespace that allows only print()
namespace = IntentNamespace(uses=[print])
@namespace.intent()
def safe_function():
print("This is allowed") # ✅
@namespace.intent()
def unsafe_function():
import os
os.system("rm -rf /") # ❌ Raises IntentViolationError
🛡️ Basic Usage
1. Allow Specific Functions
namespace = IntentNamespace(uses=[print, len])
@namespace.intent()
def my_func():
print("Hello") # Allowed
return len([1]) # Allowed
2. Recursive Enforcement
namespace = IntentNamespace(uses=[print], recursive=True)
def helper():
print("Inside helper")
@namespace.intent()
def main():
helper() # Recursively validated
3. Exempt Trusted Functions
namespace = IntentNamespace(
uses=[print, helper],
without=[helper] # Exempt from checks
)
@namespace.intent()
def main():
helper() # Called without validation
print("OK")
4. Runtime Layering
base = IntentNamespace(uses=[print])
@base.intent(uses=[len]) # Adds len to permissions
def layered_func():
print("Hi")
return len("world")
5. Explicit Denial
namespace = IntentNamespace(
uses=[print],
deny=[os.system]
)
@namespace.intent()
def restricted():
print("OK")
os.system("echo bad") # ❌ Explicitly denied
6. Local Functions
namespace = IntentNamespace(uses=[print])
def local_helper():
pass
@namespace.intent(uselocals=True)
def main():
local_helper() # Allowed (local scope)
📦 API Reference
IntentNamespace
| Parameter | Type | Description |
|---|---|---|
uses |
list[Callable] |
Allowed functions |
recursive |
bool |
Enable recursive validation (default: False) |
without |
list[Callable] |
Exempt functions from validation |
uselocals |
bool |
Allow local functions (default: False) |
deny |
list[Callable] |
Explicitly forbidden functions |
@intent() Decorator
Overrides namespace settings per function:
@namespace.intent(
uses=[print], # Override allowed functions
recursive=True, # Override recursion
without=[helper], # Override exemptions
uselocals=True, # Override local scope
deny=[os.system] # Override denials
)
def custom_func():
pass
⚠️ Exceptions
IntentViolationError
Raised when a function violates declared permissions:
from pyintents.exceptions import IntentViolationError
try:
func()
except IntentViolationError as e:
print(e) # Function 'func' calls forbidden 'os.system'
🔧 How It Works
- AST Parsing — PyIntents parses the function's source code using Python's
astmodule - Call Tree Construction — Builds a tree of all function calls up to the specified depth
- Permission Resolution — Resolves call names to actual function objects
- Rule Matching — Validates each call against:
uses— allowed functionsdeny— explicitly forbidden functionswithout— exempt functionsuselocals— local scope exceptions
- Runtime Enforcement — Validates at call time, raising
IntentViolationErroron violations
Limitations
- Source Code Required — Functions must have source code available (not built-ins or C extensions)
- Dynamic Calls — Calls via
getattr()oreval()cannot be statically analyzed - Depth Limit — Recursion depth is capped to prevent infinite loops
🎯 Use Cases
| Use Case | Description |
|---|---|
| Plugin Sandboxes | Restrict what third-party plugins can do |
| AI Agent Control | Limit tool access for LLM agents |
| Environment Policies | Enforce different rules per environment (dev/staging/prod) |
| Testing | Isolate unit tests from external dependencies |
| Security Audits | Document and enforce capability boundaries |
📄 License
Licensed under the GNU General Public License v3.0.
See LICENSE for details.
🤝 Contributing
Contributions are welcome! Feel free to open issues, submit PRs, or suggest features.
📚 Documentation
🌟 Support
If you find PyIntents useful, consider:
- ⭐ Starring the repository on GitHub
- 🐛 Reporting issues
- 💡 Suggesting features
- 📖 Improving documentation
Trust explicitly. Fail safely.
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 pyintents-0.1.0.tar.gz.
File metadata
- Download URL: pyintents-0.1.0.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30aa02f0a86f7a49b91e37e7c0e047f2c6a711420accc1b96da5acc92328339f
|
|
| MD5 |
3ee60acf094dcf4c091cbe709e020110
|
|
| BLAKE2b-256 |
671f3252abb655f4f848ff0081655cd6dd7b637033171e53970352a4664f49a5
|
File details
Details for the file pyintents-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyintents-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6d7125f0dee76d8e53b136b7873870ed27f6e335998db2bd57f26c8ab42a7e0
|
|
| MD5 |
f6696f74f1eaaf8c321d2cec30a7c55f
|
|
| BLAKE2b-256 |
2463e54425dadbbc922e8609fd040a849776b26ced411e8056601f5145435370
|