メインコンテンツまでスキップ
このページは機械翻訳であり、十分なレビューを経ていません。英語の原文が正となります。セキュリティ、プライバシー、データの取り扱い、コンプライアンス、ライセンスに関する記述は、技術レビューが完了するまで英語のまま掲載しています。 英語の原文を読む

ポリシー

英語の原文 -- 翻訳は技術レビュー待ちです

Supported modes: Hosted Hybrid Local Available in: Free Solo Teams (audit retention is a configured window by tier: Free 7 days, Solo 90 days, Teams 365 days, see Feature Availability)

ポリシーは、AI エージェントが「できること」と「できないこと」を定めるルールです。このページでは、ポリシーの作り方、SDK 呼び出しとの結び付き、評価順序、ワイルドカード、条件、暗号化、キャッシュまで、すべてを取り上げます。

基本概念​

ポリシーは、名前を付けたルールの集合です。各ルールは、「エージェントがリソース Y に対してアクション X を実行しようとしたとき、答えは allow または deny である」と定めます。

{
"name": "my-policy",
"rules": [
{
"effect": "allow",
"action": "llm:generate",
"resource": "model/gpt-4"
}
]
}

SDK のコードが cz.guard("llm", method="generate", args={"model": "gpt-5.4"}) を呼び出すと、SDK はこのルールを見つけ、エフェクトが allow であることを確認して、アクションの実行を許可します。

アクション文字列の形式: ポリシールール内のアクション文字列は、コロン区切りの形式(tool:method)を使います。SDK 呼び出しでは tool と method を別々のパラメーターとして渡し、tool:method としてマッチングされます。例: llm:generate、tool:call、data:read、api:request。

SDK 呼び出しがポリシールールに対応する仕組み​

これが、理解すべき最も重要な点です。guard() 呼び出しは、ツール名とメソッドをポリシーのアクションに、args をポリシーの条件に対応付けます。

SDK call: Policy rule:
cz.guard( {
"llm", "action": "llm:generate",
method="generate", --> "resource": "model/gpt-5.4",
args={ --> "conditions": {
"model": "gpt-5.4", "agent_id": "agent-*"
"agent_id": "agent-001", },
}, "effect": "allow"
) }
  • ツール名とメソッドが、ポリシーのアクション文字列になります(例: "llm" + "generate" = "llm:generate")。
  • args ディクショナリは、ルールの conditions オブジェクト(存在する場合)に対してマッチングされます。
  • すべてのフィールドが一致すれば、ルールの effect が結果を決めます。

ポリシーを作る: ステップごとの手順​

ステップ 1: アクションを選ぶ​

アクションは、エージェントが何をしようとしているかを表します。命名規則は自分で定義します。一般的なパターンは次のとおりです。

アクション意味使用する場面
llm:generateテキスト生成のために LLM を呼び出すchat.completions.create() や messages.create() の呼び出しの前
llm:embedエンベディングを生成するembeddings.create() の呼び出しの前
tool:callツールや関数を呼び出すLLM が要求したツールを実行する前
mcp.tool:callMCP ツールを呼び出すMCP プロトコル経由でツールを呼び出す前
mcp.resource:readMCP リソースを読み取るMCP 経由でデータを読み取る前
data:readデータソースから読み取るデータベースやベクトルストアにクエリする前
data:writeデータソースに書き込むデータを挿入または更新する前
file:readファイルを読み取るディスク上のファイルにアクセスする前
file:writeファイルを書き込むファイルを書き込みまたは変更する前
api:request外向きの HTTP リクエストを行う外部 API を呼び出す前
*すべてのアクションキャッチオールのルール

独自のアクション名を作ることもできます。これらは単なる文字列です。SDK とポリシールールは同じ文字列を使い、それによって両者が結び付きます。

ステップ 2: リソースを選ぶ​

リソースは、アクションの対象を表します。命名規則は自分で定義します。

