Was macht Operator-Approval-Loop?
Ein Agent, der mit externen Gegenübern kommuniziert, sollte niemals auf eigenes Urteil hin senden und den Betreiber intern auf dem Laufenden halten. Diese Skill definiert den Vertrag: Jeder ausgehende Entwurf wird als Verpflichtung abgelegt, ein Betreiber entscheidet über den genauen Text, und ein Lieferprotokoll beweist, was gesendet wurde.
Wann verwenden
- Ein Agent entwirft Antworten an Kunden, Lieferanten, Investoren oder Partner in einem gemeinsamen Kanal, per E-Mail oder Chat, und ein Mensch muss vor dem Senden genehmigen.
- Sie benötigen eine Prüfspur, die jede gesendete Nachricht mit dem genauen Entwurfstext, dem genehmigenden Betreiber und dem Entscheidungszeitpunkt verknüpft.
- Sie haben erlebt, dass eine veraltete Genehmigung einen neu verfassten Entwurf freigegeben hat oder zwei Worker dieselbe genehmigte Nachricht zweimal zugestellt haben.
- Entwürfe fragen immer wieder bei Gegenübern nach Fakten, die das Protokoll bereits enthält.
Funktionsweise
Objekte
| Objekt | Bedeutung |
|---|---|
| Verpflichtung (Obligation) | Eine Sache, die wir einem Gegenüber schulden. Status wechselt entworfen, dann genehmigt oder abgelehnt, dann gesendet. Trägt Richtung, Gegenüber, Kanal und einen updated_at-Epochenwert. |
| Entwurf (Draft) | Nebenreihe mit dem genauen Entwurfstext, einem SHA256 dieses Texts, Ursprungskoordinaten (Plattform, Kanal, Thread, Benutzer) und Priorität (P0 bis P3). Eine pro Verpflichtung, wird bei erneuter Ablage ersetzt. |
| Entscheidung (Decision) | Genehmigung oder Ablehnung durch einen Betreiber, erfasst mit Betreiber-ID, einem Nonce und der Entwurfsepoche, gegen die sie getroffen wurde. |
| Genehmigungssnapshot (Approval snapshot) | Unveränderlicher Text, Hash, Epoche und Ziel, aufgezeichnet vom bereits autorisierten Entscheidungsschreiber. Fehlende Snapshots können keinen Versand gewähren. |
| Anspruch (Claim) | Beständige Reservierung mit einem zufälligen Token und Status; maximal ein aktiver Anspruch pro Verpflichtung. |
| Zustellung (Delivery) | Protokollzeile, die einen Sende- oder Hinweisvorgang für ein (Verpflichtung, Entscheidung)-Paar belegt. |
Das Referenzschema befindet sich in references/approval-ledger.sql.
Ablage eines Entwurfs
- Eingaben bereinigen. Steuerzeichen entfernen, Leerzeichen in einzeiligen Feldern zusammenziehen und Längenbegrenzungen durchsetzen (Entwurf, Zusammenfassung, Kontext, Gegenüber). Leere oder zu große Felder werden abgelehnt, nicht stillschweigend abgeschnitten.
- Baseline-Prüfung (siehe unten) ausführen. Sie kann die Ablage verweigern.
- Entwurfstext mit SHA256 hashen. Das Hash-Präfix wird in die Zusammenfassung aufgenommen, damit das Genehmigungsfeld zeigt, welchen Text es genehmigt.
- Upsert. Wenn bereits eine offene, entworfene Verpflichtung für dasselbe (Gegenüber, Kanal) existiert, den Entwurfssidecar ersetzen und
updated_atder Verpflichtung vorrücken. Dieser Fortschritt ist die Epochenrotation: Jede Entscheidung, die auf die alte Epoche verweist, kann den neuen Text nicht mehr freigeben. Andernfalls eine neue Verpflichtung mit Statusentworfeneinfügen. - Die Ablagequittung nur an ein konfiguriertes, verifiziertes internes Betriebsziel weiterleiten. Wenn der Ursprung dieses interne Ziel ist, dort quittieren. Niemals still sein bedeutet interne Berichterstattung, keine automatische externe Antwort. Hashes von Entwürfen, Genehmigungsstatus, Betreiberidentität und Workflow-Metadaten aus für Gegenüber sichtbaren Kanälen heraushalten. Unbekannte oder nicht klassifizierte Ursprünge bleiben still; eine direkte Nachricht ist nicht automatisch intern.
Wenn ein verifiziertes internes Ziel nicht verfügbar ist, das Ablageergebnis im internen Tool-Ergebnis oder der Betreiberoberfläche aufbewahren. Niemals auf einen externen oder unbekannten Ursprung zurückfallen. Ein Tool-Ergebnis, das Außenstehenden zugänglich ist, ist keine interne Oberfläche.
Die Ablage eines Entwurfs autorisiert keine externe Antwort. Jede richtlinienkonforme klärende Frage oder neutrale Antwort ist eine separate ausgehende Entscheidung, die den bestehenden Einschränkungen (Erwähnung, Kanal, Nur-Entwurf, Eingefroren und Nie) in der Gegenüber-Kanal-Disziplin unterliegt. Sie darf keine internen Genehmigungsmetadaten preisgeben.
Baseline-Prüfung
Vor der Ablage eines Entwurfs die aktuelle Baseline für den Gegenüber abfragen (ein temporäres Protokoll, Vertragsspeicher oder CRM):
- Signierter oder zugestellter Vertrag in den Aufzeichnungen: Ablage mit den Nachweisen und einer Empfehlung verweigern. Einen Gegenüber nach Spezifikationen zu fragen, nachdem ein Vertrag unterschrieben wurde, ist genau der Fehler, den diese Prüfung verhindern soll.
- Betreiberüberschreibung:
force_despite_signed_contractlässt die Ablage zu und fügt[BASELINE_OVERRIDE_SIGNED_CONTRACT]in den Entwurfskontext ein. - Prüfdienst nicht erreichbar: Die Ablage wird fortgesetzt und der Kontext erhält den Vermerk
[BASELINE_CHECK_UNAVAILABLE]. Das Feld sieht, dass die Abschaltung deaktiviert war. Ausfälle deaktivieren die Prüfung niemals stillschweigend. - Wenn Fakten verfügbar sind, die aktuellsten als
[BASELINE FAKTE: ...]-Zusammenfassung an den Kontext anhängen, damit der Entwurf mit dem aktuellen Wahrheitsstand eintrifft.
Entscheidungsfindung
Das Genehmigungsfeld listet Verpflichtungen mit Status entworfen und Richtung wir_schulden_ihnen auf. Genehmigen oder Ablehnen schreibt eine Entscheidungszeile, die die Entwurfsepoche (draft_updated_ts) trägt, und ändert den Verpflichtungsstatus in derselben Transaktion. Eine Entscheidung, deren Epoche nicht mit dem aktuellen updated_at übereinstimmt, ist veraltet und darf nichts freigeben.
Für eine bereits autorisierte Genehmigungsentscheidung fügt dieselbe Transaktion eine unveränderliche obligation_approval_snapshots-Zeile ein: Entscheidungs- und Verpflichtungs-IDs, aktuelle Entwurfsepoche, genauer Text und SHA-256, Plattform/Kanal/Thread sowie Art draft_sent. Der Entscheidungsschreiber muss vor dem Schreiben eine Autorisierung nachweisen; die Referenz authentifiziert keinen Betreiber und erzeugt keine Entscheidung. Eine automatische Genehmigungsrichtlinie wird durch die Referenz weder aktiviert noch erweitert. Legacy-Entscheidungen ohne Snapshots erfordern einen expliziten Abgleich oder eine neue Genehmigung; niemals rückwirkend eine Berechtigung aus dem aktuellen veränderbaren Entwurf ableiten.
Zustellung
Die SQLite-Referenz ist references/approval_claims.py. Sie gewährt die Versandberechtigung, ruft aber niemals den Transport auf. Verwenden Sie eine vorhandene lokale Referenzdatenbank, die aus dem SQL-Fixture initialisiert wurde; das Modul wendet keine Schema- oder Produktionsmigrationen an. Nur ein vertrauenswürdiger Entscheidungsschreiber darf Genehmigungsdatensätze befüllen. Alle Schreiber müssen Fremdschlüssel und rekursive Trigger aktivieren und die Schema-Sicherungen beachten; administrative Datenbankmanipulation liegt außerhalb dieses Modells.
- Gebundene genehmigte Entwürfe ermitteln. Die Ermittlung ist keine Berechtigung.
claim()öffnet eine eigeneBEGIN IMMEDIATE-Transaktion, validiert die aktuell genehmigte Epoche, den genauen Text, den berechneten SHA-256 und das vollständige Ziel anhand des Snapshots und fügt einen eindeutigen Anspruch ein, bevor es seinen Token zurückgibt. Ein Konflikt stoppt den Worker vor dem Transport. Abgeschlossene Quittungen können nicht erneut beansprucht werden. begin_dispatch()validiert die Bindung erneut und ändert atomarclaimedindispatchingunter Verwendung des Tokens. Nur der gewinnende Aufrufer erhält nach dem Commit den genauendraft_textund das Ziel. Niemals Text neu generieren, einen veränderbaren Sidecar für den Transport erneut lesen oder die Nutzlast für einen weiteren Versuch wiederverwenden. Eine verschachtelte Aufrufertransaktion wird abgelehnt; die Berechtigung darf nicht von einem späteren Commit des Aufrufers abhängen. Es bleibt keine Datenbanktransaktion über den Transport hinweg geöffnet.- Ein bestätigtes erfolgreiches Ergebnis geht an
complete(), das atomar die Zustellungskoordinate aufzeichnet, den Anspruch als zugestellt markiert und die Verpflichtung aufgesendetsetzt. Identische Abschlüsse sind No-Ops; widersprüchliche Koordinaten schlagen fehl. Der UNIQUE-Key der Quittung dedupliziert Datensätze, nicht vorherige externe Effekte. - Ausnahmen, Zeitüberschreitungen, Worker-Ausfall nach begin_dispatch oder fehlgeschlagene Quittungspersistenz hinterlassen einen blockierten Versuch.
mark_unknown()zeichnet Unsicherheit auf. Unbekannte Ansprüche verfallen nicht, werden nicht wieder geöffnet, nicht automatisch wiederholt und erlauben keine andere Entscheidung für diese Verpflichtung, sie zu umgehen. Ein vertrauenswürdiger Aufrufer kannreconcile()mit bestätigter erfolgreicher Koordinate und Nachweis verwenden; das Modul überprüft diesen Nachweis nicht. Eine fehlende Quittung ist kein Beleg für Nicht-Zustellung.
Die Garantie ist ein automatischer Zustellungsversuch pro genehmigter Entscheidung, nicht genau-einmalige externe Zustellung. Ein Absturz nach begin_dispatch, aber vor dem Transport, kann zu null Sendungen und einem gehaltenen Anspruch führen. Die Freigabe eines unbekannten Ergebnisses für einen neuen Versuch würde die Ausgrenzung des ursprünglichen Ausführers und die Überprüfung der Anbietersemantik erfordern; diese Referenz stellt bewusst keine solche Wiederholungsoperation bereit.
| Anspruchsstatus | Erlaubte Folgezustände |
|---|---|
| claimed | dispatching oder storniert vor Versand |
| dispatching | delivered oder unknown |
| unknown | delivered nur durch vertrauenswürdigen Abgleich |
| delivered, cancelled | endgültig; Entscheidungsschlüssel kann nicht wiederverwendet werden |
Während ein Anspruch aktiv ist, sperren Datenbankwächter Schreibvorgänge auf Verpflichtung, Entwurf und Entscheidung, einschließlich Ersetzungen. Snapshots und Ansprüche können nicht gelöscht werden. Stornieren Sie einen beanspruchten Vorgang mit seinem Token vor der erneuten Ablage; der veraltete Token gewährt dann nichts. Nach Beginn des Versands halten Sie neue Bearbeitungen oder Widerrufe für den Abgleich zurück. Dies serialisiert Änderungen, anstatt vorzutäuschen, einen laufenden Vorgang zurückzurufen.
Abgelehnte Entscheidungen und Legacy-Zeilen ohne Entwurfssidecars/Snapshots gelangen nie in diesen externen Entwurfs-Sendepfad. Melden Sie sie auf der internen Betreiberoberfläche zur manuellen Bearbeitung. Interne Quittungsfußzeilen bleiben intern:
genehmigt von <Betreiber> · quittung <entscheidung_id> · entwurf sha256 <präfix>.
Niemals bereits genehmigten externen Text ändern, um Workflow-Metadaten anzuhängen.
Fokussierte lokale Validierung verwendet temporäre Datenbanken, separate Verbindungen und einen simulierten Versuchszähler, keinen Anbieter oder echte Nachricht:
python3 -m unittest discover -s tests/skills -p 'test_approval_delivery_claims.py'.
Die Tests erfordern Python 3.11+ mit SQLite-Serialisierungsunterstützung; die Referenz verwendet nur die Standardbibliothek. Die bestehenden Desk-Pattern-Vertragsprüfungen bleiben ein separater Kompatibilitätstest.
Zeitlich begrenzte automatische Genehmigung (optional)
Ein Entwurf kann auto_send_after (Epochensekunden) tragen. Ein Sweep genehmigt Entwürfe, deren Frist ohne Entscheidung abgelaufen ist, zeichnet den Betreiber auto-ttl auf, und die Zustellung erfolgt dann über den normalen Pfad. Betreiberaktionen gewinnen immer: Eine Entscheidung ändert den Status, bevor der Sweep ihn sieht, und eine erneute Ablage rotiert die Epoche und verschiebt oder löscht die Frist. Der Sweep überprüft Status und Epoche innerhalb der Schreibtransaktion erneut, sodass ein Wettlauf als No-Op endet. Entwürfe ohne Frist bleiben für immer streng gesperrt.
Signalbindung
Ein Entwurf kann die eingehende Verpflichtung benennen, die er beantwortet (signal_obligation_id). Dies ist die einzige wahrheitsgemäße Verbindung für die Latenzmessung (eingehendes Signal bis zum entworfenen Antworttext) und ermöglicht der SLA-Überprüfung, diesen eingehenden Eintrag als beantwortet zu betrachten. Die Ablage ablehnen, wenn die referenzierte Zeile nicht existiert.
Beispiele
Entwurf ablegen
file_request(
draft="Vielen Dank, wir können den Slot bis Freitag freihalten. Welches Startdatum passt?",
counterparty="acme-lieferant",
context="Antwort auf Frage zum Lieferfenster",
origin_platform="slack", origin_channel="#acme-shared",
origin_thread="1712345678.000100", priority="P1",
signal_obligation_id=412)
-> {obligation_id: 431, draft_sha256: "9f2c...", refiled: false}
Das konfigurierte, verifizierte interne Betriebsziel sieht:
Entwurf zur Genehmigung eingereicht (P1, sha 9f2c8a1b). Warte auf Betreiber.
Der für den Gegenüber sichtbare Ursprungskanal erhält keine Ablagenachricht. Wenn kein verifiziertes internes Ziel verfügbar ist, verbleibt die Quittung im internen Tool-Ergebnis oder der Betreiberoberfläche, ohne externen Rückfall.
Erneute Ablage nach einer Lenkung
Der Betreiber bittet um einen kürzeren Entwurf. Die erneute Ablage für dasselbe (Gegenüber, Kanal) gibt refiled: true zurück, Sidecar-Text und Hash ändern sich, und updated_at rückt vor. Ein Genehmigungsklick auf der alten Feldoberfläche trägt die alte Epoche und wird ignoriert.
Prüfverweigerung
DeskApprovalError: Die Baseline-Prüfung hat diesen Entwurf abgelehnt: Das Protokoll zeigt einen
unterzeichneten Vertrag für 'acme-lieferant'. Nachweis: Rahmenvertrag ausgeführt
am 2026-08-14. Empfehlung: Nicht fragen. Erneut ablegen mit
force_despite_signed_contract=true, wenn dies wirklich ein neuer Thread ist.
Zustellungsfußzeile in einem internen Kanal
Bestätigt für Freitag, Startdatum 2026-09-08.
genehmigt von operator-a · quittung 118 · entwurf sha256 9f2c8a1b2d3e4f50
Zu testende Invarianten
- Ablagequittungen gehen nur an konfigurierte, verifizierte interne Betriebe; der Ursprung erhält eine nur, wenn er dieses verifizierte interne Ziel ist.
- Ein unbekannter Ursprung bleibt still. Ein nicht verfügbares internes Ziel verwendet das interne Tool-Ergebnis oder die Betreiberoberfläche, ohne externen Rückfall.
- Zweimalige Ablage für dasselbe (Gegenüber, Kanal) ergibt eine Verpflichtung, zwei Epochen.
- Eine Entscheidung mit einer veralteten Epoche führt nie zu einer Zustellungszeile.
- Zwei konkurrierende Anspruchsberechtigte ergeben eine Versandberechtigung; Verlierer versuchen nie einen Transport.
- Unbekannte Ergebnisse und fehlgeschlagene Quittungspersistenz aktivieren nie einen automatischen Wiederholungsversuch.
- Erfolgreicher Abschluss zeichnet die Quittung und den Sende status in einer Transaktion auf.
- Eine geänderte Epoche, Text, Hash oder Ziel können keinen Anspruch erwerben oder starten.
- Aktive Ansprüche blockieren die erneute Ablage; nur eine Stornierung vor dem Versand kann diese Sperre aufheben.
- Nicht verfügbare Prüfung setzt den Marker; Prüfung mit Unterschrift verweigert ohne Force.
- Auto-ttl feuert nie gegen Text, den der Betreiber inzwischen erneut abgelegt hat.