Ony is a kill switch for autonomous coding agents, so the whole design assumes the agent might lie, the transport might be hostile, and an insider might try to rewrite history. The trust boundary is the server and your device, never the thing asking for permission.
Each one moves authority away from the agent and onto the server and your device. Together they are why an approval means what it says.
The agent can attach a risk hint to any action. Ony throws it away and re-derives the real risk from a server-owned action taxonomy. The classification you see on the call is computed by the server, never by the thing asking for permission. Actions the taxonomy does not recognize fail closed to critical.
Every verdict is HMAC-signed with a per-device key and bound to the exact request it answers. The local connector verifies that signature before it honors anything. A forged approval, a replayed approval, or a verdict aimed at a different request is rejected at the boundary, not trusted on faith.
Every decision lands in a keyed, hash-chained, append-only log. Each entry commits to the one before it, so editing or deleting any single event breaks every hash that follows. The dashboard verifies the whole chain end to end and shows you exactly where, if anywhere, it stopped matching.
If Ony is unreachable, a signature cannot be verified, or a decision deadline passes, the action is never silently allowed. The system falls back to the agent's own permission prompt or denies outright. Absence of an approval is treated as a no, never as a yes.
A good kill switch is paranoid on purpose. For every way the system could be lied to or worked around, there is a mitigation that does not depend on trusting the agent.
Assumption
The agent may misreport its own risk.
Mitigation
Risk is re-derived server-side from a fixed action taxonomy. The agent's hint is ignored, and unknown actions fail closed to critical.
Assumption
An attacker may replay an old approval.
Mitigation
Verdicts are bound to the exact request and carry an expiry. A replayed or stale verdict does not match the pending request and is rejected.
Assumption
The transport between you and the agent may be hostile.
Mitigation
Decisions are HMAC-signed and verified on-device. Any mismatch, tampering, or substitution fails closed rather than passing through.
Assumption
An insider may try to edit history after the fact.
Mitigation
The audit log is keyed and hash-chained. Altering one event breaks the chain, and the dashboard surfaces the break on verification.
Assumption
Ony itself may be unreachable when a decision is due.
Mitigation
No silent allow. The action falls back to the agent's normal permission prompt or is denied. A missing answer is never an approval.
Assumption
A high-risk action may reach the worst moment unattended.
Mitigation
Critical actions require a 6-digit code in addition to the keypad approval, so a single misdirected keypress cannot ship production.
A verdict is a small, signed statement bound to one request. The connector verifies it before honoring it, so a tampered or replayed copy never makes it through.
// signed by an enrolled device, verified on-device
{
"request_id": "req_9f3a1c84b27d",
"agent_session_id": "sess_claude_prod_api_0427",
"action": "deploy.production",
"risk": "critical",
"decision": "approve",
"approver_device_id": "dev_2b7e4a90",
"issued_at": "2026-06-30T14:22:07Z",
"expires_at": "2026-06-30T14:24:07Z",
"signature": "hmac-sha256:4c1f8a6e..."
}Illustrative shape. The signature is truncated for display.
The signature covers request_id, action, and risk, so a verdict only validates against the precise call it was issued for.
Each enrolled device signs with its own key. Revoke a device and its future signatures stop verifying immediately.
issued_at and expires_at bound the window. A verdict that arrives late is treated as no decision, not a yes.
The local connector checks the signature first. If it does not verify, the action fails closed before it ever runs.
Every decision is appended to a keyed hash-chain. Each entry hashes the one before it, so changing any single event invalidates every event after it. The dashboard verifies the chain end to end.
session.startdeploy.productiondb.migratesecret.rotate#0002and its hash changes, so#0003and#0004no longer verify. Tampering is loud, not silent.The system is built around the smallest fact it needs to do its job: what kind of action is happening and how risky it is. The payload stays with your agent.
Ony receives the action and its server-derived risk classification. It does not receive your raw commands, file contents, or secret values. You approve a category and a target, not a payload.
Run the whole stack on your own infrastructure with pip install ony and a one-command Docker deploy. In that posture, no outside service sits between your agent and your decision.
The phone call is placed through a telephony provider (SignalWire). On self-host you bring your own number and keys, so the call path is yours and usage is pass-through.
Signing material is scoped to each enrolled device. Enrollment issues a decision_key, and revoking a device invalidates its ability to sign new verdicts.
Good-faith security research is welcome. If you find a flaw in the trust model, the signing scheme, the audit chain, or anything else, email us with the details and steps to reproduce. We will work with you to confirm, fix, and credit the report. The full source is public under AGPL-3.0, so you can review the real implementation, not just this page.
Read the code, run it yourself, or let Ony Cloud run it for you. The guarantees are the same either way.