[!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
- Homepage -- product overview and demo.
- Get started -- complete installation, profile, agent connection, and approval guide.
- Design doc -- current architecture and engineering rules.
- v2 architecture spec -- forward roadmap and interface decisions.
- Benchmark results -- measured latency and correctness results.
- Research notes -- study harness and validation material.
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
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c7d2ae60115aaac956c213d17046c1dd42cc5676de7d68acb60e7021bfc9672
|
|
| MD5 |
a92f209719e605fe2127a65b68b8df23
|
|
| BLAKE2b-256 |
19aaa2bded7a6e3fb19bba1b98b46076660855fd1d79b2ceb561de0cc90bb985
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38805f2632a008e86122742e9dc07d197f6a0d572f8b2ba971e9de301029b38e
|
|
| MD5 |
67e988ce3276f2522b7df2e4839736b1
|
|
| BLAKE2b-256 |
90c5795d131df21d298cb11bdd58059f8b79c37942ea1730fe12845543d12ef9
|