Skip to main content

Interdict: Runtime Safety for Agent-Written SQL

Status: Alpha PyPI Python CI Homepage Docs License


[!IMPORTANT] Interdict is an alpha developer preview and under active development. It is designed for agent-operated Postgres workflows, not as a replacement for least-privilege database roles, backups, or human review of production policies.

Install | Quickstart | How it works | Benchmarks | Configuration | Limits | Docs | Contributing | Security

Interdict is the safety layer between AI agents and Postgres. Agents can now issue real SQL against real databases; ordinary permissions answer "may this role touch this table?", but not "how much will this statement change?" or "can I undo it if the agent is wrong?" Interdict answers those questions before damage is done.

It parses SQL into a Postgres AST, applies deterministic policy, measures every write without executing it, holds high-impact changes for operator approval, and records supported writes so a human can approve reverting them. Blocks return structured explanations and repair hints so the agent can correct itself and retry.

Platforms. Interdict requires Python 3.11+ and a reachable Postgres database. The current public adapter is an MCP server; the safety engine is transport-agnostic.

Installation

pip install interdict-db

The PyPI distribution is named interdict-db; the command it installs is interdict. The separate interdict package on PyPI is an unrelated legacy dictionary utility.

Working on Interdict itself? Install the local development environment instead:

uv sync --group dev --python 3.11
docker compose up -d

See CONTRIBUTING.md for the full local validation loop.

Quickstart

The normal setup is three commands:

pip install interdict-db
interdict setup --name production
interdict connect claude --profile production

interdict setup is a guided terminal wizard. It tests the connection, discovers tables, creates a least-privilege policy, checks the database role, initializes the control store, stores credentials in the operating-system keychain when available, and creates a named profile. It never places a database URL or approval credential in the MCP configuration.

The connector configures the agent to launch Interdict automatically. You do not run a second server window. Verify the connection by asking Claude to call interdict_status, then ask it to work with the database normally.

Other supported clients use the same profile:

interdict connect codex --profile production
interdict connect cursor --profile production
interdict connect custom --profile production

For a safe read, Interdict checks the SQL and sends it to Postgres. For a dangerous or large write, Interdict measures the blast radius and holds the exact SQL for a human decision. Approvals happen in your terminal, never in the agent chat:

interdict approvals --profile production
interdict approve latest --profile production
interdict deny latest --profile production

Use the exact approval ID instead of latest when more than one request is pending. Holds expire after 30 minutes so a stale measurement cannot be acted on. A supported successful write returns an undo_id; a human can request the newest bounded revert with:

interdict revert latest --profile production

Interdict then tells the agent which approved tool call can complete the action. The approval credential never enters the model conversation.

Multiple databases

Configure each database once and select it explicitly:

interdict setup --name staging
interdict setup --name analytics
interdict profiles
interdict profile use production

The human chooses the active profile. Interdict does not expose an MCP tool that lets an agent switch itself to a different database.

No database handy for local evaluation? Start the seeded Pagila database and choose the Development preset in the wizard:

docker compose up -d postgres
interdict setup --name local-pagila

Production setup

Production mode refuses to connect an agent when the database boundary is unsafe. The application connection must be a non-owner, non-superuser role limited to the selected tables. Approvals, undo evidence, and the durable audit copy must use a separate database and role.

If the URL entered during interdict setup is too powerful, the wizard saves the profile as needs-dba, generates one owner-only SQL file for review, and stops. It does not grant itself privileges or connect the agent. A database administrator reviews and applies the script, then the customer reruns setup using the restricted role and checks it with:

interdict doctor --profile production
interdict connect claude --profile production

Advanced operators may still use environment variables and interdict init, but customers do not need to hand-write YAML or long MCP commands for the standard workflow.

For an upgrade from the older in-application adb_undo schema, run interdict migrate-control. It is idempotent and copy-only: it does not delete the old records. Verify the copy and your backups before manually revoking or archiving the legacy schema.

Benchmarks

Interdict keeps a hard latency budget: the pass-through path must stay under 5 ms added p99, and CI fails if the gate is exceeded.

What Result
Cost added per statement, warm path 2.6 us p50 / 2.7 us p99
End-to-end overhead vs raw asyncpg measurement-noise floor; CI gate requires added p99 < 5 ms
Dangerous statements missed, red corpus 0% of 40
Safe statements wrongly blocked, green corpus 0% of 18
Blast-radius measurement exact row counts, live
Undo round-trip ~4 ms, conflict-checked restore
Automated tests 378, run in CI on every commit

