92 lines
4.3 KiB
Markdown
92 lines
4.3 KiB
Markdown
# Audit-Log & Receipts — Nachvollziehbarkeit
|
|
|
|
Setzt A3 aus der [Roadmap](Roadmap.md) um (F-A2). Zwei zusammengehörige Dinge:
|
|
|
|
- **Audit-Log** — ein Eintrag je Tool-Aufruf: wer, wann, welches Tool, mit welchem
|
|
Ausgang.
|
|
- **Receipts** — ein Abschluss-Beleg je Lauf: Ergebnis, Schritte, Tokens, Kosten,
|
|
verknüpft mit dem Task.
|
|
|
|
A3 ist das Fundament für A2 (jede Staging-Entscheidung wird als Datensatz verankert)
|
|
und für C7 („Kosten pro Ergebnis", fällt aus den Receipts ab). Die Tool-Fehlerquote aus
|
|
der Leistungsanalyse liest sich direkt aus dem Log.
|
|
|
|
## Warum eigene Tabellen, nicht der State-Store
|
|
|
|
Dieselbe Überlegung wie bei Gedächtnis und Taskboard: `IStateStore` ist Schlüssel-Wert.
|
|
Ein Log, das man nach Lauf, Task oder Tool filtern und dessen Fehlerquote man auswerten
|
|
will, braucht typisierte Spalten. Zwei Tabellen auf dem vorhandenen
|
|
[`SqliteStorage`](../src/ClawdDotNet.Core/Storage/SqliteStorage.cs): `AuditLog` und
|
|
`RunReceipts`.
|
|
|
|
## Provenienz — von der Engine gestempelt, nie vom Agenten behauptet
|
|
|
|
Die entscheidende Regel (aus dem OpenAlice-Provenance-Konzept):
|
|
|
|
- **Herkunft stempelt die Engine.** `AgentId`, `Model` und `Source` kommen aus dem
|
|
Wissen der Engine über den Lauf, nicht aus dem Tool-Ergebnis. Ein Tool kann seine
|
|
Herkunft nicht fälschen, weil es sie gar nicht schreibt.
|
|
- **Einträge sind unveränderlich.** Das Repository hat kein Update und kein Delete —
|
|
eine Korrektur ist ein neuer Eintrag. Das ist die eigentliche Zusage, keine fehlende
|
|
Funktion.
|
|
- **Unbekanntes wird als unbekannt markiert, nicht geraten.** Fehlt die Quelle, steht
|
|
`unknown`, nicht ein plausibel geratener Kanal.
|
|
- **Worker-Typ und Session sind getrennt.** `Model` (das ausführende Modell) und
|
|
`Source` (die verantwortliche Session: `webview`, `telegram`, `task`, `agentcomm`,
|
|
`job`, `direct`) sind verschiedene Begriffe und stehen in eigenen Spalten.
|
|
|
|
## Audit-Log
|
|
|
|
Gestempelt an genau einer Stelle: `AgentEngine.ExecuteToolCallAsync` — dort, wo jeder
|
|
Tool-Aufruf durchläuft. Je Aufruf ein Eintrag mit Ausgang:
|
|
|
|
| Status | Wann |
|
|
|---|---|
|
|
| `Ok` | Tool lief und lieferte ein Ergebnis |
|
|
| `Error` | Tool meldete einen Fehler oder warf |
|
|
| `Denied` | das `PermissionGate` hat abgelehnt |
|
|
| `NotFound` | Tool dem Agenten nicht zugewiesen/unbekannt |
|
|
|
|
Ein Abbruch (Cancellation) wird **nicht** protokolliert — der Aufruf kam nicht zum
|
|
Abschluss. Die Argumente werden roh, aber gekappt abgelegt (4 000 Zeichen); die
|
|
Ausgangsnotiz kurz (500).
|
|
|
|
**Best effort:** Ein Fehler beim Schreiben des Audits darf den Lauf nie scheitern
|
|
lassen — dieselbe Linie wie bei der Verbrauchserfassung. Der Eintrag wird geschrieben,
|
|
nachdem die eigentliche Arbeit getan ist.
|
|
|
|
## Receipts
|
|
|
|
Je Lauf ein Beleg, geschrieben beim Abschluss von `RunAsync`/`ChatAsync` (neben der
|
|
vorhandenen `RunUsage`-Erfassung). Er trägt Status, Schritte, Prompt-/Completion-/
|
|
Cached-Tokens, geschätzte Kosten (aus dem `ModelPricingCatalog`, mit
|
|
`CostIsKnown`-Flag) und einen kurzen Ergebnis-Verweis.
|
|
|
|
**Verknüpfung `RunUsage` ↔ Task:** Der Receipt trägt die `TaskId`, wenn der Lauf aus dem
|
|
Taskboard kam — der `EngineTaskDispatcher` reicht sie (samt `source: task`) durch. Damit
|
|
ist „Kosten pro Ergebnis" (C7) ein Abfallprodukt: `ListReceiptsForTaskAsync` liefert
|
|
alle Belege zu einem Task.
|
|
|
|
## RunId — die Klammer
|
|
|
|
Jeder Lauf bekommt zu Beginn eine `RunId` (GUID). Alle Audit-Einträge **und** der
|
|
Receipt eines Laufs tragen sie. So lässt sich ein Lauf lückenlos rekonstruieren:
|
|
`ListForRunAsync(runId)` gibt die Aufrufe in Reihenfolge, `GetReceiptForRunAsync(runId)`
|
|
den Abschluss.
|
|
|
|
## Verdrahtung
|
|
|
|
`IAuditRepository` ist optional (wie Gedächtnis und Taskboard): ohne Repo läuft die
|
|
Engine unverändert. In `Program.cs` wird ein `SqliteAuditRepository` auf der Instanz-DB
|
|
erzeugt und der Engine übergeben.
|
|
|
|
## Offen
|
|
|
|
- **Output-Scrubbing** — die `Arguments` können Secrets enthalten. Das zentrale
|
|
Maskieren bekannter Secret-Werte (eigener beschlossener Roadmap-Punkt) greift, sobald
|
|
es steht; der Andockpunkt (`ExecuteToolCallAsync`) ist derselbe.
|
|
- **Review-Oberfläche** — die Anzeige/Durchsicht des Logs und der Receipts gehört zu A2
|
|
(Staging-Review im Hauptfenster); die Abfragemethoden dafür stehen bereit.
|
|
- **Export** — ein JSONL-Export des Logs wäre für externe Auswertung nützlich (später,
|
|
passt zum A6-Spiegel).
|