Edictum

Choosing Rule Types

Four rule types for different enforcement needs. Pick the right one for your use case.

AI Assistance

Right page if: you need to decide between preconditions, postconditions, session rules, and sandbox rules for a specific enforcement goal. Wrong page if: you already know which type and need the full syntax reference -- see https://docs.edictum.ai/docs/rulesets/preconditions, https://docs.edictum.ai/docs/rulesets/postconditions, or https://docs.edictum.ai/docs/rulesets/yaml-reference. Gotcha: preconditions cover 80% of use cases. Only reach for sandbox when you need path/command/domain allowlists, session rules when you need cross-turn limits, or postconditions when you need to inspect tool output.

Edictum has four rule types. Each runs at a different point in the pipeline and solves a different problem.

At a Glance

TypeWhen it runsWhat it checksEffectsUse when
PreconditionBefore tool executesTool name, arguments, principalblock, askBlock dangerous calls, require approval
SandboxBefore tool executes (after preconditions)File paths, commands, domainsblock, askRestrict WHERE the agent can operate
SessionBefore tool executes (after sandbox)Call counts across turnsblockCap tool usage per session
PostconditionAfter tool executesTool outputwarn, redact, blockDetect PII, secrets, or violations in results

Pipeline Order

Rules evaluate in this order. If any step denies, the pipeline stops:

  1. Attempt limits — hard cap on total attempts (including denied calls)
  2. Before hooks — custom Python callbacks
  3. Preconditionstype: pre rules
  4. Sandbox rulestype: sandbox rules
  5. Session rulestype: session rules
  6. Execution limits — hard cap on successful executions
  7. Tool executes
  8. Postconditionstype: post rulesets
  9. After hooks — custom Python callbacks

Preconditions

The default choice. Covers ~80% of enforcement needs.

Use preconditions when you need to block or approve a tool call based on who is calling, what they're calling, or what arguments they're passing.

- id: deny-secret-reads
  type: pre
  tool: read_file
  when:
    args.file_path:
      matches_any: ['\.env$', '\.pem$', '\.key$']
  then:
    action: block
    message: "This file may contain secrets."

Available checks: args.*, principal.*, tool.name, env.*, boolean logic (all, any, not), 15 operators (contains, matches, gt, lt, exists, etc.)

Effects:

  • block — block the call immediately
  • ask — pause and request human approval (with timeout and timeout_action)

Sandbox Rulesets

Use when you need allowlists — restrict where the agent can read, write, execute, or connect.

Sandbox rulesets define boundaries. Anything outside the boundary is denied (or requires approval). This is the inverse of preconditions: instead of listing what's bad, you list what's allowed.

- id: workspace-boundary
  type: sandbox
  tools: [read_file, write_file, edit_file]
  within: [/workspace, /tmp]
  not_within: [/workspace/.git, /workspace/.env]
  outside: block
  message: "File access restricted to /workspace and /tmp."

Boundary types:

BoundaryApplies toExample
within / not_withinFile pathsRestrict reads to /workspace
allows.commandsShell commandsAllow only ls, cat, git
allows.domainsHTTP URLsAllow only github.com, *.googleapis.com
not_allows.domainsHTTP URLsBlock evil.com

Path resolution: All paths resolved via os.path.realpath() before comparison. Handles .. traversals and symlinks.

Sandbox vs precondition: Use preconditions for "deny this specific bad thing." Use sandbox for "only allow these specific good things."


Session Rulesets

Use when you need cross-turn limits. Preconditions and sandbox rulesets evaluate each call independently. Session rulesets track state across calls.

- id: session-limits
  type: session
  limits:
    max_attempts: 200
    max_tool_calls: 100
    max_calls_per_tool:
      exec: 20
      web_fetch: 50
  then:
    action: block
    message: "Session limit reached. Summarize progress and stop."

Available limits:

LimitWhat it counts
max_attemptsTotal PreToolUse events (including denied calls)
max_tool_callsSuccessful PostToolUse executions
max_calls_per_toolPer-tool execution cap (e.g., exec: 20)

State is stored via StorageBackend — in-memory by default, or Redis/Postgres for distributed agents.


Postconditions

Use when you need to inspect tool output. Postconditions run after the tool executes and can scan the result for PII, secrets, or rule violations.

- id: pii-in-output
  type: post
  tool: "*"
  when:
    output.text:
      matches_any:
        - '\b\d{3}-\d{2}-\d{4}\b'    # SSN
        - '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'  # Email
  then:
    action: redact
    message: "PII pattern detected and redacted."

Effects depend on tool classification:

EffectPURE / READ toolsWRITE / IRREVERSIBLE tools
warnWarning logged, callback invokedWarning logged, callback invoked
redactMatched patterns replaced with [REDACTED]Falls back to warn
blockOutput replaced with [OUTPUT SUPPRESSED] {message}Falls back to warn

The fallback exists because WRITE/IRREVERSIBLE actions have already completed — suppressing the output cannot undo the side effect. Use preconditions to deny dangerous writes before execution.


Decision Tree

Start here:

  1. Do you need to block or approve a call before it runs?

    • Yes, based on arguments, role, or tool name → Precondition
    • Yes, based on file path / command / domain boundaries → Sandbox
  2. Do you need to limit how many times a tool can be called?

    • Yes → Session rule
  3. Do you need to inspect what a tool returned?

    • Yes → Postcondition
  4. Not sure?

    • Start with a precondition. You can always add sandbox or session rulesets later.

Next Steps

Last updated on

On this page