Skip to content
Zurück zur Startseite

§ DOCUMENTATION

Benutzerdefinierte Validatoren (BYOV)

Ihr eigener HTTPS-Endpunkt, den Execlave während der Richtliniendurchsetzung aufruft. Führen Sie Ihre eigene Geschäftslogik aus — Finanzobergrenzen, Datenraum-ACLs, systemübergreifende Lookups — innerhalb der Allow-/Deny-Entscheidung.

§ 01

Wann ein benutzerdefinierter Validator sinnvoll ist

Die integrierten Richtlinientypen (Prompt Injection, PII, Rate-Limits, Werkzeugumfang, Ausgabenobergrenzen) decken die meisten Governance-Anforderungen ab. Benutzerdefinierte Validatoren sind die Notluke, wenn Ihre Richtlinie von Zuständen abhängt, die Execlave nicht speichert.

  • Kundenspezifische Ausgabenlimits, die in Ihrem Abrechnungssystem liegen.
  • Berechtigungs-Lookups (Rolle, Org, Region) gegen Ihren IdP oder LDAP.
  • Zugriffsprüfungen auf Zeilenebene gegen einen internen Datenkatalog.
  • Geschäftszeiten-/Freeze-Window-Gates, gesteuert durch Ihren Betriebskalender.
  • Systemübergreifende Freigaben, bei denen Execlave-Freigaben allein nicht ausreichen.

Ein Validator ist einfach ein HTTPS-Endpunkt. Execlave signiert jede Anfrage mit einem HMAC-SHA256-Secret, erzwingt SSRF-Schutzmaßnahmen und respektiert Ihren konfigurierten Fail-Modus (fail_closed standardmäßig).

§ 02

Request-Vertrag

Execlave sendet einen signierten POST an Ihren Endpunkt, bevor der Agent ausführt. Der Body spiegelt den Durchsetzungskontext wider.
POST https://validators.internal.acme.com/enforceContent-Type: application/jsonX-Execlave-Signature: sha256=<hex HMAC of the raw body>X-Execlave-Timestamp: 2026-04-22T09:00:00ZX-Execlave-Validator-Id: 5f3a…X-Execlave-Delivery-Id: 9c21… {  "organizationId": "org_...",  "agentId": "agt_...",  "agentName": "finance-assistant",  "environment": "production",  "input": "Transfer $50,000 to vendor-9923",  "tools": ["payments.transfer"],  "metadata": { "userId": "u_42" },  "estimatedCost": 0.02,  "timestamp": "2026-04-22T09:00:00Z"}
§ 03

Response-Vertrag

Antworten Sie mit 200 und einem JSON-Body, der eine von drei Entscheidungen enthält. Jeder andere Statuscode wird als Fehler behandelt und vom konfigurierten Fail-Modus gehandhabt.
HTTP/1.1 200 OKContent-Type: application/json {  "decision": "deny",  "reason": "Transfer exceeds $10,000 daily cap for finance-assistant",  "metadata": { "policyRef": "FIN-TX-0003" }}
EntscheidungVerhalten
allowValidator ist zufrieden — die Durchsetzung wird mit den übrigen Richtlinien fortgesetzt.
denyLöst PolicyBlockedError / ValidatorDeniedError im SDK aus — der LLM-Aufruf wird verhindert.
require_approvalErstellt eine Freigabeanfrage und setzt den Aufruf aus, bis ein Mensch zustimmt.
§ 04

Sicherheitsgarantien

  • Nur HTTPS — der SSRF-Schutz weist Nicht-HTTPS-URLs und jedes Ziel zurück, das auf eine private, Loopback-, Link-Local- oder Cloud-Metadaten-Adresse auflöst.
  • HMAC-SHA256-signiert — ein 32-Byte-validatorbezogenes Secret, serverseitig generiert und einmalig angezeigt. Rotieren Sie es jederzeit; das alte Secret funktioniert sofort nicht mehr.
  • Replay-geschützt — Anfragen enthalten einen RFC3339-Zeitstempel; lehnen Sie alles ab, was älter als 15 s ist.
  • Circuit Breaker — nach 10 aufeinanderfolgenden Fehlern öffnet der Validator; Execlave ruft ihn 30 s lang nicht mehr auf und wendet während der Abkühlphase den konfigurierten Fail-Modus an.
  • Größenbegrenzt — Antworten größer als VALIDATOR_MAX_RESPONSE_BYTES (Standard 64 KiB) werden abgebrochen und als Fehler behandelt.
  • Verschlüsselt im Ruhezustand — das HMAC-Secret wird mit AES-256-GCM unter Verwendung von VALIDATOR_ENCRYPTION_KEY verschlüsselt.
§ 05

Referenzimplementierungen

