Python SDK
Supported modes: Hosted Hybrid Local Available in: Free Solo Teams
If you are not changing your application code, the gateway proxy gives you governance with zero code changes. If you are governing developer AI tools (Claude Code, Cursor, Codex CLI), use coding hooks instead.
The Control Zero Python SDK provides policy enforcement for AI agents running in Python environments.
Installation
pip install controlzero
Requirements:
- Python 3.9 or later
- No additional system dependencies
Quickstart
Choose your deployment mode:
- Hosted
- Hybrid
- Local
Hosted Policy pulled from dashboard. Audit in cloud. Recommended for most teams.
from controlzero import Client
# SDK fetches your signed policy bundle on first call.
# Manages audit automatically. No local config needed.
client = Client(api_key="cz_live_your_api_key_here")
# Or use env var: export CONTROLZERO_API_KEY="cz_live_..."
Install: pip install controlzero (cloud mode dependencies ship in the base install as of 1.4.3).
Hybrid API key plus a local policy file. When you pass policy or policy_file explicitly to Client() alongside an api_key, your local policy governs enforcement and the hosted/dashboard bundle is IGNORED for that instance -- audit still ships to your dashboard. The SDK prints a one-time warning so the choice is visible (pass strict_hosted=True to raise HybridModeError instead). CONTROLZERO_LOCAL_OVERRIDE does not apply to this explicit-argument case; it only affects auto-discovery (an api_key is set and you do NOT pass policy/policy_file, but a local file is found via CONTROLZERO_POLICY_FILE or controlzero.yaml/.yml/.json in the working directory), where the hosted bundle wins by default and CONTROLZERO_LOCAL_OVERRIDE=1 flips to the discovered local file.
from controlzero import Client
# Your local file governs enforcement; the hosted bundle is ignored.
client = Client(
api_key="cz_live_your_api_key_here",
policy_file="controlzero.yaml",
)
# The local file already governs enforcement; the API key only routes audit to the dashboard.
Your local policy governs enforcement; the API key only routes audit to the dashboard. The SDK prints a one-time warning noting the dashboard policy is ignored for this instance (or raises HybridModeError if you set strict_hosted=True).
Local No API key. No network calls. Fully offline. Air-gap compatible.
from controlzero import Client
# Inline policy -- no file needed
client = Client(policy={
"rules": [
{"allow": "database:query", "reason": "Reads are permitted"},
{"deny": "database:execute", "reason": "Writes are blocked"},
]
})
# Or from a file
client = Client(policy_file="controlzero.yaml")
Audit written to ./controlzero.log.
Configuration
Hosted Hosted Mode (Recommended)
Pass only your project API key. The SDK pulls the signed policy bundle from the dashboard at first call, verifies its signature, decrypts locally, and enforces every call against the dashboard policy. Audit entries ship to the remote trail automatically.
from controlzero import Client
client = Client(api_key="cz_live_your_api_key_here")
Local With a Local Policy File
from controlzero import Client
client = Client(policy_file="controlzero.yaml")
Hybrid Hybrid Mode (API Key + Local Policy)
from controlzero import Client
# Explicit policy_file + api_key: the local file governs enforcement,
# the hosted bundle is IGNORED, audit still ships remotely.
client = Client(api_key="cz_live_your_api_key_here", policy_file="controlzero.yaml")
Inline Policy
from controlzero import Client
client = Client(policy={
"rules": [
{"allow": "database:query", "reason": "Reads are permitted"},
{"deny": "database:*", "reason": "All other database operations are blocked"},
]
})
database:query, database:execute, and database:delete are legacy action names that match the same calls as the canonical database:read, database:write, and database:admin classes. New policies should prefer the canonical names; existing rules with the legacy names continue to work without changes. See Read-only database recipe for the SQL semantic class mapping.