본문으로 건너뛰기
이 페이지는 기계 번역이며 충분한 검토를 거치지 않았습니다. 영어 원문이 기준입니다. 보안, 개인정보 보호, 데이터 처리, 규정 준수 및 라이선스에 관한 설명은 기술 검토가 끝날 때까지 영어로 유지됩니다. 영어 원문 보기

빠른 시작

지원 모드: Hosted Hybrid Local 제공 플랜: Free Solo Teams

5분 이내에 에이전트에 AI 거버넌스를 추가하세요. 배포 경로는 두 가지입니다. 상황에 맞는 경로를 선택하세요.

경로적합한 경우코드 변경
게이트웨이 (옵션 A)기존 에이전트, 빠른 도입없음. URL 하나만 변경
SDK (옵션 B)새 에이전트, 가장 긴밀한 통합패키지 설치, 도구 호출 감싸기

두 경로 모두 대시보드에서 정의한 동일한 정책을 적용합니다.

1단계: 가입​

  1. app.controlzero.ai에 접속하여 계정을 만드세요.
  2. 먼저 둘러보고 싶으신가요? app.controlzero.ai/demo에서 대화형 데모를 사용해 보세요. 계정이 필요 없습니다.

Free 플랜에는 월 5,000건의 통제된 액션이 포함되며 신용카드가 필요 없습니다.

2단계: 프로젝트 만들기​

  1. 로그인하면 2단계 온보딩이 첫 프로젝트 생성을 안내합니다.
  2. 프로젝트 이름(예: my-agent)을 정하고 환경을 선택하세요.
  3. 프로젝트 설정 페이지에서 API 키(예: cz_live_abc123...)를 복사하세요.

환경 변수로 설정하세요.

export CONTROLZERO_API_KEY="cz_live_your_key_here"

3단계: 대시보드에서 정책 정의하기​

정책은 정책 라이브러리의 조직 수준에 존재하며 프로젝트에 연결됩니다. 이를 통해 하나의 정책이 프로젝트별 재정의와 함께 여러 프로젝트를 통제할 수 있습니다.

3a. 라이브러리 정책 만들기​

사이드바에서 Library를 클릭한 다음 New policy를 클릭하세요.

  • 이름: db-read-only
  • 설명: 에이전트는 데이터베이스를 조회할 수 있지만 데이터를 수정할 수 없습니다.
  • 규칙(JSON 배열): 아래 스니펫을 붙여넣거나 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도 받아들이며 자동으로 정규화합니다.

SQL 의미 클래스

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+가 필요합니다. 이전 버전에서는 인자에서 도출된 클래스를 확인하기 전에 메서드에서 도출된 클래스가 허용 규칙을 충족할 수 있어 허용되었습니다. 더 세밀한 제어가 필요하면 특정 키워드(예: database:DROP)를 지정할 수도 있습니다. 전체 매핑은 Canonical Tool Names를 참고하세요.

3b. 프로젝트에 정책 연결하기​

프로젝트를 열고 Attach policy를 클릭한 뒤 db-read-only를 선택하고, 상태를 Active로 유지한 채 확인하세요. 이제 프로젝트의 정책 번들이 해당 규칙을 적용합니다. 클라이언트는 다음 갱신 때 규칙을 반영합니다. Python SDK는 기본적으로 60초마다, Node SDK는 300초마다 폴링합니다.

4단계: 에이전트 통합하기​

옵션 A: 게이트웨이 (코드 변경 없음)​

게이트웨이는 투명한 프록시입니다. LLM 기본 URL이 게이트웨이를 바라보게 하고 헤더 두 개를 추가하세요. 기존 에이전트 코드는 그대로 동작합니다.

영어 원문 -- 번역은 기술 검토 대기 중입니다

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에서 스코프가 이 레지스트리를 가리키도록 한 번만 설정하세요.

@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();

두 가지 모드, 하나의 클라이언트:

영어 원문 -- 번역은 기술 검토 대기 중입니다

  • 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=... or policy_file=...): zero network for policy eval. Audit stays in a rotating local file. Good for air-gapped deployments and controlzero.yaml checked into the repo.

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:01databaseSELECTallowagent-analyst
12:00:02databaseUPDATEdenyagent-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}"입니다.

deny 결정을 반환하는 대신 PolicyDeniedError를 발생시키려면 raise_on_deny=True를 전달하세요.

Client.close()​

버퍼링된 감사 로그를 플러시하고 열려 있는 모든 연결을 닫습니다.

PolicyDeniedError​

raise_on_deny=True이고 정책이 액션을 거부할 때 guard()가 발생시킵니다.

속성타입설명
e.decision.effectstr항상 "deny"입니다.
e.decision.reasonstr사람이 읽을 수 있는 설명입니다.
e.decision.policy_idstr일치한 정책의 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.

다음 단계​

영어 원문 -- 번역은 기술 검토 대기 중입니다