Compliance tools tell a human after something goes wrong. Then someone opens a ticket, logs into the cloud and fixes it by hand, while the AI keeps going. An Enforcement Loop closes that gap. Set a threshold on your AI's sealed decisions. The moment it's crossed, sebbi.pro contains the AI, pulls your kill switch and fires a signed command into your own infrastructure. Every step is sealed into the chain and timestamped into Bitcoin.
"5 prompt-injection attempts in 60 seconds." "3 different models blocked in 10 minutes." "Any payment over 50,000." Verdicts, reasons, scores and any field you send, counted in a sliding window.
Checked in the same request that crosses the line. From the next call, every decision on your key is a sealed BLOCK, so the sebbi.pro Gateway stops calling the model for you, until a human releases it.
Your Jugular switches are pulled so every agent halts. A signed webhook hits your infrastructure to revoke cloud keys, scale the container to zero or cut the network route.
The trip, the decisions that caused it, each action and how long it took, and the release are sealed. That's the proof regulators ask for that a stop button exists and works.
It meets EU AI Act Article 14(4)(e), the power to interrupt a high-risk AI through a stop procedure, and does it automatically and provably.
Kept only in this browser. No key yet? Connect in a minute: 7 days free, then 50p per device per month.
Your webhook runs on your side, with your own credentials. sebbi.pro never holds your cloud keys. Each call is signed: X-Sebbi-Signature: t=<time>,v1=<HMAC-SHA256 of "t.body" with your loop secret>. Check it, then run your playbook.
# sebbi.pro enforcement receiver (Python 3, standard library only)
# Run on a machine that can reach your infrastructure: python3 receiver.py
# Set SECRET to your loop's webhook_secret and ACTIONS to your own commands.
import hashlib, hmac, json, os, subprocess, time
from http.server import BaseHTTPRequestHandler, HTTPServer
SECRET = os.environ["SEBBI_WEBHOOK_SECRET"]
ACTIONS = [
# Put your containment commands here, one list per command, e.g.
# ["kubectl", "scale", "deployment/your-ai", "--replicas=0"],
# ["aws", "iam", "update-access-key", "--user-name", "your-ai", "--access-key-id", "AKIA...", "--status", "Inactive"],
]
class H(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
parts = dict(p.split("=", 1) for p in self.headers.get("X-Sebbi-Signature", "").split(",") if "=" in p)
t = int(parts.get("t", 0))
good = hmac.new(SECRET.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(good, parts.get("v1", "")) or abs(time.time() - t) > 300:
self.send_response(401); self.end_headers(); return
event = json.loads(body)
self.send_response(200); self.end_headers()
if event.get("test") or event.get("watch_only"):
return
for cmd in ACTIONS:
subprocess.run(cmd, timeout=20)
HTTPServer(("0.0.0.0", int(os.environ.get("PORT", 8443))), H).serve_forever()
// sebbi.pro enforcement receiver (Node 18+, no packages)
// SEBBI_WEBHOOK_SECRET=whsec_... node receiver.js
const http = require("http"), crypto = require("crypto"), { execFile } = require("child_process");
const SECRET = process.env.SEBBI_WEBHOOK_SECRET;
const ACTIONS = [
// ["kubectl", ["scale", "deployment/your-ai", "--replicas=0"]],
];
http.createServer((req, res) => {
let chunks = [];
req.on("data", c => chunks.push(c));
req.on("end", () => {
const body = Buffer.concat(chunks);
const parts = Object.fromEntries((req.headers["x-sebbi-signature"] || "").split(",").map(p => p.split("=")));
const t = Number(parts.t || 0);
const good = crypto.createHmac("sha256", SECRET).update(`${t}.`).update(body).digest("hex");
const ok = parts.v1 && good.length === parts.v1.length &&
crypto.timingSafeEqual(Buffer.from(good), Buffer.from(parts.v1)) && Math.abs(Date.now() / 1000 - t) < 300;
if (!ok) { res.writeHead(401).end(); return; }
res.writeHead(200).end();
const ev = JSON.parse(body);
if (ev.test || ev.watch_only) return;
for (const [cmd, args] of ACTIONS) execFile(cmd, args);
});
}).listen(process.env.PORT || 8443);
# AWS Lambda (Python) behind a Function URL: verify, then switch the AI's access key off
import base64, boto3, hashlib, hmac, json, os, time
SECRET = os.environ["SEBBI_WEBHOOK_SECRET"]
IAM_USER = os.environ["AI_IAM_USER"] # the IAM user your AI runs as
iam = boto3.client("iam")
def handler(event, context):
body = event.get("body") or ""
raw = base64.b64decode(body) if event.get("isBase64Encoded") else body.encode()
headers = {k.lower(): v for k, v in (event.get("headers") or {}).items()}
parts = dict(p.split("=", 1) for p in headers.get("x-sebbi-signature", "").split(",") if "=" in p)
t = int(parts.get("t", 0))
good = hmac.new(SECRET.encode(), f"{t}.".encode() + raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(good, parts.get("v1", "")) or abs(time.time() - t) > 300:
return {"statusCode": 401}
ev = json.loads(raw)
if not (ev.get("test") or ev.get("watch_only")):
for k in iam.list_access_keys(UserName=IAM_USER)["AccessKeyMetadata"]:
iam.update_access_key(UserName=IAM_USER, AccessKeyId=k["AccessKeyId"], Status="Inactive")
return {"statusCode": 200}
The threshold is checked in the same request as the decision that crosses it, and containment is in place before that response leaves the server. Webhook time depends on your endpoint, and is measured and sealed with the trip.
Release it here in one tap, and the release is sealed. Use watch mode and backtest to tune a loop before you arm it.
No. Your webhook receiver runs your commands with your own credentials. sebbi.pro only sends the signed instruction.
It's included with every sebbi.pro key: 7 days free, then 50p per device per month.
AI agents can set loops too: sebbi_enforce_create, sebbi_enforce_list, sebbi_enforce_release, sebbi_enforce_backtest on https://sebbi.pro/mcp.