Sofort einsetzbare Beispiele, die Signaturverifizierung, Replay-Schutz und eine Entscheidungsantwort implementieren.
Express (Node.js)
import express from 'express';import crypto from 'node:crypto'; const app = express();const SECRET = process.env.EXECLAVE_VALIDATOR_SECRET!; // 32-Byte-Hex // Rohen Body für die HMAC-Verifizierung erhaltenapp.use(express.json({ verify: (req, _res, buf) => ((req as any).rawBody = buf) })); app.post('/enforce', (req, res) => {  const sig = (req.header('X-Execlave-Signature') ?? '').replace('sha256=', '');  const ts = req.header('X-Execlave-Timestamp') ?? '';  const raw = (req as any).rawBody as Buffer;   // 1. Anfragen älter als 15 s ablehnen (Replay-Schutz)  if (Math.abs(Date.now() - Date.parse(ts)) > 15_000) {    return res.status(400).json({ error: 'stale timestamp' });  }   // 2. HMAC-Verifizierung in konstanter Zeit  const expected = crypto.createHmac('sha256', SECRET).update(raw).digest('hex');  const ok = sig.length === expected.length &&    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));  if (!ok) return res.status(401).json({ error: 'invalid signature' });   // 3. Ihre Geschäftslogik  const body = req.body as { input: string; estimatedCost: number };  if (body.estimatedCost > 1.0) {    return res.json({ decision: 'deny', reason: 'estimated cost exceeds $1.00' });  }   return res.json({ decision: 'allow' });}); app.listen(8080);
FastAPI (Python)
import hmac, hashlib, os, timefrom datetime import datetime, timezonefrom fastapi import FastAPI, Request, HTTPException SECRET = os.environ["EXECLAVE_VALIDATOR_SECRET"].encode() app = FastAPI() @app.post("/enforce")async def enforce(request: Request):    raw = await request.body()    sig = (request.headers.get("x-execlave-signature", "")           .removeprefix("sha256="))    ts = request.headers.get("x-execlave-timestamp", "")     # 1. Veraltete Anfragen ablehnen (>15 s Abweichung)    try:        delta = abs(time.time() - datetime.fromisoformat(            ts.replace("Z", "+00:00")).timestamp())    except ValueError:        raise HTTPException(400, "invalid timestamp")    if delta > 15:        raise HTTPException(400, "stale timestamp")     # 2. HMAC-Verifizierung in konstanter Zeit    expected = hmac.new(SECRET, raw, hashlib.sha256).hexdigest()    if not hmac.compare_digest(sig, expected):        raise HTTPException(401, "invalid signature")     # 3. Ihre Geschäftslogik    body = await request.json()    if body.get("estimatedCost", 0) > 1.0:        return {"decision": "deny", "reason": "cost exceeds $1.00 cap"}    return {"decision": "allow"}
§ 06

CLI

# Validatoren auflistenexeclave validators list # Validator erstellen (Secret wird einmalig angezeigt)execlave validators create \  --name finance-spend-cap \  --url https://validators.internal.acme.com/enforce \  --fail-mode fail_closed \  --timeout-ms 2000 # Validator testenexeclave validators test <id> # HMAC-Secret rotierenexeclave validators rotate-secret <id>
§ 07

Fail-Modi

Jeder Validator deklariert, was Execlave tun soll, wenn der Aufruf fehlschlägt (Timeout, Netzwerkfehler, ungültige Antwort, Circuit offen):

  • fail_closed (Standard, empfohlen für sicherheitskritische Richtlinien) — Fehler als Deny behandeln. Der LLM-Aufruf wird blockiert.
  • fail_open — Fehler als Allow behandeln. Nur für unkritische, verfügbarkeitssensible Richtlinien verwenden.

Wählen Sie den Modus pro Validator im Dashboard oder über die API. Fehler werden über Audit-Logs und das Webhook-Ereignis custom_validator.failed sichtbar gemacht.

§ 08

SDK-Fehlerbehandlung

Sowohl sdk-js als auch execlave-sdk (Python) lösen ValidatorDeniedError aus — eine Unterklasse von PolicyBlockedError — wenn die Ablehnung von einem benutzerdefinierten Validator stammt. Fangen Sie die allgemeine Klasse für eine einheitliche UX ab oder die spezifische Klasse für validatorbewusste Meldungen.

import { ValidatorDeniedError, PolicyBlockedError } from '@execlave/sdk'; try {  await exe.enforcePolicy({    agentId: agent.id,    input,    tools: ['web_search'],  });  // Sicher, mit dem LLM-Aufruf fortzufahren  const answer = await llm.call(input);} catch (err) {  if (err instanceof ValidatorDeniedError) {    return `Blocked by ${err.validatorViolations[0].policyName}: ${err.validatorViolations[0].message}`;  }  if (err instanceof PolicyBlockedError) {    return `Blocked by policy: ${err.violations[0].message}`;  }  throw err;}
Benutzerdefinierte Validatoren (BYOV) — Execlave Docs