The policy engine lets you define rules that your audit trail must satisfy, then check them automatically.
Built-in policies
Five policies are included and run with a single command:
| Policy | Description |
|---|
| Chain Integrity | Hash chain is unbroken |
| Event Completeness | Every TOOL_CALL has a matching TOOL_RESULT |
| Session Health | No >1 hour gaps between consecutive events |
| Error Rate | Flag sessions with >50% error events |
| Duration Outliers | Flag tool calls >60 seconds |
Custom policies (YAML)
Define custom policies in a YAML file:
plog policy check --file policies.yaml
plog policy check --file policies.yaml --policy my-policy # Run one specific policy
Rule types
The policy engine supports 7 rule types:
Sequence
If event X occurs, event Y must follow within a duration:
policies:
- name: tool-result-follows-call
rules:
- name: result-after-call
type: sequence
when:
action_type: TOOL_CALL
expect:
action_type: TOOL_RESULT
within: "60s"
Absence
If event X occurs, event Y must NOT follow:
policies:
- name: no-delete-after-read
rules:
- name: no-delete
type: absence
when:
action_name: read_file
deny:
action_name: delete_file
Boundary
Restrict an agent to a set of allowed actions:
policies:
- name: agent-boundary
rules:
- name: restricted-actions
type: boundary
allow_actions:
- read_file
- search
Presence
A scope must contain at least one matching event:
policies:
- name: must-have-llm-call
rules:
- name: require-llm
type: presence
scope: session
require:
action_type: LLM_CALL
Rate
No more than X events of type Y per scope:
policies:
- name: rate-limit-api-calls
rules:
- name: llm-rate
type: rate
per: session
count:
action_type: LLM_CALL
max: 100
Pattern
Field values must match (or not match) a regex:
policies:
- name: no-pii-in-output
rules:
- name: no-ssn
type: pattern
for_field: action_output
deny_pattern: "\\d{3}-\\d{2}-\\d{4}"
Use match_pattern to require a field value matches a regex, or deny_pattern to require it does not.
Temporal
Events must fall within a time window:
policies:
- name: business-hours-only
rules:
- name: weekday-hours
type: temporal
when:
action_type: TOOL_CALL
hours: [9, 17]
days: [1, 2, 3, 4, 5]
timezone: "America/New_York"
The hours field takes [start, end) in 24-hour format. The days field uses 0=Sunday through 6=Saturday.
Common rule fields
All rule types support these optional fields:
| Field | Description |
|---|
name | Name of the rule |
severity | "fail" (default) or "warn" |
scope | "session" or "agent" |
label_filter | Filter events by label values before evaluation |
Dry run
Test policies against existing events without affecting anything:
plog policy test --file policies.yaml
plog policy test requires --file — it is designed for validating custom policy definitions.
Policy result schema
{
"policy": "event-completeness",
"status": "fail",
"violations": [
{
"policy_name": "event-completeness",
"rule": "result-after-call",
"trigger_event": "evt-123",
"expected_event": "TOOL_RESULT",
"session_id": "session-456",
"agent_id": "my-agent",
"timestamp": "2026-02-17T10:30:00Z",
"message": "TOOL_CALL without matching TOOL_RESULT",
"detail": "Expected TOOL_RESULT within 60s of TOOL_CALL at sequence 42"
}
],
"events_evaluated": 150,
"timestamp": "2026-02-17T12:00:00Z"
}