Canopy Agent Safety Runtime: policy enforcement for tool-using agents
Project description
Canopy Runtime
Minimal Agent Safety Runtime focused on a single primitive:
authorize_action(agent_ctx, action_type, action_payload) → {decision, reason, avid}
Decisions:
ALLOWDENYREQUIRE_APPROVAL
Every decision is appended to a JSONL hash-chain audit log (audit.log by default).
Audit log appends are synchronized across threads/processes using a lockfile (audit.log.lock).
REQUIRE_APPROVAL behavior
authorize_action() always returns immediately.
REQUIRE_APPROVAL means: "do not proceed without human sign-off".
The caller is responsible for implementing the approval workflow.
guard_tool() and guard_tool_http() treat REQUIRE_APPROVAL as a block (raises PermissionError).
Quickstart
pip install canopy-runtime # v0.2
from canopy import authorize_action
decision = authorize_action(
agent_ctx={"env": "production"},
action_type="execute_shell",
action_payload={"command": "rm -rf /tmp/logs"},
)
print(decision["decision"]) # DENY
print(decision["reason"]) # Denied by policy: matched /rm\s+-rf/
print(decision["avid"]) # AVID-...
An audit.log file is created automatically in the current directory.
Verify audit log integrity
Python:
from canopy.audit import HashChainAuditLog
ok = HashChainAuditLog("audit.log").verify_integrity()
CLI:
canopy-verify audit.log
Default policy pack
Works out of the box — no configuration required:
execute_shell: denies destructive patterns; requires approval for network/install commands.modify_file: denies protected paths; requires approval unless path is inagent_ctx["safe_paths"].call_external_api: requires approval.
See POLICY_COOKBOOK.md for production-ready examples.
Config
| Variable | Default | Description |
|---|---|---|
CANOPY_POLICY_FILE |
bundled default.yaml |
Path to a custom YAML policy file |
CANOPY_AUDIT_LOG_PATH |
audit.log |
Path to audit log |
Pass agent_ctx["safe_paths"] as a list to allowlist paths for modify_file:
agent_ctx = {"env": "production", "safe_paths": ["/tmp/", "/repo/"]}
Policy conditions (basic AND/OR)
Rules can be conditionally applied using when_all, when_any, and when_not.
Example: deny rm in production only:
rules:
- action_type: "execute_shell"
when_all:
- 'agent_ctx.env == "production"'
- 'payload contains "rm"'
deny_regex: 'rm\\s+-rf'
Optional HTTP gateway
pip install canopy-runtime[gateway]
CANOPY_AUDIT_LOG_PATH=/tmp/canopy_audit.log python -m uvicorn canopy.service:app --port 8010
Demo CLI
canopy-demo
canopy-demo --safe-path /tmp/
Development
git clone https://github.com/Mavericksantander/Canopy
cd Canopy
pip install -e ".[dev]"
pytest -q
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 canopy_runtime-0.2.0.tar.gz.
File metadata
- Download URL: canopy_runtime-0.2.0.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef5d8e10b412e0eb95e5274ba4acb86bcf088e537913b8cf96eb5072163ae56a
|
|
| MD5 |
8d369c9bcce6a203ec9a00eb9afe629b
|
|
| BLAKE2b-256 |
d3dc246afa64d61ec63d0131688ae10ed8f99f6fc5317b5a9d7e13a31acddffe
|
File details
Details for the file canopy_runtime-0.2.0-py3-none-any.whl.
File metadata
- Download URL: canopy_runtime-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8c357d34de0e5cbfc749a15f68f2723509c7af20e5d2e54e0b8759804f9f5f1
|
|
| MD5 |
db2ee4af5d1a8dc9e4a35271d572e5d5
|
|
| BLAKE2b-256 |
d99eb02cfd91edcc92d25fd0e0d4af108377b7ab591fd3d844e23c3725e474a3
|