Skip to main content

CHOKR Policy Language (CPL): AI agent governance as code

CPL is a small, declarative policy-as-code language for governing what AI agents and other programs may do. You write the rules as data in a YAML (or JSON) file; CPL evaluates them against a description of something that is about to happen, such as an agent's tool call, and returns a decision: allow, ask (human approval), deny and more.

Use it when a program must make allow/deny style decisions that other people need to read, review or change, and the decisions must be deterministic, testable and auditable. CPL is a library and a command line tool; your application asks for a verdict and acts on it. Typical uses: tool-call authorization, human-in-the-loop approval, spend and rate limits, data-access control, and audit with replay. It works with any agent framework or tool-calling protocol, including MCP, because it only sees the action you hand it.

CPL decides; it does not enforce. It does not sandbox or intercept anything, so your application must act on the verdict.

Status: alpha (0.0.x). The language and the Python API may change before 1.0.

Example: govern an AI agent's tool calls

cpl: "1.0"
id: agent-tool-calls
version: 1
default: deny                         # fail closed: anything not allowed is denied
rules:
  - id: small-payments
    match: {kind: [tool_call]}
    when: {arguments.tool: send_payment, expr: "arguments.amount <= 100"}
    outcome: allow

  - id: large-payments-need-a-human
    match: {kind: [tool_call]}
    when:
      arguments.tool: send_payment
      expr: "arguments.amount > 100"
      approval: {timeout_seconds: 900}
    outcome: ask

From a clone of this repository, run its test cases:

$ cplang test --policy examples/agent_tool_call --fixtures examples/agent_tool_call/agent.fixtures.yaml

The full policy and its test cases are in examples/agent_tool_call.

Install

pip install chokr-policy-language            # library and the `cplang` command
pip install "chokr-policy-language[prove]"   # adds the optional prover
uv add chokr-policy-language                 # or add it to a uv project
pipx install chokr-policy-language           # or the command line tool only

Python 3.14 or newer. Import name: cplang.

Concepts

  • Action: what is being decided, a JSON-like document with a timestamp and any fields you choose. The timestamp is the time.now of time windows and rate limits, so the host sets it from its own clock, never from the agent's request.
  • Signal: an optional named finding about the action, for example {code: scan.malware, severity: high}.
  • Policy: a YAML/JSON file of rules.
  • Verdict: allow, watch, modify, ask or deny, with reason codes and the rules that decided it.

A policy

cpl: "1.0"
id: document-access
version: 1
default: deny                       # outcome when no rule matches
rules:
  - id: read-public
    match: {kind: [read]}           # which actions the rule is about
    when: {resource.type: public}   # further conditions
    outcome: allow

  - id: large-upload-needs-approval
    match: {kind: [write]}
    when:
      expr: "arguments.size_kb > 512"
      approval: {timeout_seconds: 3600}
    outcome: ask

  - id: malware-found
    when: {signal: {code: scan.malware, severity_gte: high}}
    outcome: deny

Rules take id, outcome and optionally match, when, let, reason, explain, obligations, modify, priority, enabled, mode. Conditions read paths of the action (resource.type, customer.tier) with operators such as eq, in, gt, between, glob, regex, exists, combined with any, all, not. Policies can import declaration files for shared parameters, constants, tables and types.

A deny: or threshold check on a field the action does not carry denies, so leaving a field out never skips a limit. To let a missing field through, test for it first: deny: {all: [{arguments.amount: {exists: true}}, {arguments.amount: {gt: 100}}]}. A check on the tool's arguments.response waits until the response exists.

Your own fields work without any setup. To have them type-checked, declare them:

schema: cpl.declarations/1.0
types:
  Customer: {kind: object, fields: {tier: {type: string}, spend: {type: number, required: false}}}  # fields are required unless marked
inputs:
  customer: {type: Customer}
shortcuts:
  tier_is: {path: customer.tier}    # your own condition key: when: {tier_is: [gold, silver]}

