Runtime rule enforcement for AI agent tool calls.
Prompts are suggestions. Rules are enforcement. The LLM cannot talk its way past a rule.
55us overhead · 18 adapters across Python, TypeScript, Go · Zero runtime deps · Fail-closed by default
pip install edictum[yaml]Deny first -- see enforcement before writing YAML:
from edictum import Edictum, EdictumDenied
guard = Edictum.from_template("file-agent")
result = guard.evaluate("read_file", {"path": ".env"})
print(result.decision) # "block"
print(result.block_reasons[0]) # "Sensitive file '.env' blocked."Full path -- your rule, your enforcement:
guard = Edictum.from_yaml("rules.yaml")
try:
result = await guard.run("read_file", {"path": ".env"}, read_file)
except EdictumDenied as e:
print(e.reason) # "Sensitive file '.env' blocked."rules.yaml:
apiVersion: edictum/v1
kind: Ruleset
metadata:
name: file-safety
defaults:
mode: enforce
rules:
- id: block-sensitive-reads
type: pre
tool: read_file
when:
args.path:
contains_any: [".env", ".secret", "credentials", ".pem", "id_rsa"]
then:
action: block
message: "Sensitive file '{args.path}' blocked."Rules are YAML. Enforcement is deterministic -- no LLM in the evaluation path, just pattern matching against tool names and arguments. The agent cannot bypass a matched rule. Rule errors, type mismatches, and missing fields all fail closed (block). Tool calls with no matching rules are allowed by default -- add a catch-all tool: "*" rule for block-by-default.
An agent says "I won't read sensitive files" -- then calls read_file(".env") and leaks your API keys.
A DevOps agent recognizes a jailbreak attempt, writes "I should NOT comply" in its reasoning -- then reads four production database credentials in the next tool call.
Prompt engineering doesn't fix this. You need enforcement at the tool-call layer.
| Framework | Adapter | Integration |
|---|---|---|
| LangChain + LangGraph | LangChainAdapter |
as_tool_wrapper() / as_middleware() |
| OpenAI Agents SDK | OpenAIAgentsAdapter |
as_guardrails() |
| Claude Agent SDK | ClaudeAgentSDKAdapter |
to_hook_callables() |
| CrewAI | CrewAIAdapter |
register() |
| Agno | AgnoAdapter |
as_tool_hook() |
| Semantic Kernel | SemanticKernelAdapter |
register() |
| Google ADK | GoogleADKAdapter |
as_plugin() / as_agent_callbacks() |
| Nanobot | NanobotAdapter |
wrap_registry() |
# LangChain
from edictum.adapters.langchain import LangChainAdapter
adapter = LangChainAdapter(guard)
tool = adapter.as_tool_wrapper(tool)
# OpenAI Agents SDK
from edictum.adapters.openai_agents import OpenAIAgentsAdapter
adapter = OpenAIAgentsAdapter(guard)
input_gr, output_gr = adapter.as_guardrails()
# Claude Agent SDK
from edictum.adapters.claude_agent_sdk import ClaudeAgentSDKAdapter
adapter = ClaudeAgentSDKAdapter(guard)
hooks = adapter.to_hook_callables()
# Google ADK
from edictum.adapters.google_adk import GoogleADKAdapter
adapter = GoogleADKAdapter(guard)
plugin = adapter.as_plugin()See Adapter docs for all 8 frameworks.
Rules -- four types covering the full tool call lifecycle:
- Preconditions block dangerous calls before execution
- Postconditions scan tool output -- warn, redact PII, or block
- Session rules cap total calls, per-tool calls, and retry attempts
- Sandbox rules allowlist file paths, commands, and domains
Principal-aware enforcement -- role-gate tools with claims and env.* context. set_principal() for mid-session role changes.
Callbacks -- block/allow lifecycle callbacks for logging, alerting, or approval workflows.
Test and validate:
guard.evaluate()-- dry-run without executing the tool- Load rules in tests and assert decisions directly from Python
- For CLI workflows, use the Go binary in edictum-go -- that is the canonical Edictum CLI
Ship safely:
- Observe mode -- log what would be blocked, then enforce
- Multi-file composition with deterministic merge
- Custom YAML operators and selectors
- For CLI-based diff/replay workflows, use the Go binary in edictum-go
Audit and observability:
- Structured audit events on every evaluation
- OpenTelemetry spans and metrics
- Secret values auto-redacted in audit events
- File, stdout, and composite sinks
guard = Edictum.from_template("file-agent")
# Blocks .env, .pem, credentials, id_rsa reads. Blocks rm -rf, chmod 777, destructive shell commands.
guard = Edictum.from_template("research-agent")
# Postcondition PII scanning on tool output. Session limits (100 calls, 20 per tool).
guard = Edictum.from_template("devops-agent")
# Role gates (only ops principal can deploy). Ticket ID required. Bash command safety.
guard = Edictum.from_template("nanobot-agent")
# Approval gates for exec/spawn/cron/MCP. Workspace path restrictions. Session limits.Pre-execution governance for coding assistants. Sits between the assistant and the OS, evaluating every tool call against rules.
pip install edictum[gate]The Python package ships the Gate library and integrations. For command-line workflows, use the Go binary in edictum-go -- that is the canonical Edictum CLI.
Supports Claude Code, Cursor, Copilot CLI, Gemini CLI, and OpenCode. Self-protection rules prevent the assistant from disabling governance. Optional sync to Edictum Console for centralized audit.
See the Gate guide for setup.
Optional self-hostable operations console for governed agents. Rule management, live hot-reload via SSE, human-in-the-loop approvals, audit event feeds, and fleet monitoring.
guard = await Edictum.from_server(
url="http://localhost:8000",
api_key="edk_production_...",
agent_id="my-agent",
)See edictum-console for deployment.
Edictum was evaluated across six regulated domains in the GAP benchmark (6 LLMs, 17,420 datapoints).
Used to audit OpenClaw's 36,000-skill registry -- found live C2 malware on first scan.
For CLI-based scanning and other command-line workflows, use the Go binary in edictum-go.
Requires Python 3.11+.
pip install edictum # core (zero deps)
pip install edictum[yaml] # + YAML rule parsing
pip install edictum[otel] # + OpenTelemetry span emission
pip install edictum[gate] # + coding assistant governance library
pip install edictum[verified] # + Ed25519 bundle signature verification
pip install edictum[server] # + server SDK (connect to Edictum Console)
pip install edictum[all] # everything in this Python packageFor CLI workflows, use the Go binary in edictum-go.
| Approach | Scope | Runtime enforcement | Audit trail |
|---|---|---|---|
| Prompt/output guardrails | Input/output text | No -- advisory only | No |
| API gateways / MCP proxies | Network transport | Yes -- at the proxy | Partial |
| Security scanners | Post-hoc analysis | No -- detection only | Yes |
| Manual if-statements | Per-tool, ad hoc | Yes -- scattered logic | No |
| Edictum | Tool call rules | Yes -- deterministic pipeline | Yes -- structured + redacted |
| Domain | What Edictum enforces |
|---|---|
| Coding agents | Secret protection, destructive command denial, write scope (Gate guide) |
| Healthcare | Patient data access control, role-gated queries |
| Finance | PII redaction in query results, transaction limits |
| DevOps | Production deploy gates, ticket requirements, bash safety |
| Education | Student data protection, session limits per assignment |
| Legal | Privileged document access, audit trail for compliance |
| Repo | Language | What it does |
|---|---|---|
| edictum | Python | Core library -- this repo |
| edictum-ts | TypeScript | Core + adapters (Claude SDK, LangChain, OpenAI Agents, OpenClaw, Vercel AI) |
| edictum-go | Go | Core + adapters (ADK Go, Anthropic, Eino, Genkit, LangChain Go) |
| edictum-console | Python + React | Self-hostable ops console: HITL, audit, fleet monitoring |
| edictum-schemas | JSON Schema | Rule bundle schema + cross-SDK conformance fixtures |
| edictum-demo | Python | Scenario demos, adversarial tests, benchmarks, Grafana observability |
| Documentation | MDX | Full docs site |
| edictum.ai | -- | Official website |
See SECURITY.md for vulnerability reporting.