Skip to content

Your first policy

Kite Logik policies are OPA/Rego files. You can either write them directly, or write them in a constrained YAML DSL and let kitelogik compile generate the Rego for you. Most teams start with YAML and drop into hand-written Rego when they need delegation cascades, plan evaluation, or data-classification flow control — features the YAML compiler intentionally doesn't cover.

Option A — YAML

The YAML DSL covers the common cases: action allowlists/denylists, argument thresholds, role and scope checks, risk tier assignment, deny reasons.

yaml
# policies/policy.yaml
version: 1
package: kitelogik.main

rules:
  - name: allow_read_ops
    when:
      action: [get_customer, list_transactions]
      scope: read_customer
    then: allow
    risk_tier: INFORMATIONAL

  - name: allow_small_refund
    when:
      action: approve_refund
      role: [support_agent, manager]
      scope: approve_refund
      args:
        amount: { lte: 200 }
    then: allow
    risk_tier: TRANSACTIONAL_LOW

  - name: block_large_refund
    when:
      action: approve_refund
      args:
        amount: { gt: 200 }
    then: deny
    reason: "Refunds over $200 require manager approval"

  - name: block_shell_access
    when:
      action: run_shell_command
    then: deny
    reason: "Shell access is prohibited"

Supported argument operators

The args: block compares fields on input.args. Five operators:

YAMLRego operator
gt>
gte>=
lt<
lte<=
eq==

Compile

bash
kitelogik compile policies/policy.yaml

Writes policies/policy.rego next to the source. With -o path/to.rego you can override the destination, and with --check you can validate the YAML without writing output.

Validate the generated Rego

bash
kitelogik validate

Runs opa check on every *.rego file in policies/ (excluding *_test.rego).

What the YAML compiler will not generate

By design, complex interactions stay in hand-written Rego:

  • Delegation cascades (agent.spawn / agent.delegate rules that reference parent_token_id and delegation_depth graph relationships)
  • Plan evaluation (agent.plan rules that count step types or check cross-step invariants)
  • Data classification flow (data_classification field rules and cross-event flow constraints)

For those, see Option B.

Option B — Hand-written Rego

Every policy file starts with default allow := false (deny-by-default), imports the if and in keywords, and lives in kitelogik/policies/<name>.rego (or your project's policies/ for kitelogik init projects).

rego
package kitelogik.financial

import future.keywords.if
import future.keywords.in

default allow := false

# Allow refunds under $100 for support agents with the right scope
allow if {
    input.action == "approve_refund"
    "approve_refund_under_100" in input.context.session_scopes
    input.context.user_role in {"support_agent", "manager"}
    input.args.amount <= 100
}

The same pattern works for agent lifecycle policies — just match on input.event_type:

rego
package kitelogik.agent_lifecycle

import future.keywords.if
import future.keywords.in
import future.keywords.every

default allow := false
default deny := false

allow if {
    input.event_type == "agent.spawn"
    input.context.delegation_depth <= 2
    every cap in input.requested_capabilities {
        cap in input.context.session_scopes
    }
}

deny if {
    input.event_type == "agent.spawn"
    input.context.delegation_depth > 2
}

See kitelogik/policies/examples/ in the source for annotated templates, and kitelogik/policies/library/ for ready-to-use starter policies (financial, security, RBAC, tool allowlists).

Test policies with opa test

Rego has first-class unit testing. Drop a *_test.rego file alongside your policy and run:

bash
kitelogik test

Internally this calls opa test policies/. Use kitelogik test -v for verbose output.

rego
# policies/financial_test.rego
package kitelogik.financial_test

import data.kitelogik.financial

test_small_refund_is_allowed if {
    financial.allow with input as {
        "action": "approve_refund",
        "args": {"amount": 50},
        "context": {
            "user_role": "support_agent",
            "session_scopes": ["approve_refund_under_100"],
        },
    }
}

test_large_refund_is_denied if {
    not financial.allow with input as {
        "action": "approve_refund",
        "args": {"amount": 5000},
        "context": {
            "user_role": "support_agent",
            "session_scopes": ["approve_refund_under_100"],
        },
    }
}

Dry-run a single event with kitelogik check

Useful for "would this event be allowed?" debugging without spinning up an agent. Pass the event payload as JSON:

bash
kitelogik check '{
  "action": "read_file",
  "resource_path": "/etc/passwd",
  "context": {
    "session_id": "s1",
    "user_role": "support",
    "session_scopes": ["read_customer"]
  }
}'

Returns the full PolicyDecision as JSON.

Iterate

OPA's --watch flag (set on the kitelogik init Docker Compose) means edits to policies/*.rego hot-reload. Edit, save, re-run your agent — the new rules are live without restarting OPA.

Next

Released under the Apache 2.0 License.