リソースのパターン対象SDK 呼び出しの例
model/gpt-5.4特定の LLM モデルguard("llm", method="generate", context={"resource": "model/gpt-5.4"})
model/claude-*すべての Claude モデル(ワイルドカード)guard("llm", method="generate", context={"resource": "model/claude-sonnet-4-6"})
tool/search_web特定のツールguard("tool", method="call", context={"resource": "tool/search_web"})
mcp://filesystem/read_file特定の MCP ツールguard("mcp.tool", method="call", context={"resource": "mcp://filesystem/read_file"})
mcp://filesystem/*MCP サーバー上のすべてのツールfilesystem サーバー上のあらゆるツールに一致します
vectorstore/documentsデータコレクションguard("data", method="read", context={"resource": "vectorstore/documents"})
https://api.example.com/*API エンドポイントguard("api", method="request", context={"resource": "https://api.example.com/v1/users"})
*すべてのリソースキャッチオール

ステップ 3: エフェクトを設定する​

各ルールには effect があり、allow または deny のいずれかです。

[
{ "effect": "allow", "action": "llm:generate", "resource": "model/gpt-5.4" },
{ "effect": "deny", "action": "llm:generate", "resource": "model/gpt-4*" }
]

ステップ 4: 条件を追加する(任意)​

条件を使うと、SDK から渡される実行時の値に基づいてルールを絞り込めます。条件はローカルのポリシーエンフォーサー(Python、Node、Go)に実装されているため、Hosted モードでも Local のみのモードでも動作します。

{
"effect": "allow",
"action": "llm:generate",
"resource": "model/gpt-4",
"conditions": {
"agent_id": "support-*",
"environment": "production"
}
}

マッチングの詳しい仕様については、下の専用の条件セクションを参照してください。

検証​

ポリシーバージョンを公開または保存するとき、プラットフォームはすべてのルールのすべての actions[*] エントリを、正規のアクションセットとエイリアステーブル(正規ツール名を参照)に照らして検証します。不明なアクション(タイプミス、でたらめな名前)を対象とするルールは、did_you_mean の候補リストを伴う 422 validation_failed レスポンスで拒否されます。これにより、「ルールは登録されたのに一度も発火しない」という無言のバグが、本番に出荷された後ではなく、作成時に検出されます。

ルールが database:queryy(タイプミス)を対象としている場合のレスポンス例:

{
"error": "validation_failed",
"unknown_actions": ["database:queryy"],
"suggestions": {
"database:queryy": ["database:query (legacy)"]
}
}

ダッシュボードのルールエディターは、問題のあるルールを赤い枠で表示し、候補ごとに「database:query を使用」というワンクリックのボタンを表示します。(legacy) と付いた候補は、正規化前のルール向けのエイリアスシムに由来します。タグのない候補は、現行の正規クラスです(新しいルールにはこちらを優先してください)。

SDK は、ポリシーの読み込み時に同じバリデーターを警告として実行するため、ローカルポリシーモード(プラットフォームバックエンドなし)のユーザーもタイプミスに気付けます。SDK の警告はブロックしません。ポリシーは引き続き読み込まれるため、SDK がまだ認識していないカスタムツールを使うお客様は作業を続けられ、本物のタイプミスについては did-you-mean が表示されます。

バリデーターが既知とするアクションの集合は、正規の SDK エクストラクターのツール、ホストツールのエイリアス(例: Read は file_read に解決されます)、4つの正規 SQL セマンティッククラス(database:read|write|admin|exec)、すべてのレガシー SQL エイリアス(database:query、database:SELECT、database:DROP など)、ワイルドカード(*、tool:*、*:method)の和集合です。SDK のエイリアステーブルを更新すると、バリデーターが受け入れる範囲は自動的に広がります。

ルールフィールドのリファレンス​

フィールド型必須説明
effect"allow" または "deny"はいルールがアクションを許可するかブロックするか
actionstringはいマッチさせるアクション。ワイルドカード(*)に対応
resourcestringはいマッチさせるリソース。ワイルドカード(*)に対応
conditionsobjectいいえリクエストのコンテキストにすべて一致する必要があるキーと値のペア。値は glob パターンに対応
clientslist of stringsいいえルールを特定の AI クライアント(cursor、claude-code、gemini-cli、codex-cli、windsurf、python-sdk など)に限定します。空または未指定の場合は、すべてのクライアントに一致します。glob パターンに対応。#175 で追加。
projectslist of stringsいいえルールを特定のプロジェクト ID に限定します。空または未指定の場合は、すべてのプロジェクトに一致します。glob パターンに対応。#175 で追加。

