クイックスタート
対応モード: Hosted Hybrid Local 利用可能なプラン: Free Solo Teams
5 分足らずで、エージェントに AI ガバナンスを追加できます。デプロイ方法は 2 通りあります。状況に合うほうを選んでください。
| 方法 | 適したケース | コード変更 |
|---|---|---|
| ゲートウェイ(オプション A) | 既存のエージェント、素早い導入 | なし。URL を 1 つ変更するだけ |
| SDK(オプション B) | 新規のエージェント、最も緊密な統合 | パッケージをインストールし、ツール呼び出しをラップ |
どちらも、ダッシュボードで定義した同じポリシーを適用します。
ステップ 1: サインアップ
- app.controlzero.ai にアクセスして、アカウントを作成します。
- まず試してみたい場合は、app.controlzero.ai/demo のインタラクティブなデモをお試しください。アカウントは不要です。
無料プランには、月 5,000 件のガバナンス対象アクションが含まれ、クレジットカードは不要です。
ステップ 2: プロジェクトを作成する
- サインイン後、2 ステップのオンボーディングで最初のプロジェクトを作成します。
- プロジェクトに名前を付け(例:
my-agent)、環境を選択します。 - プロジェクトの設定ページから API Key をコピーします(例:
cz_live_abc123...)。
環境変数として設定します。
export CONTROLZERO_API_KEY="cz_live_your_key_here"
ステップ 3: ダッシュボードでポリシーを定義する
ポリシーは組織レベルの Policy Library に置かれ、プロジェクトにアタッチします。これにより、1 つのポリシーで多数のプロジェクトを統制しつつ、プロジェクトごとに上書きすることもできます。
3a. ライブラリポリシーを作成する
サイドバーの Library をクリックし、続けて New policy をクリックします。
- Name:
db-read-only - Description: エージェントはデータベースにクエリできますが、データを変更することはできません。
- Rules (JSON array): 以下のスニペットを貼り付けるか、Insert sample をクリックします。
[
{ "effect": "allow", "actions": ["database:read"], "resources": ["*"] },
{ "effect": "deny", "actions": ["database:write"], "resources": ["*"] },
{ "effect": "deny", "actions": ["database:admin"], "resources": ["*"] }
]
Create & publish v1 をクリックします。ポリシーは保存され、バージョン 1 として自動的に公開されるため、すぐにアタッチできます。
actions、resources、principals は配列です。作成ダイアログは、古いドキュメントにある単数形のフラットな action / resource 形式も受け付け、自動的に正規化します。
database:read は、SELECT、EXPLAIN、SHOW、DESCRIBE、CTE の各ステートメントを、方言ごとのキーワードの綴りに関係なくカバーする、移植性のある正規クラスです。database:write は INSERT/UPDATE/DELETE/MERGE など、データを変更するステートメントをカバーします。database:admin はスキーマや権限の変更をカバーします。SELECT 1; DROP TABLE x のような複数ステートメントの便乗は database:admin として解決されるため、deny: database:admin ルールが、公開済みのすべてのバージョンでそれを捕捉します。許可のみの形(明示的な deny ルールなし)では、method を渡したときに破壊的な SQL を正しくブロックするために controlzero 1.13.13+ が必要です。以前のバージョンでは、引数から導出されたクラスが参照される前に、メソッドから導出されたクラスが allow ルールを満たしてしまうことがあったため、許可されていました。より細かく制御したい場合は、特定のキーワード(例: database:DROP)を対象にすることもできます。対応表の全体はCanonical Tool Namesを参照してください。
3b. ポリシーをプロジェクトにアタッチする
プロジェクトを開き、Attach policy をクリックして db-read-only を選び、状態は Active のままにして確定します。これでプロジェクトのポリシーバンドルがルールを適用します。クライアントは次回のリフレッシュ時にそれらを取り込みます。Python SDK はデフォルトで 60 秒ごと、Node SDK は 300 秒ごとにポーリングします。
ステップ 4: エージェントを統合する
オプション A: ゲートウェイ(コード変更なし)
ゲートウェイは透過的なプロキシです。LLM のベース URL をゲートウェイに向け、ヘッダーを 2 つ追加します。既存のエージェントのコードはそのまま動作します。
英語の原文 -- 翻訳は技術レビュー待ちです
The gateway enforces policies on every request and response automatically.
1. ベース URL を変更する
Anthropic(Claude):
# Before
ANTHROPIC_BASE_URL=https://api.anthropic.com
# After
ANTHROPIC_BASE_URL=https://gateway.controlzero.ai
OpenAI:
# Before
OPENAI_BASE_URL=https://api.openai.com
# After
OPENAI_BASE_URL=https://gateway.controlzero.ai/v1
2. Control Zero のヘッダーを追加する
すべての LLM リクエストに、次のヘッダーを追加します。
X-ControlZero-API-Key: cz_live_your_key_here
X-ControlZero-Agent-ID: my-first-agent
X-ControlZero-API-Key(必須)は、ダッシュボードのプロジェクトキーです。X-ControlZero-Agent-ID(任意)は、監査上の帰属のために呼び出し元にラベルを付けます。省略した場合は<provider>-directになります。
3. 試してみる(Anthropic)
curl -X POST https://gateway.controlzero.ai/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "X-ControlZero-API-Key: $CONTROLZERO_API_KEY" \
-H "X-ControlZero-Agent-ID: my-first-agent" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 100,
"messages": [{"role": "user", "content": "What is 2+2?"}]
}'
Anthropic の API キー(x-api-key)は Anthropic での認証に使われます。Control Zero の API キー(X-ControlZero-API-Key)は、ガバナンス、監査ログ、ポリシーの適用を有効にします。どちらも必須です。
以上です。ゲートウェイはすべての LLM レスポンスをインターセプトし、ツール呼び出しをポリシーに照らして評価し、許可されていないアクションをブロックします。事前チェック(モデルのブロック、コスト上限、PII 検出)は、リクエストがプロバイダーに届く前に、すべてのリクエストで実行されます。
セルフホストでのデプロイ、対応プロバイダー、設定の詳細は、ゲートウェイガイドを参照してください。
オプション B: SDK 統合
SDK をインストールして、アプリケーションレベルでツール呼び出しを統制します。
英語の原文 -- 翻訳は技術レビュー待ちです
With an API key the SDK pulls your signed policy bundle from the dashboard automatically -- no local policy file required.
ツールを実行する前に guard() を呼び出してください。
1. SDK をインストールする
Python:
pip install controlzero
要件: Python 3.9 以降。
Node.js:
@controlzero パッケージは Control Zero のレジストリから提供されます。.npmrc(プロジェクトレベルまたはユーザーレベル)で、スコープをそのレジストリに 1 回だけ向けてください。
@controlzero:registry=https://npm.controlzero.ai
そのうえでインストールします。
npm install @controlzero/sdk
@controlzero スコープ外の依存関係は、引き続き npmjs.org から解決されます。
2. AI アプリにガバナンスを追加する(Hosted モード)
Python:
from controlzero import Client
# SDK pulls your dashboard policy on first call. Signed bundle, verified
# locally. Audit streams to the dashboard trail.
cz = Client(api_key="cz_live_your_key_here")
# Policies are managed in app.controlzero.ai, not in code. The SDK
# derives the SQL semantic class (read|write|admin|exec) from the
# `sql` argument, so a `database:read` rule fires for SELECT,
# EXPLAIN, SHOW, and CTE statements regardless of dialect.
result = cz.guard("database", method="SELECT", args={"sql": "SELECT id FROM orders"})
print(result.decision) # "allow" or "deny" per dashboard rules
result = cz.guard("database", method="DROP", args={"sql": "DROP TABLE orders"})
print(result.decision) # typically "deny" (matches database:admin)
print(result.reason)
# Or raise on deny:
from controlzero import PolicyDeniedError
try:
cz.guard("database", method="DROP", args={"sql": "DROP TABLE orders"}, raise_on_deny=True)
except PolicyDeniedError as e:
print(f"Blocked: {e.decision.reason}")
cz.close()
Node.js:
import { Client } from '@controlzero/sdk';
// Hosted mode uses the async factory. The SDK pulls your dashboard
// policy on first call, verifies signature, decrypts, and enforces.
const cz = await Client.create({ apiKey: 'cz_live_your_key_here' });
const result = cz.guard('database', {
method: 'SELECT',
args: { sql: 'SELECT id FROM orders' },
});
console.log(result.decision); // "allow" or "deny"
await cz.close();
2 つのモード、1 つのクライアント:
-
英語の原文 -- 翻訳は技術レビュー待ちです
Hosted mode (
api_key=...): the SDK pulls the signed policy bundle from the dashboard, verifies and decrypts it locally, and ships audit to the remote trail. Keys and bundles are cached under~/.controlzero/cache/so restarts work offline. This is the recommended flow -- policies live where your team can manage them. -
英語の原文 -- 翻訳は技術レビュー待ちです
Local mode (
policy=...orpolicy_file=...): zero network for policy eval. Audit stays in a rotating local file.エアギャップ環境でのデプロイや、リポジトリにチェックインした
controlzero.yamlに適しています。
guard() メソッドは、decision("allow" または "deny")と reason のフィールドを持つ PolicyDecision を返します。deny の判定を返す代わりに PolicyDeniedError を発生させるには、raise_on_deny=True を渡します。
呼び出しがブロックされたときの動作
guard() の呼び出しが deny の判定を返した場合は、結果を確認するか、例外を発生させることができます。
from controlzero import Client, PolicyDeniedError
cz = Client(api_key="cz_live_your_key")
# Check the decision object. Note: `database:execute` is a legacy action
# name. The canonical name is `database:write`; both forms match the
# same calls.
result = cz.guard("database", method="execute", args={"sql": "DROP TABLE orders"})
if result.effect == "deny":
print(f"Blocked: {result.reason}")
# result.effect = "deny"
# result.reason = human-readable explanation
# result.policy_id = which policy matched
# Or raise on deny
try:
cz.guard("database", method="execute", args={"sql": "DROP TABLE orders"}, raise_on_deny=True)
except PolicyDeniedError as e:
print(f"Blocked by policy {e.decision.policy_id}: {e.decision.reason}")
ステップ 5: コンテキストマネージャーを使う(任意)
Client はコンテキストマネージャープロトコルをサポートしており、終了時に close() を呼び出して監査ログをフラッシュします。
from controlzero import Client, PolicyDeniedError
with Client(policy_file="./controlzero.yaml") as cz:
result = cz.guard(
"filesystem",
{"path": "/data/report.csv"},
method="read_file",
context={"resource": "/data/report.csv"},
)
if result.denied:
print(f"Access denied: {result.reason}")
else:
print(f"Allowed: {result.reason}")
ガバナンスの総合シナリオ
次のエンドツーエンドの例は、データベースから読み取り、許可されていない書き込みを試みる現実的なエージェントを示します。書き込みは、ツールが呼び出される前にポリシーによってブロックされます。
from controlzero import Client
policy = {
"rules": [
{"allow": "database:read", "reason": "Reads are permitted"},
{"deny": "database:*", "reason": "All other database operations are blocked"},
]
}
def run_analyst_agent(cz: Client) -> None:
# Step 1: check if read is allowed. The SDK derives the SQL
# semantic class (read) from the `sql` argument, so the
# `database:read` rule fires.
read_decision = cz.guard(
"database",
{"sql": "SELECT * FROM orders WHERE region = 'APAC'"},
method="SELECT",
)
print(f"Read decision: {read_decision.decision} - {read_decision.reason}")
# Step 2: check if write is allowed (it will be denied; class is `write`)
write_decision = cz.guard(
"database",
{"sql": "UPDATE orders SET status = 'processed' WHERE region = 'APAC'"},
method="UPDATE",
)
print(f"Write decision: {write_decision.decision} - {write_decision.reason}")
with Client(policy=policy) as cz:
run_analyst_agent(cz)
期待される出力:
Read decision: allow - Reads are permitted
Write decision: deny - All other database operations are blocked
監査ログを見る
英語の原文 -- 翻訳は技術レビュー待ちです
Every guard() decision, allowed or denied, is automatically logged.
ダッシュボードでプロジェクトに移動し、Audit Log をクリックすると、次の内容が表示されます。
英語の原文 -- 翻訳は技術レビュー待ちです
This is a complete decision trail, not a sample. Each entry records coverage for that event, so “did not run” is distinguishable from “ran and found nothing.”
| タイムスタンプ | ツール | メソッド | 判定 | エージェント |
|---|---|---|---|---|
| 12:00:01 | database | SELECT | allow | agent-analyst |
| 12:00:02 | database | UPDATE | deny | agent-analyst |
SDK リファレンス: 主なメソッド
Client.__init__()
def __init__(
self,
api_key: str = None, # optional, for hosted mode (cz_live_ or cz_test_)
policy: dict = None, # inline policy dict with "rules" key
policy_file: str = None, # path to controlzero.yaml policy file
strict_hosted: bool = False, # raise on hybrid (API key + local policy) instead of warn
log_path: str = "./controlzero.log", # local audit log path
log_rotation: str = "daily", # audit log rotation interval
log_retention: str = "30 days", # how long to keep rotated logs
log_compression: str = None, # compress rotated logs (e.g. "gz")
log_format: str = "json", # audit log format
): ...
ポリシーの解決順序: policy= 引数、policy_file= 引数、CONTROLZERO_POLICY_FILE 環境変数、次にカレントディレクトリで最初に自動検出されたファイル(controlzero.yaml、次に controlzero.yml、次に controlzero.json -- 最初に存在したものが優先)、次に CONTROLZERO_API_KEY 環境変数(Hosted モード)、最後に何もしないパススルーです。ポリ シーファイルは YAML でも JSON でもよく、どちらも同一のスキーマを使います。
Client.guard(tool, args, method, raise_on_deny, context)
ロードされたポリシーに照らして、ツール呼び出しを評価します。decision("allow" または "deny")、reason、policy_id のフィールドを持つ PolicyDecision を返します。評価されるアクション文字列は "{tool}:{method}" です。
raise_on_deny=True を渡すと、deny の判定を返す代わりに PolicyDeniedError を発生させます。
Client.close()
バッファされた監査ログをフラッシュし、開いている接続をすべて閉じます。
PolicyDeniedError
raise_on_deny=True でポリシーがアクションを拒否したときに、guard() によって発生します。
| 属性 | 型 | 説明 |
|---|---|---|
e.decision.effect | str | 常に "deny"。 |
e.decision.reason | str | 人が読める説明。 |
e.decision.policy_id | str | 一致したポリシーの ID。なければ None。 |
デバッグ
CZ_DEBUG=1 を設定すると、stderr に詳細なデバッグ出力が有効になります。すべてのポリシー評価、キャッシュのヒット/ミス、監査ログのフラッシュが出力され、ガバナンスの問題の診断に役立ちます。
CZ_DEBUG=1 python my_agent.py
デバッグ出力のサンプル:
[CZ DEBUG] initialized client agent=my-agent project=proj_abc123
[CZ DEBUG] policy_eval tool=database method=SELECT action=database:SELECT class=database:read effect=allow policy_id=db-read-only latency_ms=0.12
[CZ DEBUG] policy_eval tool=database method=UPDATE action=database:UPDATE class=database:write effect=deny policy_id=db-read-only latency_ms=0.08
[CZ DEBUG] audit_flush count=2 status=ok
latency_ms フィールドは、ポリシー評価にかかった時間を示します。
英語の原文 -- 翻訳は技術レビュー待ちです
Policy evaluation is local and does not make network requests.
次のステップ
-
ゲートウェイプロキシ: セルフホストでのデプロイ、対応するすべてのプロバイダー、設定リファレンス。
-
ポリシー: ポリシーの書き方を学びます: ワイルドカード、条件、評価順序。
-
MCP サーバー: AI コーディングクライアントからガバナンスを管理します。
-
MCP ツール呼び出しの統制: MCP サーバーとツールへのアクセスを統制します。
-
英語の原文 -- 翻訳は技術レビュー待ちです
Secrets Management: Store provider keys in the encrypted vault.
-
SDK リファレンス: Python: Python SDK の完全なドキュメント。