Skip to main content

Govern an AI app I'm building in Python

Surfaces used: Python SDK, framework integrations (LangChain, CrewAI, LangGraph, OpenAI Agents, PydanticAI) Modes supported: Local Hosted Hybrid Tiers: Free (baseline) Solo Teams (hosted features)

What you'll do

Wrap the dangerous parts of your Python AI app -- tool calls, external API hits, file writes -- with a single guard() check. Policy lives in a YAML file you control; the SDK returns allow/deny with a reason, and logs the decision.

Why this is the right path for you

  • If you are writing a Python app that invokes LLMs or tools and you own the code, the SDK gives you the finest-grained control.
  • If you use LangChain, CrewAI, LangGraph, OpenAI Agents, or PydanticAI, first-class integration helpers are in Integrations.
  • If you cannot change the code, use the gateway.
  • If your app is Node or Go, use the Node SDK or the Go SDK instead.

When NOT to use this approach

caution

The SDK requires you to call guard() (or use an integration wrapper) at each decision point. If you want a zero-code path that intercepts every LLM request automatically, use the gateway.

5-minute setup

pip install control-zero

Local mode (no account, policy on disk)

from controlzero import Client

cz = Client(mode="local", policy_path="./policy.yaml")

decision = cz.guard(
tool="shell",
arguments={"command": "rm -rf /"},
)

if not decision.allowed:
raise RuntimeError(f"Blocked by policy: {decision.reason}")

Minimal policy.yaml:

rules:
- id: block-shell-execute
deny: 'shell:execute'
reason: 'Destructive shell commands are not allowed.'
- id: allow-everything-else
allow: '*'
reason: 'Default-allow for everything else.'

Expected output when the rule triggers:

RuntimeError: Blocked by policy: Destructive shell commands are not allowed.

Hosted mode (policy lives in the dashboard)

import os
from controlzero import Client

cz = Client(api_key=os.environ["CONTROLZERO_API_KEY"])

decision = cz.guard(tool="web_search", arguments={"query": "..."})

Set CONTROLZERO_API_KEY=cz_live_... in your environment; policy is fetched and kept fresh automatically.

Verifying it's working

  1. Run your app and watch the audit log (Local mode) or the dashboard Audit page (Hosted).
  2. Trigger a request your policy should deny. Confirm decision.allowed == False and that the event shows up.
  3. Trigger an allowed request. Confirm decision.allowed == True and an allow audit row.

Common follow-ups

Reference