セレクターの意味論(clients / projects)​

空でない clients リストを持つルールは、リクエストで検出されたクライアント名がいずれかのエントリに一致しない限り、スキップされます。projects も同様です。両方のセレクターが、リクエストを明示的に選び取る必要があります。空の client_name は clients: ["cursor"] に一致しません。first-match-wins は引き続き適用されます。暗黙の「最も具体的なものが優先」という並べ替えはありません。優先順位は、より具体的なルールをより一般的なルールの前に書くことで表現します。

rules:
- allow: delete_* # cursor-only override fires first
clients: ['cursor']
- deny: delete_* # global default applies to everything else

glob 構文の注意: clients / projects の glob 対応は、action / resource のルールと同じです。Rust と Go では *、prefix*、*suffix、Python では加えて ? と [seq](fnmatch.fnmatchcase 経由)が使えます。これは SDK 間で以前から存在する挙動のクラスで、アクションとリソースにも当てはまります。移植性のために、最も共通性の高い構文(完全一致、prefix*、*suffix)に絞ることをお勧めします。

ワイルドカード​

action と resource の両方のフィールドが、glob 形式のワイルドカードに対応しています。

[
{ "action": "llm:*", "resource": "*" },
{ "action": "mcp.tool:call", "resource": "mcp://filesystem/*" },
{ "action": "*", "resource": "*" }
]
パターン一致するもの一致しないもの
model/gpt-5.4model/gpt-5.4 のみmodel/gpt-5.4-mini
model/gpt-5.4*model/gpt-5.4、model/gpt-5.4-minimodel/gpt-4-turbo
model/*任意のモデルtool/search_web
mcp://filesystem/*mcp://filesystem/read_file、mcp://filesystem/write_filemcp://github/create_issue
*すべて(すべてに一致)

条件​

条件は、実行時にすべて一致する必要がある、キーと glob パターンのペアでルールを絞り込みます。条件は、すべての SDK(Python と Node)のローカルエンフォーサーによって、Hosted でも Local のみのモードでも評価されます。サーバーへの往復はありません。

各条件が照合する対象​

ルールに conditions: { key: pattern, ... } がある場合、エンフォーサーは guard 呼び出しのマージしたビューを作り、各 key をそのビューに対してテストします。マージの規則は次のとおりです。

  1. 呼び出しの args ディクショナリから始めます。
  2. その上に context を重ねます(キーが衝突した場合は context が優先されます)。
  3. context["tags"] がマッピングの場合は、context と同じ優先度でトップレベルに展開します。
  4. 各条件の値は glob(* ワイルドカード)です。key の値が glob に一致すれば、その条件は成立します。すべての条件が成立する必要があります。

実際上は、args、トップレベルの context、入れ子になった context["tags"] のいずれからでも条件を駆動できます。呼び出し側にとって最も自然なものを選んでください。

例: プロバイダーのタグ(簡易ラッパーのパターン)​

- effect: allow
action: 'llm:generate'
conditions:
provider: 'openai'

このルールは、次のいずれかの呼び出しが行われた場合に一致します。

# via top-level context (direct guard)
cz.guard("llm", method="generate", context={"provider": "openai"})

# via nested tags (simplified wrapper populates tags)
cz.guard("llm", method="generate", context={"tags": {"provider": "openai"}})

# via args (some integrations put it there)
cz.guard("llm", method="generate", args={"provider": "openai"})

例: エージェント + 環境​

{
"effect": "allow",
"action": "llm:generate",
"conditions": {
"agent_id": "support-*",
"environment": "production"
}
}
cz.guard(
"llm",
method="generate",
context={
"agent_id": "support-agent-1", # matches "support-*"
"environment": "production", # matches "production"
},
)

例: 入れ子のタグ​

ラッパーがタグ(プロバイダー、モデルファミリー、コスト階層)で呼び出しを分類する場合、条件はそれらのタグを、トップレベルにあるかのようにマッチングできます。

{ "effect": "deny", "action": "llm:generate", "conditions": { "cost_tier": "premium" } }
cz.guard(
"llm",
method="generate",
context={"tags": {"cost_tier": "premium", "provider": "openai"}},
)
# Denied: conditions.cost_tier matches tags.cost_tier after flattening.

ポリシーの評価順序​

複数のルールが同じ guard() 呼び出しに一致しうる場合、Control Zero は次の優先順位を適用します。

3つの規則:

  1. 明示的な deny が常に優先されます。 いずれかの deny ルールが一致すれば、allow ルールも一致していたとしても、アクションはブロックされます。

  2. より具体的なルールが、より広いルールより優先されます。 model/gpt-4 のルールは、model/* のルールに勝ちます。

  3. 一致なし = deny(デフォルト)。 アクションとリソースに一致するルールがない場合、アクションは拒否されます。

    英語の原文 -- 翻訳は技術レビュー待ちです

    This is the secure-by-default allow-list posture, and it is the default. It is also a knob: the settings.default_action field controls the no-match path and can be set to deny (allow-list, the default), warn (log-and-proceed, for discovery rollouts), or allow (deny-list -- allow unmatched calls and block only the tools you explicitly deny:).

    完全な仕様は適用の動作を、コピーして使える default_action: allow のポリシーは拒否リストのレシピを参照してください。

例: 実際の評価​

次のポリシーがあるとします。

{
"rules": [
{ "effect": "allow", "action": "llm:generate", "resource": "model/*" },
{ "effect": "deny", "action": "llm:generate", "resource": "model/gpt-4*" }
]
}
SDK 呼び出しルール 1 に一致?ルール 2 に一致?結果
guard("llm:generate", "model/gpt-4")はい(allow)いいえALLOWED
guard("llm:generate", "model/gpt-3.5-turbo")はい(allow)いいえALLOWED
guard("llm:generate", "model/gpt-4-turbo")はい(allow)はい(deny)DENIED(deny が優先)
guard("tool:call", "tool/search")いいえいいえDENIED(一致なし = deny)

ポリシーの完全な例​

例 1: モデルのガバナンス​

特定のモデルを許可し、それ以外はすべて拒否します。

{
"name": "model-governance",
"description": "Only approved models can be used",
"rules": [
{
"effect": "allow",
"action": "llm:generate",
"resource": "model/gpt-5.4"
},
{
"effect": "allow",
"action": "llm:generate",
"resource": "model/claude-sonnet-4-6"
},
{
"effect": "deny",
"action": "llm:generate",
"resource": "model/*"
}
]
}

最後のルールはキャッチオールとして働き、明示的に許可されていないモデルはすべて拒否されます。

コードでは:

cz.guard("llm", method="generate", context={"resource": "model/gpt-5.4"}) # ALLOWED
cz.guard("llm", method="generate", context={"resource": "model/claude-sonnet-4-6"}) # ALLOWED
cz.guard("llm", method="generate", context={"resource": "model/gpt-4o"}) # DENIED (catch-all)

例 2: MCP ツールの制御​

エージェントが呼び出せる MCP ツールを制御します。

{
"name": "mcp-tool-control",
"description": "Restrict MCP tool access per agent",
"rules": [
{
"effect": "allow",
"action": "mcp.tool:call",
"resource": "mcp://filesystem/read_file",
"conditions": { "agent_id": "analyst-*" }
},
{
"effect": "deny",
"action": "mcp.tool:call",
"resource": "mcp://filesystem/write_file"
},
{
"effect": "allow",
"action": "mcp.tool:call",
"resource": "mcp://github/*",
"conditions": { "agent_id": "dev-agent" }
},
{
"effect": "deny",
"action": "mcp.tool:call",
"resource": "mcp://*"
}
]
}

コードでは:

# Analyst agent reading a file: ALLOWED (rule 1 matches)
cz.guard(
"mcp.tool",
method="call",
context={"resource": "mcp://filesystem/read_file", "agent_id": "analyst-42"},
)

# Any agent writing a file: DENIED (rule 2 matches)
cz.guard(
"mcp.tool",
method="call",
context={"resource": "mcp://filesystem/write_file", "agent_id": "analyst-42"},
)

# Dev agent using GitHub: ALLOWED (rule 3 matches)
cz.guard(
"mcp.tool",
method="call",
context={"resource": "mcp://github/create_issue", "agent_id": "dev-agent"},
)

# Unknown MCP tool: DENIED (rule 4 catch-all)
cz.guard(
"mcp.tool",
method="call",
context={"resource": "mcp://slack/send_message", "agent_id": "analyst-42"},
)

例 3: 多層の本番ポリシー​

モデルのガバナンス、ツールの制御、データアクセス、API の制限を組み合わせたポリシーです。

{
"name": "production-agent-policy",
"description": "Full governance for production AI agents",
"rules": [
{
"effect": "allow",
"action": "llm:generate",
"resource": "model/gpt-4",
"conditions": { "environment": "production" }
},
{
"effect": "allow",
"action": "tool:call",
"resource": "tool/search_web"
},
{
"effect": "deny",
"action": "tool:call",
"resource": "tool/execute_code"
},
{
"effect": "allow",
"action": "data:read",
"resource": "vectorstore/public-docs"
},
{
"effect": "deny",
"action": "data:read",
"resource": "vectorstore/internal-*"
},
{
"effect": "allow",
"action": "api:request",
"resource": "https://api.internal.example.com/*"
},
{
"effect": "deny",
"action": "api:request",
"resource": "https://*.external.example.com/*"
},
{
"effect": "deny",
"action": "*",
"resource": "*"
}
]
}

最後のルールはグローバルなキャッチオールで、明示的に許可されていないものはすべて拒否されます。

ポリシーバンドル​

ポリシーは、SDK に個別には送られません。代わりに、プロジェクトのすべての有効なポリシーが、1つのポリシーバンドルにコンパイルされます。

バンドルの仕組み​

ダッシュボードでポリシーを公開すると、Control Zero はそれらを1つのバンドルとして SDK に配信します。新しいポリシーは、約1分以内に、または手動更新で即座に、エージェントで有効になります。

バンドルのセキュリティ​

英語の原文 -- 翻訳は技術レビュー待ちです

Every policy bundle is signed. The SDK verifies the signature before use, detects tampering, and rejects an invalid bundle. If this happens on a background refresh, it keeps enforcing the last known good policy; if it happens at startup, there is no verified policy to fall back to and calls are denied. A modified bundle cannot silently change enforcement either way.

ローカルキャッシュ​

SDK は現在のバンドルをディスクにキャッシュします。これにより、次のことが可能になります。

  • 英語の原文 -- 翻訳は技術レビュー待ちです

    Offline enforcement: If the SDK cannot reach the server, it enforces the last known good policy.

  • 遅延ゼロの評価: すべての guard() 呼び出しは、ローカルメモリに対して評価されます。

    英語の原文 -- 翻訳は技術レビュー待ちです

    No network round-trip.

  • 英語の原文 -- 翻訳は技術レビュー待ちです

    Resilience: Network outages or server maintenance do not interrupt policy enforcement.

デフォルトのキャッシュの場所:

  • Python: ~/.controlzero/cache/
  • Go: ~/.controlzero/cache/
  • Node.js: ~/.controlzero/cache/

ポリシーを更新する​

SDK は、デフォルトで60秒ごとに新しいバンドルを確認します(各確認は ETag 条件付きリクエストなので、ポリシーが変わっていなければ再ダウンロードは発生しません)。この間隔を広げたり狭めたりするには、CONTROLZERO_POLICY_STALENESS_S を設定します。更新を強制することもできます。

# Python: policies refresh automatically; close the client when done
client.close()
// Go
err := client.RefreshPolicies(ctx)
// Node.js
await cz.refreshPolicies();

英語の原文 -- 翻訳は技術レビュー待ちです

Audit log retention

Audit log retention is a configured window by tier: Free 7 days, Solo 90 days, Teams 365 days (see Feature Availability). Automatic deletion of audit records at the end of the window is not currently running on the production audit store, so audit records are kept longer than the window. Deletion will be switched on only after dated notice to affected organizations. When tiered audit retention takes effect, Free organizations created before then keep their existing 30-day window unless an owner changes it, and an owner can set a shorter window. Compliance exports are available in Solo and Teams. View pricing

MCP ツール呼び出しのガバナンス​

Model Context Protocol(MCP)のツールは、ファイルシステムへのアクセス、データベースクエリ、シェルの実行、API 呼び出しなど、AI エージェントに幅広い機能を与えます。Control Zero は、MCP ツールの呼び出しを (action, resource) のペアとして統制します。アクションは mcp.tool:call で、リソースは mcp://{server}/{tool} の規則に従います。

このセクションでは MCP ポリシーのマッチングを定義します。実際の適用は、各クライアントの文書化されたフックのカバレッジに依存します。

一般的なパターン​

読み取り専用エージェント -- 読み取りを許可し、書き込みとシェルを拒否します。

{
"name": "read-only-agent",
"rules": [
{ "effect": "allow", "action": "mcp.tool:call", "resource": "mcp://filesystem/read_file" },
{ "effect": "allow", "action": "mcp.tool:call", "resource": "mcp://filesystem/list_directory" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://filesystem/write_file" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://filesystem/delete_file" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://shell/execute" }
]
}

データベースリーダー -- SELECT を許可し、書き込みを拒否します。

{
"name": "db-reader-agent",
"rules": [
{ "effect": "allow", "action": "mcp.tool:call", "resource": "mcp://database/read_query" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://database/write_query" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://database/execute_query" }
]
}

API 専用エージェント -- 外向きの HTTP を許可し、ローカルへのアクセスを拒否します。

{
"name": "api-only-agent",
"rules": [
{ "effect": "allow", "action": "mcp.tool:call", "resource": "mcp://http/request" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://filesystem/*" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://shell/*" },
{ "effect": "deny", "action": "mcp.tool:call", "resource": "mcp://database/*" }
]
}

MCP ポリシーゲートウェイのパターン​

MCP ネイティブのクライアントでは、ツール呼び出しを小さなゲートウェイでラップし、実際の MCP サーバーに転送する前に guard() を呼び出します。

from controlzero import Client
from typing import Any

cz = Client(api_key="cz_live_your_api_key_here")


class PolicyGateway:
"""MCP gateway that enforces Control Zero policies on tool calls."""

def __init__(self, agent_id: str):
self.agent_id = agent_id

def call_tool(self, server: str, tool: str, arguments: dict) -> Any:
cz.guard(
"mcp.tool",
method="call",
context={"resource": f"mcp://{server}/{tool}", "agent_id": self.agent_id},
args=arguments,
)
return self._forward_to_server(server, tool, arguments)

def check_tool(self, server: str, tool: str) -> bool:
"""Check if a tool call would be allowed (without enforcing)."""
decision = cz.guard(
"mcp.tool",
method="call",
context={"resource": f"mcp://{server}/{tool}", "agent_id": self.agent_id},
)
return decision.effect == "allow"

def _forward_to_server(self, server, tool, arguments):
# Implementation depends on your MCP client library.
pass

提示時にツールリストをフィルタリングする​

エージェントにツールを提示する前に、ポリシーでカタログをフィルタリングして、モデルが呼び出しを許可されていないツールを目にしないようにします。

available_tools = [
("filesystem", "read_file"),
("filesystem", "write_file"),
("database", "read_query"),
("database", "write_query"),
("shell", "execute"),
("http", "request"),
]

allowed_tools = []
for server, tool in available_tools:
decision = cz.guard(
"mcp.tool",
method="call",
context={"resource": f"mcp://{server}/{tool}", "agent_id": "my-agent"},
)
if decision.effect == "allow":
allowed_tools.append((server, tool))

これにより、モデルは拒否されたツールを試みることすらなくなり、無駄なトークンとノイズの多い監査イベントが減ります。

次のステップ​