218 lines
9.7 KiB
Markdown
218 lines
9.7 KiB
Markdown
## Das eigentliche Problem
|
||
|
||
Munin schickt jedem Werkzeug eine kurze Gebrauchsanleitung mit. Viele Werkzeuge
|
||
gewichten sie aber schwach. **Ohne eigene Anweisung antwortet ein Agent lieber
|
||
aus seinem eigenen Wissen**, statt im Gedächtnis nachzusehen, und schreibt
|
||
Neues, ohne vorher zu suchen.
|
||
|
||
Abhilfe schafft ein kurzer Block im Projekt- oder Systemprompt.
|
||
|
||
## Wohin der Projektprompt gehört
|
||
|
||
Jedes Werkzeug liest seine Anweisungen aus einer anderen Datei:
|
||
|
||
| Werkzeug | im Projekt | persönlich, für alle Projekte |
|
||
|---|---|---|
|
||
| OpenCode | `AGENTS.md` (ersatzweise `CLAUDE.md`) | `~/.config/opencode/AGENTS.md` |
|
||
| Cline | `AGENTS.md` oder `.clinerules/` | `~/Documents/Cline/Rules/` |
|
||
| Claude Code | `CLAUDE.md` | `~/.claude/CLAUDE.md` |
|
||
| eigene Anwendung | Systemprompt | |
|
||
|
||
**Mehrere Werkzeuge im Team:** Den Block in **eine** `AGENTS.md` im
|
||
Projektverzeichnis schreiben. OpenCode und Cline lesen sie direkt. Claude Code
|
||
liest `AGENTS.md` nur, wenn es keine `CLAUDE.md` gibt (und erst in neueren
|
||
Fassungen). Sicher ist deshalb: in die `CLAUDE.md` die Zeile `@AGENTS.md`
|
||
schreiben, gegebenenfalls als einzige Zeile. So steht der Block an genau einer
|
||
Stelle und läuft nicht auseinander.
|
||
|
||
**Persönlich statt im Projekt:** Ist Munin global eingerichtet (Claude Code mit
|
||
`--scope user`, OpenCode in `~/.config/opencode/opencode.json`), passt der Block
|
||
auch in die persönliche Datei. Dann gilt er überall, ohne dass jedes Repository
|
||
ihn braucht.
|
||
|
||
## Der Projektprompt
|
||
|
||
Diesen Block übernehmen:
|
||
|
||
```markdown
|
||
## Munin
|
||
|
||
Für dieses Projekt gibt es einen Munin über MCP (Werkzeuge: recall,
|
||
get, list, related, remember, forget). Er ist das gemeinsame Gedächtnis des Teams.
|
||
|
||
LESEN — vor jeder Antwort zu projektspezifischen Fragen:
|
||
- Zuerst `recall` mit der Frage aufrufen, nicht mit Stichworten. Unter
|
||
`synonyms` weitere Namen für das Thema mitgeben (Synonyme, Übersetzung,
|
||
Abkürzungen) — die Suche vergleicht Wörter, keine Bedeutungen.
|
||
- Findet `recall` nichts, mit anderen Begriffen erneut suchen.
|
||
- Passenden Treffer mit `get` vollständig laden.
|
||
- Für mehr Kontext mit `related` die verknüpften Einträge ansehen.
|
||
- Einträge mit `"stale": true` sind über ein Jahr alt: vor Verwendung prüfen
|
||
und in der Antwort erwähnen, dass der Stand alt ist.
|
||
- Erst wenn nichts Passendes da ist, aus eigenem Wissen antworten — und das
|
||
kenntlich machen.
|
||
- Nie raten, wenn es um Prozesse, Zugänge oder Entscheidungen dieses Teams geht.
|
||
|
||
SCHREIBEN — sobald etwas festgehalten werden sollte:
|
||
- IMMER zuerst `recall`, ob es zum Thema schon einen Eintrag gibt.
|
||
- Gibt es einen: mit DESSEN slug `remember` aufrufen. Das aktualisiert ihn.
|
||
- Nur wenn wirklich nichts passt, einen neuen slug wählen.
|
||
- Meldet `remember` `judgment_required`, die `candidates` prüfen: Passt einer,
|
||
ihn fortschreiben. Nur bei wirklich anderem Thema mit `force: true` anlegen.
|
||
- Einträge mit `"curated": true` hat ein Mensch geprüft: Sie haben Vorrang.
|
||
Nur ändern, wenn sie nachweislich nicht mehr stimmen — dann mit
|
||
`override_curated: true` und einer Begründung unter `reason`.
|
||
- Vor dem Aktualisieren `get` aufrufen und die gelieferte `version` als
|
||
`expected_version` mitgeben.
|
||
|
||
WAS festgehalten wird:
|
||
- Entscheidungen mit Begründung
|
||
- Abläufe, die sich wiederholen
|
||
- Lösungen für Probleme, die länger gedauert haben
|
||
- Nicht: Zwischenstände, Diskussionsverlauf, was im Code steht
|
||
|
||
WIE festgehalten wird:
|
||
- Destilliert, nicht als Protokoll. Ein Eintrag beantwortet eine Frage.
|
||
- Verwandtes mit [[bezeichner]] verknüpfen.
|
||
- Am Ende eine Zeile `Auch gesucht als: …` mit 2–5 Begriffen, die nicht im
|
||
Text stehen, unter denen man den Eintrag aber suchen würde.
|
||
- Schlagworte sparsam: 1–3 aus dem bestehenden Bestand (`list` zeigt sie).
|
||
```
|
||
|
||
## Die Werkzeuge
|
||
|
||
| Werkzeug | Rolle | Wofür |
|
||
|---|---|---|
|
||
| `recall` | read | Suchen. Der wichtigste Einstieg, auch vor dem Schreiben. |
|
||
| `get` | read | Einen Eintrag vollständig laden, mit Verweisen und Fassungsnummer. |
|
||
| `list` | read | Überblick: zuletzt geänderte Einträge und alle Schlagworte. |
|
||
| `related` | read | Verknüpfte Einträge finden, auch solche, die die Suche nicht trifft. |
|
||
| `remember` | write | Einen Eintrag anlegen oder aktualisieren. |
|
||
| `forget` | write | Einen Eintrag in den Papierkorb legen. |
|
||
|
||
## Gute Bezeichner
|
||
|
||
Der Bezeichner entscheidet, ob ein Eintrag aktualisiert oder neu angelegt wird.
|
||
|
||
| Gut | Schlecht | Warum |
|
||
|---|---|---|
|
||
| `deployment-prozess` | `notiz-2026-01-15` | Ein Datum ist kein Thema. |
|
||
| `fehler-zugriff-verweigert` | `problem-3` | Nicht wiederzufinden. |
|
||
| `entscheidung-sqlite` | `sqlite-entscheidung-final-v2` | Fassungen zählt das System selbst. |
|
||
|
||
Kurz, sprechend und dauerhaft. Ohne Angabe wird der Bezeichner aus dem Titel
|
||
abgeleitet.
|
||
|
||
## Muster für den Alltag
|
||
|
||
**Nachschlagen**
|
||
|
||
```
|
||
Wie läuft bei uns das Deployment? Schau zuerst im Munin nach.
|
||
```
|
||
|
||
**Nach getaner Arbeit festhalten**
|
||
|
||
```
|
||
Halte fest, was wir über den abgelaufenen Token herausgefunden haben.
|
||
Prüfe vorher mit recall, ob es dazu schon einen Eintrag gibt — dann
|
||
ergänze diesen, statt einen neuen anzulegen.
|
||
```
|
||
|
||
**Vorhandenes fortschreiben**
|
||
|
||
```
|
||
Lies deployment-prozess mit get, ergänze den Schritt mit dem Rollback und
|
||
schreibe zurück — mit expected_version aus dem get.
|
||
```
|
||
|
||
**Aufräumen**
|
||
|
||
```
|
||
Rufe list auf und nenne mir Einträge, die dasselbe Thema doppelt behandeln.
|
||
Nichts ändern, nur auflisten.
|
||
```
|
||
|
||
**Einarbeiten**
|
||
|
||
```
|
||
Verschaffe dir mit list und recall einen Überblick über den Munin
|
||
und fasse zusammen, was dieses Team über Betrieb und Deployment festgehalten hat.
|
||
```
|
||
|
||
## Wenn zwei gleichzeitig schreiben
|
||
|
||
`get` liefert eine Fassungsnummer (`version`). Gibt ein Agent sie beim
|
||
Schreiben als `expected_version` mit, lehnt Munin die Änderung ab, falls
|
||
inzwischen jemand anderes den Eintrag geändert hat. Der Agent lädt dann neu und
|
||
führt beides zusammen. Ohne diese Angabe würde die fremde Änderung einfach
|
||
überschrieben. Sie wäre zwar im Verlauf noch zu finden, aber niemand würde es
|
||
merken.
|
||
|
||
## Wenn Munin nachfragt, statt zu schreiben
|
||
|
||
In zwei Fällen schreibt `remember` nicht sofort, sondern antwortet mit
|
||
`judgment_required`. Das ist kein Fehler, sondern eine Rückfrage an den Agenten:
|
||
|
||
- **Ähnlicher Eintrag vorhanden:** Ein neuer Eintrag ähnelt einem vorhandenen
|
||
(gleiche Wörter im Titel, oder ein Wort steht wörtlich in „Auch gesucht
|
||
als“). Die Antwort nennt die Kandidaten samt der gemeinsamen Wörter
|
||
(`matched_words`). Passt einer, schreibt der Agent diesen fort; ist es
|
||
wirklich ein anderes Thema, legt er mit `force: true` doch an. `force`
|
||
übergeht nur diese eine Rückfrage, nichts sonst. Ein gemeinsamer Titelanfang
|
||
wie „Munin – “ zählt nicht.
|
||
- **Kuratierter Eintrag:** Ein Mensch hat den Eintrag geprüft. Der Agent ändert
|
||
ihn nur mit `override_curated: true` und einer Begründung unter `reason`.
|
||
Dabei fällt der Haken „Kuratiert“ weg, und der Eintrag erscheint auf der
|
||
Nutzungsseite unter *Zur Prüfung*.
|
||
|
||
## Grenzen, die man kennen sollte
|
||
|
||
- **Die Suche ist wortbasiert.** Sie gleicht Wortanfänge, Endungen und
|
||
zusammengesetzte Wörter aus („deployen“ findet „Deployment“, „prozess“ findet
|
||
„Releaseprozess“), aber keine Bedeutungen: „Wie deployen wir“ findet
|
||
„Release-Prozess“ nur, wenn der Agent `release` unter `synonyms` mitgibt oder
|
||
der Eintrag es unter „Auch gesucht als“ nennt. Im Zweifel hilft `list` für den
|
||
Überblick.
|
||
- **`forget` legt in den Papierkorb.** Der Eintrag ist für alle Agenten sofort
|
||
weg, lässt sich aber 30 Tage lang von einem Menschen zurückholen. Agenten
|
||
selbst können nichts wiederherstellen und den Papierkorb nicht leeren.
|
||
Veraltetes trotzdem besser mit `remember` richtigstellen: Dann bleibt der
|
||
Eintrag auffindbar, und der Verlauf zeigt, was sich geändert hat.
|
||
- **Schreibt ein Agent unter einem Bezeichner, der im Papierkorb liegt**, holt
|
||
er den Eintrag zurück und überschreibt ihn. Der gelöschte Stand steht danach
|
||
im Verlauf, und die Antwort an den Agenten sagt, was passiert ist.
|
||
- **Was drinsteht, landet im Kontext aller Agenten des Projekts.** Wer schreiben
|
||
darf, schreibt damit indirekt in deren Prompts. Deshalb stehen Herkunft und
|
||
Autor an jedem Eintrag.
|
||
|
||
## Prüfen, ob es wirkt
|
||
|
||
Die Seite **Nutzung** in der Seitenleiste zählt die Schreibvorgänge der letzten
|
||
30 Tage, getrennt nach Agenten und Menschen und nach „neu angelegt“ und
|
||
„aktualisiert“. Der wichtigste Wert steht darunter: welcher Anteil der
|
||
Schreibvorgänge einen vorhandenen Eintrag fortgeschrieben hat.
|
||
|
||
Am Anfang legen Teams naturgemäß vor allem an. Nach ein paar Wochen sollte der
|
||
Anteil der Aktualisierungen steigen. Viele Neuanlagen zu ähnlichen Themen
|
||
bedeuten: Der Projektprompt greift nicht.
|
||
|
||
Außerdem zeigt die Seite:
|
||
|
||
- **Zur Prüfung:** kuratierte Einträge, die ein Agent seitdem geändert hat, mit
|
||
seiner Begründung. Der Link führt zum Verlauf, dort lässt sich die Änderung mit
|
||
dem geprüften Stand vergleichen. Stimmt sie, den Haken „Kuratiert“ wieder
|
||
setzen; sonst die alte Fassung wiederherstellen. Danach verschwindet der
|
||
Eintrag aus der Liste.
|
||
- **Suchen der Agenten:** wie oft Agenten gesucht haben, wie oft ohne Treffer
|
||
und wie oft mit Synonymen. Darunter die häufigsten Anfragen ohne Treffer.
|
||
Steht das Gesuchte unter anderen Wörtern da, hilft eine Zeile
|
||
„Auch gesucht als: …“ im Eintrag. Fehlt es, ist das ein Kandidat für einen
|
||
neuen Eintrag.
|
||
- **Verweise ins Leere:** Bezeichner, auf die mit `[[…]]` verwiesen wird, ohne
|
||
dass es den Eintrag gibt. Die meistgenannten sind gute Kandidaten für den
|
||
nächsten Eintrag; mit Schreibrecht führt *anlegen* direkt dorthin.
|
||
- **Einträge ohne Schlagwort**, zum Nachtragen mit der Sammelbearbeitung.
|
||
- **Zuletzt aktive Zugänge**, um zu sehen, welche Agenten wirklich arbeiten.
|
||
|
||
Einzelne Vorgänge mit Zugang und Zeit stehen unter *Protokoll*.
|