Decision Engine (POST /v1/decisions)
Entscheidungen statt Antworttexte — Zustand und Fragen mit festen Optionen rein, Wahrscheinlichkeiten raus. Private Preview.
Private Preview. Der Endpunkt ist stabil im Vertrag, aber neu im Betrieb: Limits, Preise und Modellversionen können sich in der Preview noch ändern. Wir kündigen Änderungen im Changelog an.
Die Decision Engine beantwortet Fragen mit festen Antwortmöglichkeiten — welches Team ist zuständig, wie dringend ist das, muss ein Mensch prüfen? Sie erzeugt dafür keinen Text: für jede Frage rechnet das Modell genau einen Vorwärtsdurchlauf und wir lesen die Wahrscheinlichkeit jeder erlaubten Option direkt ab. Das ist der Grund, warum eine Entscheidung warm in Millisekunden zurückkommt, wo eine Chat-Antwort Sekunden braucht.
Gemessen am 2026-09-20 von einem Rechner in Jena aus, warm, Ticket-Text mit vier
Optionen: 65 ms je Frage auf sovr-decision-v1, 198 ms auf sovr-decision-v2;
vier Fragen gleichzeitig 123 ms bzw. 397 ms. Eine Chat-Antwort zum selben
Text braucht auf denselben Modellen 5–30 s. Diese Zahlen sind unsere Messung, keine
Zusage — sie hängen vom Anbieter, der Last und der Länge des Zustands ab.
Base-URL: https://sovrgpt.com/api/v1 · Scope: decisions · Auth: Authorization: Bearer sov_…
Modelle
| Modell | Betrieb | Bilder | Charakter |
|---|---|---|---|
sovr-decision-v1 (Vorgabe) | Deutschland, freigegebene Infrastruktur (BSI C5) | ja | sehr schnell, sehr entschieden — Wahrscheinlichkeiten fast immer nahe 1,0 oder 0 |
sovr-decision-v2 | EU (Irland/Finnland), Zero-Retention vertraglich | ja | feiner aufgelöste Wahrscheinlichkeiten — für Schwellenwert-Logik |
Beide Versionen laufen auf offenen Grundmodellen unter unserer Steuerung; welche
Version ohne Angabe gilt und wo sie rechnet, steht je Organisation unter
GET /v1/decisions/models. Ein Owner oder Admin kann das unter
Decision Engine → Einstellung dieser Organisation ändern.
Eine Entscheidung anfragen
curl https://sovrgpt.com/api/v1/decisions \
-H "Authorization: Bearer $SOVR_KEY" -H "content-type: application/json" \
-d '{
"preset": "ticket-routing-v1",
"state": "Seit heute früh kann ich mich nicht mehr anmelden. Außerdem wurde meine Rechnung doppelt abgebucht — bitte prüfen Sie das dringend."
}'Antwort (gekürzt, echte Messung vom 2026-09-20 auf sovr-decision-v2):
{
"object": "decision",
"id": "dec_3f1c…",
"status": "completed",
"model": { "id": "sovr-decision-v2", "runtime": "…", "operator": "TensorX Ltd", "country": "IE", "via": "platform" },
"preset": { "id": "ticket-routing-v1", "version": "1.0.0" },
"answers": {
"team": {
"type": "choice",
"value": "support",
"probabilities": { "support": 0.6512, "billing": 0.0367, "sales": 0.0044, "unclear": 0.3076 },
"max_probability": 0.6512,
"normalized_entropy": 0.58,
"calibration": { "status": "uncalibrated" },
"abstain": true,
"abstain_reasons": ["review_only_policy", "calibration_unavailable"],
"diagnostics": { "label_mass": 0.9967, "low_label_mass": false, "missing_labels": [] }
},
"urgency": { "type": "score", "value": 3, "expected_index": 3.29, "normalized_score": 0.82, "probabilities": { "0": 0.0002, "1": 0.0003, "2": 0.0017, "3": 0.7042, "4": 0.2936 }, "…": "…" },
"needs_human": { "type": "binary", "value": true, "probability_true": 0.9933, "…": "…" },
"language": { "type": "choice", "value": "de", "probabilities": { "de": 0.9993, "en": 0.0006, "other": 0 }, "…": "…" }
},
"policy": { "mode": "review_only", "threshold": 0.85 },
"usage": { "input_tokens": 860, "output_tokens": 4, "evaluated_questions": 4, "forward_passes": 4 },
"timing_ms": { "total": 412, "inference_max": 397, "inference_sum": 688 }
}Anfrage
| Feld | Pflicht | Bedeutung |
|---|---|---|
state oder messages | genau eines | Der zu beurteilende Zustand: Text, JSON-Objekt/-Array — oder ein Gesprächsverlauf ([{role, content}], nur Text). Wird als Daten behandelt, nie als Anweisung. |
questions oder preset | genau eines | Eigene Fragen (siehe unten) oder ein hinterlegtes Paket (GET /v1/decisions/presets). |
model | nein | sovr-decision-v1 oder sovr-decision-v2. Ohne Angabe: Vorgabe der Organisation. |
images | nein | Bis zu 2 Bilder als [{ "data_url": "data:image/png;base64,…" }], je ≤ 4 MB. Nur data:-Adressen — der Dienst lädt keine fremden URLs. |
policy | nein | { "mode": "review_only" } (Vorgabe) oder { "mode": "threshold", "threshold": 0.85 }, siehe „Freigabe". |
request_id | nein | Frei wählbar, wird gespiegelt (Korrelation). |
Fragetypen
{
"team": { "type": "choice", "instructions": "Welches Team zuerst?", "options": [ { "id": "support", "description": "Technik" }, { "id": "billing" }, { "id": "unclear", "description": "nicht zuordenbar" } ] },
"urgency": { "type": "score", "instructions": "Wie dringend?", "levels": ["nicht", "wenig", "normal", "dringend", "sofort"] },
"needs_human": { "type": "binary", "instructions": "Muss ein Mensch prüfen?", "true_description": "ja", "false_description": "nein" }
}| Typ | Ergebnis |
|---|---|
choice — 2–26 Optionen | value = Options-Id mit der höchsten Wahrscheinlichkeit, probabilities über alle Optionen |
score — 2–10 geordnete Stufen | value = wahrscheinlichste Stufe (0-basiert), expected_index = Σ p·i, normalized_score = expected/(n−1). Ein Score ist keine physikalische Skala. |
binary | value = true/false, probability_true |
Reihenfolge zählt: Optionen und Fragen werden in Quellreihenfolge bewertet. Ein Modell kann auf die Reihenfolge reagieren — wer das ausschließen will, prüft mit vertauschten Optionen.
Grenzen (Preview)
1–16 Fragen · Zustand ≤ 16 000 Zeichen · Frage ≤ 1 000 Zeichen · Beschreibung ≤ 512
Zeichen · Rumpf ≤ 64 KiB. Zu groß → 413. Unbekannte Felder werden abgelehnt
(400), nicht ignoriert — ein tenant_id oder tools im Rumpf soll nicht so
aussehen, als wirke es.
Was die Zahlen bedeuten — und was nicht
probabilitiesist die Verteilung über Ihre Optionen.max_probability: 0.92heißt: das Modell gibt dieser Option 92 % der Masse. Es heißt nicht, dass sie zu 92 % richtig ist.calibration.statusist in der Preview immeruncalibrated.diagnostics.label_masssagt, wie viel Wahrscheinlichkeit überhaupt auf den erlaubten Optionen lag. Liegt sie unter 0,5, wollte das Modell etwas anderes schreiben — dann ist die Verteilung ein Artefakt, undlow_label_massisttrue.sovr-decision-v1antwortet meist mit 1,0 / 0 / 0 — sehr entschieden, wenig Zwischentöne. Für „unsicher → Mensch prüft" ist dort die fachliche Option (unclear,other) der verlässlichere Weg als eine Prozent-Schwelle.
Freigabe (abstain)
abstain: true heißt: nicht ungeprüft automatisieren. Die Bewertung ist trotzdem
vollständig — sie ist eine Empfehlung an Ihren Workflow, keine Handlung.
review_only(Vorgabe): jede Antwort trägtabstain: true.threshold:abstainfällt auffalse, wennmax_probability ≥ threshold, die Label-Masse belastbar ist und die gewählte Option nichtunclear/other/unknownheißt. Die Gründe stehen immer inabstain_reasons.
Verbindliche Freigaben, Zugriffsrechte und Aktionen bleiben bei Ihrer Anwendung. Eine typisierte Falschantwort ist eine Falschantwort.
Fehler
| Status | code | Bedeutung |
|---|---|---|
| 400 | invalid_request_error, invalid_json, images_unsupported | Rumpf ungültig |
| 401 | — | Schlüssel fehlt, ungültig oder widerrufen |
| 402 | org_spend_limit, user_spend_limit | Ausgabenlimit erreicht |
| 403 | missing_scope | Schlüssel ohne Scope decisions |
| 404 | unknown_preset, model_not_found | |
| 413 | request_too_large | |
| 502 / 504 | upstream_error, upstream_timeout | Laufzeit hat nicht brauchbar/rechtzeitig geantwortet — keine Teilantwort |
| 503 | runtime_unavailable | In dieser Umgebung ist keine gemessene Laufzeit erreichbar — es wird nie still ein anderes Modell genommen |
Datenschutz
Zustand, Fragen und Antworten werden nicht gespeichert. Abgerechnet werden
Eingabetoken (und ein Token je Frage); nur diese Zahlen stehen in Ihrem Verbrauch.
Bilder werden nicht nachgeladen: nur data:-Adressen sind erlaubt. Der Verarbeitungsort
steht in jeder Antwort (model.operator, model.country).
Weitere Endpunkte
GET /v1/decisions/presets— hinterlegte Fragenpakete mit Beispielzustand.GET /v1/decisions/models— die Versionen dieser Organisation, Vorgabe, Betreiber, Land, Messwerte, Limits.
Ein Playground mit echter Inferenz liegt eingeloggt unter Decision Engine in der Seitenleiste.