Skip to main content

Runtime safety for AI agents. Stop agents before they break things.

Project description

Edictum

PyPI License Python

Runtime contract enforcement for AI agent tool calls.

AI agents call tools with real-world side effects -- reading files, querying databases, executing commands. The standard defense is prompt engineering, but prompts are suggestions the LLM can ignore. Edictum enforces contracts at the decision-to-action seam: before a tool call executes, Edictum checks it against YAML contracts and denies it if it violates policy. The agent cannot bypass it.

This is not feature flags. This is not prompt guardrails. Edictum is a deterministic enforcement point for tool calls -- preconditions before execution, postconditions after, session limits across turns, and a full audit trail.

Show Me

contracts.yaml

apiVersion: edictum/v1
kind: ContractBundle

metadata:
  name: my-policy

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."
      tags: [secrets, dlp]

Python

import asyncio
from edictum import Edictum, EdictumDenied

async def read_file_fn(path):
    return open(path).read()

async def main():
    guard = Edictum.from_yaml("contracts.yaml")

    try:
        result = await guard.run("read_file", {"path": "/app/config.json"}, read_file_fn)
        print(result)
    except EdictumDenied as e:
        print(f"Denied: {e}")

asyncio.run(main())

CLI

$ edictum validate contracts.yaml
  contracts.yaml -- 1 contract (1 pre)

$ edictum check contracts.yaml --tool read_file --args '{"path": ".env"}'
  DENIED by block-sensitive-reads
   Message: Sensitive file '.env' denied.
   Tags: secrets, dlp
   Contracts evaluated: 1

Framework integration (one adapter, same contracts)

from edictum import Edictum, Principal
from edictum.adapters.langchain import LangChainAdapter

guard = Edictum.from_yaml("contracts.yaml")
adapter = LangChainAdapter(guard, principal=Principal(role="analyst"))
wrapper = adapter.as_tool_wrapper()
# Wraps any LangChain tool -- preconditions, audit, and session limits apply automatically

How It Works

  1. Write contracts in YAML. Preconditions deny dangerous calls before execution. Postconditions check tool output after. Session limits cap total calls and retries.
  2. Attach to your agent framework. One adapter line. Same contracts across all six frameworks.
  3. Compose and layer bundles. Split contracts across files by concern. from_yaml() accepts multiple paths with deterministic merge semantics. Shadow-test updates with observe_alongside before promoting.
  4. Every tool call passes through the pipeline. Preconditions, session limits, and principal context are evaluated. If any contract fails, the call is denied and never executes.
  5. Full audit trail. Every evaluation produces a structured event with automatic secret redaction.

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

Framework Support

Edictum integrates with six agent frameworks. Same YAML contracts, same enforcement, different adapter patterns:

Framework Integration PII Redaction Complexity
LangChain + LangGraph as_tool_wrapper() Full interception Low
OpenAI Agents SDK as_guardrails() Logged only Medium
Agno as_tool_hook() Full interception Low
Semantic Kernel register() Full interception Medium-High
CrewAI register() Partial High
Claude Agent SDK to_hook_callables() Logged only Low

See Adapter Docs for setup, known limitations, and recommendations.

Install

Requires Python 3.11+. Current version: v0.8.0.

pip install edictum              # core (zero deps)
pip install edictum[yaml]        # + YAML contract engine
pip install edictum[otel]        # + OpenTelemetry span emission
pip install edictum[cli]         # + validate/check/diff/replay CLI
pip install edictum[all]         # everything

Built-in Templates

guard = Edictum.from_template("file-agent")      # secret file protection, destructive cmd blocking
guard = Edictum.from_template("research-agent")   # output PII detection, session limits
guard = Edictum.from_template("devops-agent")     # role gates, ticket requirements, bash safety

Demos & Examples

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

edictum-0.8.1.tar.gz (245.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

edictum-0.8.1-py3-none-any.whl (71.5 kB view details)

Uploaded Python 3

File details

Details for the file edictum-0.8.1.tar.gz.

File metadata

  • Download URL: edictum-0.8.1.tar.gz
  • Upload date:
  • Size: 245.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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

Hashes for edictum-0.8.1.tar.gz
Algorithm Hash digest
SHA256 7ce4fd1fa16832d4a1725e79e686daf236d04ee4c4e073b384cc8bfccee9bca4
MD5 26f32cee6cf53c6b50036e2aeb6860c1
BLAKE2b-256 1870bb203040861bc279799eb70eb5cf45c781387e55d79c79c428264efe6124

See more details on using hashes here.

File details

Details for the file edictum-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: edictum-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 71.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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

Hashes for edictum-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5bf528379eb07481c2230b654366e87298d28a5ac979414d1de6a7ac709d7b24
MD5 cf4b5664534b41e32e96d91c6ff88b9e
BLAKE2b-256 8d5d449f89c6fcf0489fb0c89d67505fa5d9bd113d710e6d900763a99bb3e4c3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page