Skip to main content
Everyone is rushing to ship AI agents without thinking about consequences. An agent that only reads is wrong at no cost. An agent that can pay, delete, deploy, grant or send is wrong at the cost of the thing it did, and its framework was built to make it act, not to act once. CTRLRun exists for the boundary between intending an effect and having caused one. Five principles.

FAILED is not UNKNOWN

A timeout tells you nothing. The refund may have committed at Stripe a millisecond before the connection dropped. A framework that marks the call failed and retries has turned one unknown into a probable double. CTRLRun has three outcomes: COMMITTED, FAILED and AMBIGUOUS. Only the executor can say FAILED, by raising NotExecuted, and only when it knows the remote did nothing. Everything else after the first byte is AMBIGUOUS, and an AMBIGUOUS effect blocks a blind retry until a human or a reconcile hook says what happened. Never map an unknown exception to a failure.

An approval is bound to what the human saw

A human who approved “refund €2,000 on txn_2” did not approve €5,000, and did not approve €2,000 again next week. CTRLRun binds an approval to the SHA-256 of the exact action: name, canonical arguments, resource, principal, environment. It is used once, expires, and is consumed in the same atomic write that reserves the effect, so a mutated action matches nothing and a replayed one finds its approval spent. An approval authorizes one exact action, not a category of action.

Autonomy belongs to the action, not the agent

The question is not whether an agent is trusted. It is whether this action, with these arguments, may run without a person. A €100 refund is autonomous, a €2,000 refund needs a human, a €20,000 refund is refused, whichever agent proposes it. The policy decides per action and cannot see who is asking. Who may ask at all is a second axis, authority, evaluated first and separately, and the two combine as the stricter of the pair. Neither reads the agent’s instructions, which is why a prompt injection cannot talk its way past either. Decide the action. Grant the principal. Never let one loosen the other.

Unknown means no

An action the policy does not list is denied. A missing policy, a malformed policy, a missing principal, an expired credential, a mismatched approval, an inconsistent store: denied. There is no flag that makes a consequential action permissive by default, in the kernel, in verify or in an adapter, because the first deployment to set it would be the one that mattered. Observe mode lets a rollout measure before it enforces; it is not a way to relax a check. Fail closed is not configurable.

Evidence leaves the building

Every executed action leaves a portable JSON receipt: who, what, decision, approval, effect key, outcome, and the hash of the policy that decided it, chained to the receipt before it. Receipts go to a JSONL file beside the store and to any sink you give them, because evidence has to survive the process that produced it. The chain detects alteration. It does not prove authorship, and the page that describes it says so in the same breath. A receipt is worth what it says when the process is gone.

What follows

CTRLRun does not host models, plan, prompt, retrieve, route, remember or orchestrate. It is not a guardrail library, an IAM system, a workflow engine or a compliance product, and it issues no credential. It cannot guarantee exactly-once execution against a remote it does not control; it guarantees it will not knowingly act twice and will never call an unknown a failure. The reason to believe this is not this page: every README sentence has a row in CLAIMS.md naming the code and the test, every requirement is mutation-tested, and ctrlrun verify runs the guarantees against your own configuration and reports what it could not check.

Next