Declare your own types under types:: enum, object, list, set, map, union, quantity, or a constrained scalar such as Email: {kind: string, format: email} or Score: {kind: integer, min: 0, max: 10}. A string pattern is searched for, as in JSON Schema, so anchor it to match the whole value: {kind: string, pattern: "^[A-Z]{2}$"}. Declared inputs are checked against their type on every evaluation, and a mismatch denies with EVALUATION_ERROR. The language's own type names (string, list, ...) and standard field names (kind, arguments, ...) are reserved and cannot be redefined.

Use from the command line

$ cplang policy check policy.yaml                         # validate + lint; fails on any problem
$ cplang eval --policy policy.yaml --action action.yaml   # decide one action
allow POLICY_SATISFIED  rules=['read-public']
$ cplang test --policy policy.yaml --fixtures cases.yaml  # check expected decisions

cases.yaml:

schema: cpl.fixtures/1.0
now: "2026-01-05T10:00:00Z"
cases:
  - name: malware-is-denied
    action: {kind: read, resource: {type: public}}
    signals: [{code: scan.malware, severity: critical}]
    expect: {outcome: deny}

Other commands: cplang policy validate|lint|fmt|fingerprint|types|explain|prove, cplang expr eval, cplang decl check|show|fmt|lock, cplang schema. Run cplang --help for options. --json gives machine-readable output. Exit codes: 0 ok, 1 the check failed (or eval returned deny/ask), 2 bad usage or input (an unreadable policy or fixture file), 3 an internal error.

Use from Python

from pathlib import Path
from cplang import Action, RuleEvaluator, Signal, load_policy

policy = load_policy([Path("policy.yaml")], roots=[Path(".")])  # raises AuthoringError if invalid
evaluator = RuleEvaluator(policy)  # thread-safe; reuse it
verdict = evaluator.evaluate(
    Action({"kind": "read", "resource": {"type": "public"}, "timestamp": "2026-01-05T10:00:00Z"}),
    [Signal(code="scan.malware", source="scanner", severity="low")],
)
print(verdict.outcome, verdict.reason_codes, verdict.matched_rules)

load_policy also takes limits=CplLimits(...), profile=Profile(...) (host reason codes, input names, rule keys) and strict_inputs=True (reject names that are neither standard nor declared). FunctionRegistry adds functions callable from expressions. verdict.to_wire() returns JSON-compatible data. The package is fully typed.

More examples: examples/agent_tool_call and examples/access.

Contributing and security

See CONTRIBUTING.md. Report vulnerabilities privately as described in SECURITY.md, not in public issues.

License

Apache License 2.0. Copyright 2026 chokr-ai. See LICENSE and NOTICE.

Metadata

Release files for chokr-policy-language 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chokr-policy-language 0.0.1
File Size Uploaded Provenance
chokr_policy_language-0.0.1.tar.gz 168.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for chokr-policy-language 0.0.1
File Interpreter ABI Platform
chokr_policy_language-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 356.4 kB

Release files / chokr_policy_language-0.0.1.tar.gz

Download URL chokr_policy_language-0.0.1.tar.gz
Size 168.0 kB
Tags Source
SHA-256 checksum
How to use checksums
934f7e6096677c9345a6d13e89a8f9e940401246ad6bda1bfbe95783e72bbb15
BLAKE2b-256 checksum
How to use checksums
6b4d5ee0007fd2742e51777bd9bf4aa767709daebba57a2434a2e065504216c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / chokr_policy_language-0.0.1-py3-none-any.whl

Download URL chokr_policy_language-0.0.1-py3-none-any.whl
Size 188.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
953795ad58dc5f556f8446b4adae9704eb4121972b69b4d2e6f499c4b1182da3
BLAKE2b-256 checksum
How to use checksums
29d75953eedcddc62ce06fb5d04d20903f3eca6b2c188703f0e82e3046923c5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Security for chokr-policy-language 0.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for chokr_policy_language-0.0.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page