The benchmark methodology, caveats, and raw tables live in benchmarks/RESULTS.md. CI runs lint, the full pytest suite against seeded Postgres 16, and the latency gate on every push and pull request.

Configuration

Named profiles are the recommended configuration interface. The following variables remain available for advanced/manual deployments:

Variable Default Purpose
AGENT_DB_DSN local dev DSN Target Postgres connection string.
AGENT_CONTROL_DSN unset Separate control database for approvals, undo evidence, and durable audit events; required in production.
AGENT_SAFETY_PROFILE production production fails startup on unsafe privileges; development relaxes deployment topology.
AGENT_POLICY policies/default.yaml Database-agnostic safety policy.
AGENT_OPERATOR_TOKEN unset Required to approve held writes; use at least 32 random characters.
AGENT_OPERATOR_ID unset Stable identity recorded for the human operator; required in production.
AGENT_APPROVAL_TTL_SECONDS 1800 How long a held write stays approvable.
AGENT_AUDIT_LOG ~/.interdict/audit.jsonl Async audit log with raw SQL redacted and hashes retained.

policies/pagila.yaml shows a stricter allowlist-style policy for the bundled development database.

Honest limits

  • Interdict only governs SQL sent through its adapter. Do not give the agent a raw database DSN, cloud-admin token, shell with production credentials, or a second unguarded database tool.
  • Undo is bounded compensation, not a backup system. Interdict blocks automatic undo for unsupported statement shapes, user triggers, cascading foreign-key actions, oversized captures, and conflicts detected during restore.
  • Keep encrypted backups and point-in-time recovery in a different failure domain from the production volume, and regularly test restoration. A backup on the same volume does not protect against volume deletion.
  • Least privilege, dev/staging separation, reviewed migrations, CI/CD gates, provider deletion protection, and human incident procedures remain required.
  • The MCP adapter cannot intercept destructive cloud API calls such as deleting a Railway volume. The agent must not possess credentials scoped to those actions; enforce that boundary in your cloud IAM system.

Development

uv sync --group dev --python 3.11
docker compose up -d
uv run ruff check .
uv run black --check .
uv run pytest
uv run python -m benchmarks.ci_latency_gate

The seeded database mirrors the GitHub Actions service container: postgresql://postgres:postgres@localhost:5433/pagila.

Documentation

Repository Layout

engine/      safety core: parse, classify, policy, measure, undo, audit
adapters/    MCP server
policies/    YAML policies
corpus/      red and green query sets
benchmarks/  latency harness and CI gate
tests/       correctness, race, fault-injection, evasion, and MCP tests
examples/    local demo script
website/     landing page source for interdict.vercel.app
research/    study harness, figures, and paper artifacts
docs/        design notes and architecture specs

Contributing

Contributions are welcome for bug fixes, documentation, examples, tests, and tightly scoped improvements. Please read CONTRIBUTING.md before opening a pull request and follow the Code of Conduct.

Security

Please do not report security vulnerabilities through public issues or pull requests. Follow SECURITY.md for private reporting guidance.

License

Interdict is licensed under the MIT License.

Download files

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

Source Distribution

interdict_db-0.3.0.tar.gz (89.2 kB view details)

Uploaded Source

Built Distribution

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

interdict_db-0.3.0-py3-none-any.whl (96.0 kB view details)

Uploaded Python 3

File details

Details for the file interdict_db-0.3.0.tar.gz.

File metadata

  • Download URL: interdict_db-0.3.0.tar.gz
  • Upload date:
  • Size: 89.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for interdict_db-0.3.0.tar.gz
Algorithm Hash digest
SHA256 6c7d2ae60115aaac956c213d17046c1dd42cc5676de7d68acb60e7021bfc9672
MD5 a92f209719e605fe2127a65b68b8df23
BLAKE2b-256 19aaa2bded7a6e3fb19bba1b98b46076660855fd1d79b2ceb561de0cc90bb985

See more details on using hashes here.

File details

Details for the file interdict_db-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: interdict_db-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 96.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for interdict_db-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 38805f2632a008e86122742e9dc07d197f6a0d572f8b2ba971e9de301029b38e
MD5 67e988ce3276f2522b7df2e4839736b1
BLAKE2b-256 90c5795d131df21d298cb11bdd58059f8b79c37942ea1730fe12845543d12ef9

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 Sentry Error logging StatusPage Status page