Runtime safety for AI agents. Stop agents before they break things.
Project description
Edictum
Runtime contract enforcement for AI agent tool calls.
Prompts are suggestions. Contracts are enforcement. The LLM cannot talk its way past a contract.
55us overhead · 18 adapters across Python, TypeScript, Go · Zero runtime deps · Fail-closed by default
pip install edictum[yaml]
Quick Start
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.verdict) # "deny"
print(result.deny_reasons[0]) # "Sensitive file '.env' denied."
Full path -- your contract, your enforcement:
guard = Edictum.from_yaml("contracts.yaml")
try:
result = await guard.run("read_file", {"path": ".env"}, read_file)
except EdictumDenied as e:
print(e.reason) # "Sensitive file '.env' denied."
contracts.yaml:
apiVersion: edictum/v1
kind: ContractBundle
metadata:
name: file-safety
defaults:
mode: enforce
contracts:
- id: block-sensitive-reads
type: pre
tool: read_file
when:
args.path:
contains_any: [".env", ".secret", "credentials", ".pem", "id_rsa"]
then:
effect: deny
message: "Sensitive file '{args.path}' denied."
Contracts 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 contract. Contract errors, type mismatches, and missing fields all fail closed (deny). Tool calls with no matching contracts are allowed by default -- add a catch-all tool: "*" contract for deny-by-default.
The Problem
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.
Works With Your Framework
| 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.
What You Can Do
Contracts -- four types covering the full tool call lifecycle:
- Preconditions deny dangerous calls before execution
- Postconditions scan tool output -- warn, redact PII, or deny
- Session contracts cap total calls, per-tool calls, and retry attempts
- Sandbox contracts 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 -- on_deny / on_allow for logging, alerting, or approval workflows.
Test and validate:
edictum validate-- catch schema errors at load timeedictum test-- YAML test cases with expected verdictsguard.evaluate()-- dry-run without executing the tool
Ship safely:
- Observe mode -- log what would be denied, then enforce
- Multi-file composition with deterministic merge
- Custom YAML operators and selectors
edictum diffandedictum replayfor contract drift detection
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
Built-in Templates
guard = Edictum.from_template("file-agent")
# Blocks .env, .pem, credentials, id_rsa reads. Denies 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.
Edictum Gate
Pre-execution governance for coding assistants. Sits between the assistant and the OS, evaluating every tool call against contracts.
pip install edictum[gate]
edictum gate init
Supports Claude Code, Cursor, Copilot CLI, Gemini CLI, and OpenCode. Self-protection contracts prevent the assistant from disabling governance. Optional sync to Edictum Console for centralized audit.
See the Gate guide for setup.
Edictum Console
Optional self-hostable operations console for governed agents. Contract 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.
Research & Real-World Impact
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.
edictum skill scan ./skills/
Install
Requires Python 3.11+.
pip install edictum # core (zero deps)
pip install edictum[yaml] # + YAML contract parsing
pip install edictum[otel] # + OpenTelemetry span emission
pip install edictum[cli] # + validate/check/diff/replay CLI
pip install edictum[gate] # + coding assistant governance
pip install edictum[verified] # + Ed25519 bundle signature verification
pip install edictum[server] # + server SDK (connect to Edictum Console)
pip install edictum[all] # everything
How It Compares
| 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 contracts | Yes -- deterministic pipeline | Yes -- structured + redacted |
Use Cases
| 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 |
Ecosystem
| 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 | Contract 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 |
Security
See SECURITY.md for vulnerability reporting.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file edictum-0.16.0.tar.gz.
File metadata
- Download URL: edictum-0.16.0.tar.gz
- Upload date:
- Size: 676.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f60c54063b5ffa6a95f8dce9f18e108e20707e1e983ecfd9800e7408f15589f9
|
|
| MD5 |
09c5dd75422e7a32a779e37124453e3c
|
|
| BLAKE2b-256 |
47c0759b460b0c59a0fc1e87b7d9e9c4a4c580c616c57ceabbd930ad5d80dcbe
|
File details
Details for the file edictum-0.16.0-py3-none-any.whl.
File metadata
- Download URL: edictum-0.16.0-py3-none-any.whl
- Upload date:
- Size: 173.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
270c97fbc6c8415f6777d4eb680be6bb64cb9ca64e3ba32f2a19a3e09033131c
|
|
| MD5 |
d1462ef79e5d6cca604139764db27921
|
|
| BLAKE2b-256 |
cb037f57c1bec76c0ff84dcc27e9044cf5f49dd86d7392322dafac5e785ee54a
|