Cedar Policy Authoring Guide
This guide covers how to write Cedar policies for Lucid. Cedar is the unified policy language for all enforcement decisions -- it replaces LPL, OPA/Rego, and block_on_* flags.
How Cedar Works in Lucid
- ClaimsAuditors observe AI traffic and produce typed claims (e.g.,
toxic_content = 0.42) - The Gateway collects all claims into a
ClaimsContext - The Gateway evaluates your Cedar policy against the context
- The policy produces an allow or deny decision
- The decision is recorded in the Evidence and AI Passport
You write Cedar policies that reference claim names. The Gateway does the rest.
Cedar Syntax Primer
Cedar policies are either permit or forbid statements:
// Allow a request
permit(principal, action, resource)
when { <conditions> };
// Deny a request
forbid(principal, action, resource)
when { <conditions> };
Cedar uses deny-overrides: if any forbid matches, the request is denied regardless of permit rules.
Principals, Actions, and Resources
In Lucid's Cedar schema:
| Concept | What It Represents | Examples |
|---|---|---|
| Principal | Who is making the request | User::"user-123", Agent::"legal-bot", APIKey::"key-abc" |
| Action | What operation is being performed | Action::"invoke", Action::"access_data" |
| Resource | The target agent or service | Agent::"my-agent", Service::"compliance-api" |
| Context | Claims and metadata | context.claims.*, context.phase, context.trace_id |
Accessing Claims in Conditions
Claim names from auditors are available under context.claims:
// Auditor produces: toxic_content = 0.42
// Cedar accesses: context.claims.toxic_content
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.8 };
Common Policy Patterns
Block on Threshold
// Block toxic content
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.7 };
Block on Boolean Detection
// Block injection attempts
forbid(principal, action == Action::"invoke", resource)
when { context.claims.secret_leaked == true };
Block with Confidence Check
// Only block if injection risk is very high
forbid(principal, action == Action::"invoke", resource)
when { context.claims.injection_risk > 0.9 };
Block Unless Authorized
// Block PII access unless the agent is authorized for PII
forbid(principal, action == Action::"invoke", resource)
when { context.claims.pii_count > 0 }
unless { resource.pii_authorized == true };
Allow Specific Principals
// Only admin users bypass toxicity checks
permit(principal in Group::"admins", action == Action::"invoke", resource);
// Everyone else is subject to toxicity checks
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.5 };
Geo-Fencing
// Block if not in allowed region
forbid(principal, action == Action::"invoke", resource)
when { !("EU" in context.claims.detected_regions) };
Multi-Claim Combinations
// Block if BOTH injection risk AND toxicity are high
forbid(principal, action == Action::"invoke", resource)
when {
context.claims.injection_risk > 0.7 &&
context.claims.toxic_content > 0.5
};
Response-Phase Policies
Response-phase claims use the same syntax:
// Block responses that contain hallucinations
forbid(principal, action == Action::"invoke", resource)
when {
context.phase == "response" &&
context.claims.hallucination_score > 0.6
};
Decision Annotations
Annotate policies to control enforcement behavior beyond simple allow/deny:
Warn Instead of Block
// Flag but don't block moderate toxicity
@annotation("decision", "warn")
forbid(principal, action == Action::"invoke", resource)
when {
context.claims.toxic_content > 0.5 &&
context.claims.toxic_content <= 0.8
};
Escalate to Human
// Require human approval for high PII exposure
@annotation("decision", "escalate")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.pii_count > 5 };
Shadow Mode (Test Without Enforcing)
// Test a new rule without affecting traffic
@annotation("decision", "shadow")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.new_experimental_score > 0.9 };
| Annotation | Behavior |
|---|---|
deny (default) |
Block the request |
warn |
Allow but flag in passport |
escalate |
Block and create approval request |
shadow |
Evaluate and log, but do not enforce |
log |
Silent logging only |
Detection Rules vs Response Rules
Cedar policies are the Response Rules — they define what happens when claims fire. The Detection Rules (auditor settings) control what claims are produced and at what sensitivity. Both can be configured together via auditor presets (Starter, Balanced, Strict) that provide coherent bundles of settings and policies.
Auditor settings also support enforcement modes (floor, ceiling, exact, superset, unlocked) that control how parent scope constraints are inherited. See the Policy as Code guide for details.
Policy Scoping
Organization Policies
Org policies are security baselines that cannot be overridden:
@annotation("scope", "org")
@annotation("id", "org-baseline-injection")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.injection_risk > 0.7 };
Workspace Policies
Workspace policies add restrictions for a group of agents:
@annotation("scope", "workspace")
@annotation("workspace_id", "ws-customer-support")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.3 };
Agent Policies
Agent-specific policies for individual agents:
@annotation("scope", "agent")
@annotation("agent_id", "agent-legal-reviewer")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.location_confidence >= 0.9 };
Scoping Rules
- Org
forbidrules apply everywhere and cannot be removed - Workspace
forbidrules add to org rules - Agent
forbidrules add to org + workspace rules - A lower-scope
permitcannot override a higher-scopeforbid
Compliance Annotations
Map policies to regulatory controls:
@annotation("compliance_framework", "GDPR")
@annotation("control_id", "Art.5(1)(c)")
@annotation("description", "Data minimization - block unnecessary PII exposure")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.pii_found == true }
unless { resource.pii_authorized == true };
These annotations are surfaced in the Observer UI for compliance reporting.
Testing Policies
CLI Testing
# Validate syntax
lucid policy validate policy.cedar
# Test against sample claims
lucid policy test policy.cedar --claims-file test-claims.json --expect deny
# Preview changes before deploying
lucid policy diff policy.cedar --scope agent --scope-id agent-abc123
Sample Claims File
{
"principal": "User::\"user-123\"",
"action": "Action::\"invoke\"",
"resource": "Agent::\"my-agent\"",
"context": {
"phase": "request",
"claims": {
"toxic_content": 0.9,
"injection_risk": 0.1,
"pii_found": true,
"pii_count": 1,
"detected_regions": ["US"]
}
}
}
Deploying Policies
Via CLI
# Push to an agent
lucid policy push policy.cedar --scope agent --scope-id agent-abc123
# Push to a workspace
lucid policy push workspace-policy.cedar --scope workspace --scope-id ws-123
# Push org baseline
lucid policy push org-baseline.cedar --scope org
Via Observer UI
Use the three-tab policy editor (IFTTT, Visual, Cedar) in the Observer. See the Policy Editor Guide.
Via YAML
Include Cedar policies in your agent definition:
apiVersion: lucid.io/v1alpha1
kind: LucidAgent
metadata:
name: my-agent
spec:
model:
id: meta-llama/Llama-3.3-70B
policy:
cedar: |
forbid(principal, action == Action::"invoke", resource)
when { context.claims.injection_risk > 0.7 };
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.7 };
permit(principal, action == Action::"invoke", resource);
Best Practices
- Start with deny-all, permit explicitly: Begin with no default permit and add specific allows.
- Use shadow mode for new policies: Test new rules with
@annotation("decision", "shadow")before enforcing. - Keep org policies minimal: Org-level rules should be absolute security baselines only.
- Reference specific claims: Avoid broad conditions; reference the exact claim names from the auditor vocabulary.
- Add compliance annotations: Map every security rule to a regulatory control for audit trails.
- Version control your
.cedarfiles: Treat policies like code -- review, test, and version them.