Files
ClawdDotNet/docs/Staging-Konzept.md
T

5.1 KiB

Staging-Freigabe für irreversible Aktionen

Setzt A2 aus der Roadmap um (F-A1 + S4). Irreversible Aktionen werden gestaged statt ausgeführt: Vorschlag → Review im Hauptfenster → Freigabe/Ablehnung. Aufbauend auf dem Taskboard (A1, Fortsetzung nach Freigabe) und dem Audit-Log (A3, Approval-Records).

Sicherheitswirkung: Eine Prompt-Injection (K2) kann dann nur noch einen Vorschlag erzeugen, keine Ausführung.

Das Gate wird zum Durchsetzungspunkt (S4)

Das bisher wirkungslose PermissionGate (es prüfte nur, ob ein Tool zugewiesen ist) wird zur zentralen Stelle: Policy-Prüfung, Staging-Entscheidung und Audit-Hook an einer Stelle (AgentEngine.ExecuteToolCallAsync), statt ad-hoc in jedem Tool. S4 geht hier auf.

Policy: auto | approve | deny pro Tool/Aktion

Je (Tool, Aktion) eine Entscheidung:

  • auto — läuft wie bisher.
  • approve — wird gestaged; die Ausführung wartet auf eine menschliche Freigabe.
  • deny — wird gar nicht erst vorgeschlagen, sondern abgelehnt.

Auflösung vom Speziellen zum Allgemeinen: Tool.AktionTool → Standard (auto). Die „Aktion" ist das action-Argument des Aufrufs (die meisten Tools haben es).

Eingebaute Standardregeln (nach Sichtung der Tools, überschreibbar per Konfiguration) — genau die in der Roadmap genannten irreversiblen Aktionen:

Tool.Aktion Standard
Mail.send approve
Telegram.send_message approve
Database.insert, Database.upsert approve
FileRW.delete approve
FTP.upload, FTP.delete approve
alles andere auto

Lesende Aktionen (Mail.read_inbox, FileRW.read, Database.query, …) bleiben auto — Staging soll schützen, nicht lähmen.

Plan-Freeze

Freigegeben wird ein eingefrorener, konkreter Aufruf: Tool, Aktion und die exakten Argumente zum Zeitpunkt des Stagings. Ausgeführt wird genau das Eingefrorene (der gespeicherte Argument-JSON), nie eine nachträglich veränderte Fassung. Jede Änderung wäre eine neue Freigabe.

Das ist auch der Grund, warum der Agent den Aufruf nicht nach der Freigabe erneut formuliert (er könnte etwas anderes bauen) — der eingefrorene JSON wird direkt an das Tool gegeben.

Fortsetzung nach Freigabe — kein pausierter Lauf

Die tragende Architektur-Vorgabe (aus der Roadmap-Einstufung): Kein pausierter, im Speicher gehaltener Lauf. Der Ablauf:

  1. Vorschlag. Der Agent ruft eine approve-Aktion auf. Das Gate führt sie nicht aus, sondern legt einen Pending-Datensatz an (eingefrorener Aufruf) und gibt dem Agenten „Zur Freigabe vorgelegt (#id)" als Tool-Ergebnis zurück. Der Lauf endet regulär — der Agent schließt ab, nichts hängt im Speicher.
  2. Review. Ein Mensch sieht die offenen Vorschläge im Hauptfenster und entscheidet. 3a. Freigabe. Der eingefrorene Aufruf wird direkt ausgeführt (standalone, nicht über einen Chat-Lauf). Das Ergebnis wird festgehalten, und ein Folge-Task (A1) weckt den Agenten: „Deine Aktion X wurde freigegeben und ausgeführt, Ergebnis: Y — mach weiter." Der Scanner stellt ihn zu (ChatAsync, bestehender Kontext). 3b. Ablehnung. Ein Folge-Task weckt den Agenten mit der Ablehnung (samt Grund).

Echtes Suspend/Resume eines laufenden ChatAsync wäre Fable-Terrain — und ist mit dieser Vereinfachung unnötig.

Approval-Records (A3)

Jede Entscheidung — Freigabe wie Ablehnung — wird an zwei Stellen verankert:

  • Im Staging-Datensatz selbst: Status, DecidedBy, DecidedAt, Ergebnis-Verweis bzw. Ablehnungsgrund.
  • Als Audit-Eintrag (A3): Tool, Ausgang, source: approval, „Freigegeben von …" bzw. „Abgelehnt von …". Die Herkunft stempelt auch hier das System, nicht der Agent.

Der Vorschlag selbst wird beim Anlegen als Audit-Eintrag mit Status Staged notiert — so ist die ganze Kette (Vorschlag → Entscheidung → Ausführung) im Log nachvollziehbar.

Nebenläufigkeit

Zwei Reviewer dürfen nicht denselben Vorschlag doppelt freigeben. Der Übergang pending → approved/rejected ist ein atomares, bedingtes UPDATE (dieselbe Claim-Technik wie beim Taskboard): Genau einer gewinnt, der zweite Klick läuft ins Leere. Erst nach gewonnenem Übergang wird der eingefrorene Aufruf ausgeführt.

Verdrahtung

  • StagingGate (Policy + Anlegen des Vorschlags) hängt optional an der Engine — ohne es läuft alles wie bisher (auto).
  • Der eingefrorene Aufruf wird über IFrozenCallExecutor (von der Engine implementiert) ausgeführt: gültiger Tool-Kontext, aber ohne LLM-Schleife.
  • StagingService (Freigabe/Ablehnung) nutzt Executor, Audit und das Taskboard für den Folge-Task. Es ist die API, die die Review-Oberfläche aufruft.

Offen

  • Review-Oberfläche im Hauptfenster (Liste der offenen Vorschläge, Freigeben/Ablehnen) — die Dienst-API steht bereit; die WinForms-Ansicht ist die verbleibende Integration.
  • Output-Scrubbing greift auch hier auf den gespeicherten Argument-JSON, sobald es steht (eigener Roadmap-Punkt).
  • Orders (Handelsaufträge) reihen sich später als weitere approve-Aktionen ein.