ctrlrun
An open-source Python library that acts as an execution safety layer for AI agents, checking every action against your rules before it runs and blocking wrong, restricted, or malicious actions.
At a Glance
Fully open-source under Apache-2.0. Free to use, modify, and distribute.
Engagement
Available On
Alternatives
Listed Sep 2026
About ctrlrun
ctrlrun is an open-source Python library that sits between an AI agent's decision to act and the call that actually executes. It checks every outbound action against a YAML policy before it runs, routes sensitive actions to a human for approval, and blocks forbidden ones entirely. Released under Apache-2.0, it runs in production on a single SQLite file or on Postgres across multiple hosts, with no external service required.
What It Is
ctrlrun is an execution safety layer — a programmable checkpoint that intercepts consequential AI agent actions before they reach your systems. The core idea is that a tool being callable is not permission to call it with any arguments: ctrlrun reads the arguments about to leave your process and answers one of three things — let it run, ask a human, or stop it cold. It is a Python library installed via pip install ctrlrun, and integration is as simple as a @ctrlrun.protect decorator on the function that has the consequence, plus a YAML policy file that names the rules.
The Seven-Step Execution Boundary
Every protected call, regardless of how it arrives, passes through the same pipeline before reaching your systems:
- Normalize — the call becomes a canonical
Actionwith a SHA-256 hash - Decide — authority is checked first (may this principal propose this?), then policy (how much autonomy does this action get?); silence is never permission
- Approve — a human answers against the exact action hash; the approval is single-use, expires, and matches nothing but that exact action
- Reserve — the effect key is claimed in one atomic write; a second caller on another process or host is refused
- Execute — your code runs; only
NotExecutedmeansFAILED, every other exception meansAMBIGUOUS - Resolve — an
AMBIGUOUSeffect keeps its key and refuses a retry until a human or a reconcile hook says what happened - Record — a portable JSON receipt is written for every attempt, refusals included, chained to the receipt before it
Three Ways to Integrate
ctrlrun offers three integration paths depending on what you have:
@protectdecorator — wraps any Python function in this process: a raw model call, a LangChain tool, a hand-rolled loop, or a cron job; needs nothing beyondpip install ctrlrun- MCP gateway — places every guarantee in front of an MCP tool server in any language, with no changes to the agent or server code; installed with
pip install "ctrlrun[gateway]" - Framework adapters — routes an
approvedecision through a framework's own interrupt (LangChain, LangGraph, OpenAI Agents SDK) so a human answers where they already answer
Key Guarantees
The library enforces six core guarantees, each present since early versions:
- Approval binding — an approval is bound to the exact action hash; mutated or replayed approvals are refused
- One effect, once — one logical effect key happens at most once, across threads, processes, and hosts
- Unknown is not failed — a lost reply is
AMBIGUOUS, neverFAILED, and blocks a blind retry - Fail closed — an unknown action, missing policy, or missing principal is denied by default
- Authority and delegation — every principal needs a grant; delegation cannot widen one; a grant bounds the total, including optional rolling-window budgets since v0.9
- Receipts — every executed action leaves a portable JSON receipt of who, what, and outcome, chained by hash
Update: v0.12.2
The latest release is v0.12.2, published on 2026-09-15, available on PyPI for Python 3.11 through 3.14. The project's changelog tracks features by version: the @protect decorator and core guarantees landed in v0.1; the MCP gateway and webhook approvals in v0.2; authority and delegation in v0.3; the ctrlrun verify command and verified badge in v0.4; framework adapters in v0.5; Postgres support, receipt chaining, policy versioning, and the control registry in v0.6; and budget-bounded grants in v0.9. The repository lists 6,248 tests, with every requirement mutation-tested, and 32 guarantees checkable in any user's own setup via ctrlrun verify.
Architecture and Deployment
State lives in SQLite by default — a single file with no server and no ops, production-grade on one host. Pointing it at Postgres (pip install "ctrlrun[postgres]") enables the same guarantees across multiple hosts, graded by the same test suite. The enforcement kernel is fully open source under Apache-2.0, and releases carry PyPI provenance attestations from GitHub Actions. Two products — ctrl ai agents and ctrl payments — are documented on the ctrlrun site as running on this kernel and crediting it on every page.
Community Discussions
Be the first to start a conversation about ctrlrun
Share your experience with ctrlrun, ask questions, or help others learn from your insights.
Pricing
Open Source
Fully open-source under Apache-2.0. Free to use, modify, and distribute.
- Full enforcement kernel
- SQLite and Postgres backends
- All guarantees: approval binding, one effect once, AMBIGUOUS, fail closed, authority, receipts
- @protect decorator, MCP gateway, framework adapters
- Operator CLI
Capabilities
Key Features
- Per-action YAML policy (allow / approve / deny per action and argument)
- Approval binding — approvals bound to exact action hash; mutations void the approval
- One effect, once — atomic effect key reservation across threads, processes, and hosts
- AMBIGUOUS outcome — unknown results block blind retries until a human resolves
- Fail closed — unknown actions, missing policy, or missing principal are denied
- Authority and delegation — grants, delegation chains, and rolling-window budgets
- Portable JSON receipts chained by hash for every action, including refusals
- @protect decorator for Python functions
- MCP gateway for tool servers in any language
- Framework adapters for LangChain, LangGraph, and OpenAI Agents SDK
- Operator CLI (approve, deny, resolve, inspect, count)
- Webhook approvals (e.g., Slack)
- Reconciliation hook for AMBIGUOUS effects
- OpenTelemetry export (one span per action)
- Observe mode — records what would have been blocked without blocking
- ctrlrun verify — runs guarantee catalogue against your policy and store
- Verified badge for GitHub Actions CI
- SQLite (single host) and Postgres (multi-host) backends
- Versioned schema with forward-only migrations
- Recovery after crash — dead worker effects stay AMBIGUOUS until resolved
- Receipt chain integrity — alteration detected and named
- Policy versioning — every receipt names the policy hash that decided it
- Control registry — name compliance controls satisfied by an action
- Data scope — label arguments by data class and condition rules on labels
- Runtime delegation — principals narrow their own grants at runtime
- MCP server exposing documentation search
