Agent-Memory jenseits von Markdown: Wo Markdown aufhört und ein RDF-Graph anfängt
Wo Markdown-Memory für KI-Agenten kippt, und wie ein RDF-Graph an dieser Stelle weitermacht.
Ein KI-Agent löst eine Aufgabe, schließt die Session, und beim nächsten Mal kennt er weder das Projekt noch die Korrektur, die ich gestern angebracht habe. Das ist das Standardverhalten heute. Wer das ändern will, baut ein Gedächtnis. Die naheliegende erste Form sind Markdown-Dateien neben dem Projekt, organisiert nach Themen, gepflegt vom Agenten selbst. Das funktioniert besser, als es klingt. Und es hört an einem Punkt auf zu funktionieren, der sich klar benennen lässt.
Dieser Artikel beschreibt drei Sachen. Was Markdown-Memory in der Praxis heute leistet. An welcher Stelle es kippt. Welchen Weg ich seit einigen Wochen ausprobiere, um über diese Stelle hinwegzukommen. Der Weg ist nicht abgeschlossen. Ich zeige, was läuft, und ich zeige, was nicht.
1. Was Markdown-Memory heute schon leistet
Mein primärer Coding-Agent hat seit einigen Monaten ein typisiertes Auto-Memory. Pro Projekt liegt ein Verzeichnis mit einer Index-Datei und kleinen Markdown-Dateien daneben. Jede Datei trägt einen Typ im Frontmatter: ein Profil des Nutzers, eine Feedback-Regel, eine Projekt-Notiz, ein Verweis auf eine externe Quelle. Der Index nennt alle Einträge mit einer einzeiligen Beschreibung. Beim Session-Start liest der Agent den Index. Wenn etwas relevant aussieht, holt er die einzelne Datei nach.
Mein eigenes Verzeichnis hat rund 40 Einträge. Es ist organisch gewachsen, nicht geplant. Ich nutze es täglich, ohne darüber nachzudenken. Ein typischer Feedback-Eintrag sieht so aus:
---
name: feedback-db-mocks
type: feedback
---
Integrationstests müssen gegen eine echte Datenbank laufen, nicht gegen Mocks.
**Warum:** Im letzten Quartal hat ein mock-basierter Test grün gemeldet,
während die Produktions-Migration auf einer realen Spalte gescheitert ist.
Der Mock kannte das Schema nicht.
**Anwenden:** Wenn ein neuer Test eine Repository-Klasse berührt, immer
gegen Testcontainers laufen, nie gegen einen In-Memory-Stub.
Drei Sätze, ein Grund, eine Anwendungsregel. Der Agent zieht das beim nächsten Mal, wenn er einen Test schreibt, der eine Datenbank anspricht. Ich muss die Regel nicht wiederholen. Diese Form von Gedächtnis ist erstaunlich stabil. Sie überlebt einen Wechsel des Modells, einen Wechsel des Editors und Wochen ohne Berührung. Sie ist außerdem für mich als Mensch jederzeit lesbar, mit jedem Texteditor, ohne Tool.
Markdown hat dafür konkrete Stärken. Es braucht keinen Server. Jeder Editor öffnet es. grep findet jeden String. git diff zeigt jede Änderung, git blame jeden Urheber. Es gibt keine Schema-Migration. Es gibt nicht einmal ein verbindliches Schema, nur eine Konvention. Die Anlauf-Hürde liegt bei null.
Für ein Setup mit einem Agent, einem Nutzer und überschaubarer Tiefe ist das eine produktive Architektur. Die Frage ist nicht, ob Markdown schlecht ist. Die Frage ist, an welcher Stelle die Tragfähigkeit aufhört.
2. Wo Markdown aufhört
Vier konkrete Bruchstellen, jeweils mit einer Aussage, die Markdown nicht beantwortet.
Erstens: Beziehungen sind Konvention, kein Constraint. Wenn ich in einer Datei [[memory-hygiene]] schreibe, ist das ein Querverweis. Wenn ich [[memory-hygine]] schreibe, ist das ein Tippfehler, den niemand bemerkt. Es gibt kein System, das Referenzen prüft. Ich entdecke das frühestens beim nächsten Suchen, wenn ein Treffer fehlt, den ich erwartet habe. Bei vierzig Einträgen ist das ärgerlich. Bei vierhundert ist es ein Datenqualitäts-Problem.
Zweitens: Mehrfach-Bedingungen sind nicht abfragbar. “Welche Einträge betreffen Projekt X und Technologie Y, sind nach Datum Z geschrieben und haben eine hohe Konfidenz?” In Markdown ist das eine grep-Pipeline mit drei Stufen, gefolgt von Augenarbeit. Es ist keine Abfrage, sondern eine Suche, die ich jedes Mal neu zusammenbaue. Das hält, solange die Fragen einfach bleiben. Sobald ich Memory wirklich als Wissensbasis nutzen will, fängt das Modell an, mich zu bremsen.
Drittens: Provenienz und Konfidenz sind Freitext. Ich schreibe “Quelle: Audit vom April 2026” in den Fließtext. Das kann ich durchsuchen, aber ich kann es nicht zählen. Ich kann nicht filtern. Ich kann die Antwortqualität nicht gewichten. Wenn ich später wissen will, wie viele meiner Aussagen auf diesem Audit beruhen, muss ich grep nehmen und hoffen, dass ich überall dieselbe Formulierung benutzt habe. Habe ich nicht. Auch das ist Konvention statt Schema.
Viertens: Vektor-RAG löst manches, scheitert an deterministischen Beziehungen. Embedding-Suche findet semantisch ähnliche Texte. Das ist nützlich, wenn ich nicht weiß, wonach ich genau suche. Es beantwortet aber nicht “alle Konzepte, die unter dem Oberbegriff X stehen” und es beantwortet nicht “welche Konzepte sind über Domain-Grenzen hinweg explizit als verwandt markiert”. Das sind Graph-Fragen, nicht Ähnlichkeits-Fragen. Ein Vektor-Index weiß nicht, dass A das Oberkonzept von B ist. Er weiß, dass A und B oft gemeinsam im Text vorkommen. Das ist nicht dasselbe.
Ein konkretes Beispiel aus meiner eigenen Praxis, anonymisiert. Der interne Codename phase-2-migration taucht in vier Memory-Dateien auf, mal als Implementierungs-Notiz, mal als Bug-Folge, mal als Fahrplan-Eintrag, mal als Querverweis. Markdown weiß nicht, dass diese vier Einträge zum selben Codenamen gehören. Ich weiß es, solange ich aktiv bin. Ein neuer Agent, ein neues Repository, ein halbes Jahr später: weg.
Es gibt eine zweite Klasse von Problemen, die ich live erlebt habe, als ich kürzlich mein Memory-Verzeichnis bereinigt habe. Das sind keine Modell-Mängel im engeren Sinn, sondern Verhaltensmuster, die das Modell begünstigt.
Schreiben ist in Markdown billig. Eine neue Datei kostet zwei Sekunden. Ich habe gesehen, wie mein Agent eine starke Aussage in einer Feedback-Datei festgehalten hat, ohne mit mir Rücksprache zu halten, weil das Festhalten so einfach war. Das war keine Lüge, sondern eine Festlegung auf eine bestimmte Strategie-Interpretation, die ich so nicht abgesegnet hatte. In einem Speicher mit Konfidenz-Bewertung und Provenance-Forderung wäre das langsamer gewesen, und genau dieses Bisschen Friktion hätte ausgereicht, um zu fragen.
Der Index ist mächtig, weil er zuerst gelesen wird, und er ist gefährlich, weil er die Aufmerksamkeit dominiert. Wenn vierzig Einträge im Index stehen, gehen Hinweise im weiterführenden Repository-CLAUDE.md unter. Der Agent macht Pattern-Match auf Index-Einträge statt zu denken. Im Graph würde eine SKOS-Hierarchie zusammen mit einer Volltext-Suche das richtige Wissen kontextabhängig hochholen. In einem flachen Index gewinnt, was zuerst geschrieben wurde.
Markdown belohnt Sammeln, weil es keine Struktur erzwingt. Bei meiner Bereinigung waren zwölf von sechsundfünfzig Einträgen reine Status-Updates, die git log ohnehin liefert. “PR #X gemerged” hat in einem Memory nichts verloren, das Wissen festhalten soll. Aber wenn der Agent darf, schreibt er, weil es ihm wie Fortschritt vorkommt.
Das ist die ehrliche Diagnose, die mich Richtung Graph schiebt. Nicht weil Markdown grundsätzlich falsch ist. Sondern weil ein Speicher ohne Constraints den Agenten zu Verhalten verleitet, das in einem Speicher mit Constraints schwerer wäre.
3. Forschungsweg: RDF-Knowledge-Graph als Agent-Memory
Was ich seit einigen Wochen baue, ist ein RDF-basiertes Memory-System. RDF ist der Standard des W3C für Aussagen in der Form Subjekt-Prädikat-Objekt. Ein Triple. Statt eine Datei “feedback-db-mocks.md” mit Fließtext zu haben, habe ich Aussagen wie “Konzept Database-Mock-Avoidance hat Typ Test-Regel”, “Konzept Database-Mock-Avoidance gehört zu Schema Testing”, “Konzept Database-Mock-Avoidance wurde generiert von Aktor fred, Quelle Incident-2026-Q1”. Jede Aussage ist abfragbar. Jede Aussage ist mit Provenance versehen, wenn ich es will. Jede Aussage gehorcht einem Vokabular.
Das System ist in drei Schichten gegliedert. Schema, Seeds, Dynamic. Im selben Graph.
┌──────────────────────────────────────┐
│ Schema ontology/ │
│ SKOS + PROV-Vokabular │
└────────────────┬─────────────────────┘
│ gilt für
┌──────────┴──────────┐
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ Seeds │◄─────│ Dynamic │
│ domain/ │ ref. │ domain/ │
│ │ │ │
│ SOLID, │ │ vom Agenten │
│ Hexagonal, │ │ gelernte │
│ ... │ │ Konzepte │
└──────────────┘ └──────────────────┘
Schema definiert die Klassen und Prädikate. Hier kommt nichts Eigenes hin, sondern standardisiertes Vokabular: SKOS für Wissensorganisation, PROV-O für Provenienz, DCTerms für Metadaten. Seeds enthält vorinstalliertes Domänenwissen. Bei meinem System sind das beim Start die Konzepte SOLID, Clean Code und Hexagonale Architektur, jeweils mit ihren Unterkonzepten. Dynamic wächst durch den Agenten. Beide, Seeds und Dynamic, leben im selben Graph mit demselben Vokabular. Es gibt keinen Bruch zwischen “vom System mitgeliefert” und “selbst gelernt”. Eine Abfrage sieht beides.
Was ein Graph anders macht, lässt sich an zwei Abfragen zeigen, die in Markdown nicht ohne menschlichen Vor-Sort-Schritt funktionieren.
Erste Abfrage: transitive Hierarchie. Welche Konzepte stehen unter dem Oberbegriff SOLID, egal wie tief die Verschachtelung ist?
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX kb: <https://kogn.io/kb/>
SELECT ?konzept ?label WHERE {
?konzept skos:broader+ kb:solid .
?konzept skos:prefLabel ?label .
FILTER (lang(?label) = "de")
}
ORDER BY ?label
Antwort gegen die laufende Instanz, fünf Zeilen:
| konzept | label |
|------------------|------------------------------------|
| kb:dip | Abhängigkeitsumkehrprinzip |
| kb:lsp | Liskovsches Substitutionsprinzip |
| kb:ocp | Offen/Geschlossen-Prinzip |
| kb:srp | Prinzip der einzigen Verantwortung |
| kb:isp | Schnittstellentrennungsprinzip |
Der entscheidende Operator ist das + hinter skos:broader. Das ist die transitive Hülle: nicht nur direkte Unterkonzepte, sondern alle Unterkonzepte, beliebig tief verschachtelt. Eine Markdown-Suche nach “SOLID” findet Dateien, in denen das Wort vorkommt. Sie findet nicht die fünf Unterprinzipien, sortiert nach Label, im richtigen Sprach-Filter. Sie findet auch nicht den Fall, dass ich später ein Unter-Unter-Konzept hinzufüge und es automatisch in dieser Liste erscheint.
Zweite Abfrage: Verbindungen über Bereichsgrenzen hinweg. Welche Konzepte aus unterschiedlichen Themen-Schemata sind ausdrücklich als verwandt markiert?
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT DISTINCT ?a ?aLabel ?b ?bLabel ?aScheme ?bScheme WHERE {
?a skos:related ?b .
?a skos:prefLabel ?aLabel .
?b skos:prefLabel ?bLabel .
?a skos:inScheme ?aScheme .
?b skos:inScheme ?bScheme .
FILTER (?aScheme != ?bScheme)
}
Antwort, eine symmetrische Kante zwischen zwei Themen-Schemata:
| a | aLabel | b | bLabel |
|----------------|----------------------------|----------------------------|-------------------------|
| kb:dip | Abhängigkeitsumkehrprinzip | kb:hexagonal_architecture | Hexagonale Architektur |
skos:related ist symmetrisch nach SKOS-Definition. Das Triple wird einmal gespeichert, die Query liefert deshalb eine Zeile pro Verbindung, nicht zwei.
kb:dip lebt im Schema clean-code. kb:hexagonal_architecture lebt im Schema hexagonal-architecture. Beide Themen sind getrennt modelliert, weil sie inhaltlich getrennt gelernt wurden, aber ihre Verbindung ist explizit. Ein Agent, der bei einer Design-Frage zu Dependency Inversion landet, bekommt die Hexagonale Architektur als verwandtes Konzept mitgeliefert, ohne dass jemand eine “siehe auch”-Notiz pflegen muss. Diese Aussage beantwortet Markdown nicht, weil ihm der Begriff von Schemata fehlt. In Markdown ist alles in einem flachen Verzeichnis und die Cross-Reference ist Text, kein Constraint.
Diese zweite Query ist für mich der härteste Beleg gegen reine Markdown-Lösungen. Sie zeigt, dass ein Memory mehr als Dokumenten-Sammlung sein kann, sobald die Beziehungen erstklassig modelliert sind.
Provenienz funktioniert über denselben Mechanismus. Jedes Konzept hat ein prov:wasGeneratedBy auf einen Aktor und optional einen prov:wasDerivedFrom auf eine Quelle. Die Frage “wie viele meiner Aussagen stammen aus diesem Audit” ist eine SPARQL-Zeile statt einer grep-Pipeline. Die Frage “zeig mir alle Aussagen, die der Agent in den letzten zwei Wochen hinzugefügt hat” auch.
4. Was funktioniert, was nicht
Funktioniert heute. Die Drei-Schichten-Trennung ist tragfähig. Seeds und Dynamic teilen denselben Graph mit demselben Vokabular, was bedeutet, dass eine Abfrage nicht zwischen “mitgeliefert” und “selbst gelernt” unterscheiden muss. SKOS als Standard-Vokabular für Taxonomie deckt einen großen Teil der Fälle ab, ohne dass ich eigene Klassen erfinden muss. Hierarchie, verwandte Konzepte, mehrere Labels pro Konzept, Zugehörigkeit zu einem Schema, das alles bringt SKOS mit. PROV-O für Provenance ist nicht hübsch, aber fragbar. Wer welche Aussage wann woraus erzeugt hat, ist eine Standard-Form, nicht ein selbstgebauter Formatvorschlag.
Der Stack ist eine Java-Anwendung mit Spring Boot 4 und Eclipse RDF4J 5.2.2 als Triplestore. Ein Repository pro Project. Die LLM-Schnittstelle ist ein MCP-Server, der dem Agenten Tools zum Lesen und Schreiben des Graphen anbietet. Das System läuft lokal und auf einem Dev-Server. Der Demo-Pfad läuft End-to-End: Konzept anlegen, Hierarchie abfragen, Cross-Scheme-Beziehung lesen, alles aus dem laufenden System gegen den Live-Knoten. Langzeit-Erfahrung im Alltag steht noch aus, die Beobachtung beginnt jetzt.
Intern ist das System nach Hexagonal-Architektur strukturiert, framework-frei im Kern-Modul, mit ArchUnit erzwungen. Domänen-Klassen wie Concept und ConceptScheme, ein KnowledgeApplicationService, der UseCase-Interfaces wie UCFindBroaderConcepts umsetzt, ein Out-Port ConceptRepository mit RDF4J-Adapter Rdf4jSparqlExecutor in einem eigenen Persistenz-Modul, und MCP-Tools (ConceptTools, SparqlTools) als Eingangs-Adapter. Eine Anfrage des Agenten läuft so durch die Schichten:
LLM-Agent
│
│ MCP-Call: findBroaderConcepts('kb:solid')
▼
ConceptTools (Adapter-In)
│
▼
UCFindBroaderConcepts (Port-In)
│
▼
KnowledgeApplicationService (Application)
│
▼
ConceptRepository (Port-Out)
│
▼
Rdf4jSparqlExecutor (Adapter-Out)
│
▼
RDF4J NativeStore
Der Aufwand hat zwei Gründe. Erstens bleibt die Domäne testbar, ohne dass ein Triplestore laufen muss. Zweitens lassen sich Eingangs-Kanäle austauschen, ohne den Kern anzufassen.
Funktioniert noch nicht. Volltextsuche ist als Stub vorhanden, der zugrundeliegende Index wird noch nicht zuverlässig befüllt. Ich behelfe mir derzeit mit SKOS-Label-Suche und SPARQL-CONTAINS. Für die meisten Memory-Fälle reicht das, aber für die freie Suche im Korpus fehlt das Stück noch.
Ein gemessener A/B-Vergleich gegen Vektor-RAG fehlt. Ich kann argumentieren, dass deterministische Beziehungen über transitive Hierarchien und cross-Scheme-Kanten Embedding-Suche strukturell überlegen sind. Ich kann es noch nicht in einer Vergleichsmessung zeigen. Das ist die nächstliegende Lücke, die ich schließen will, weil die Aussage “Graph beantwortet Fragen, die Vektor nicht beantwortet” momentan auf Hypothese steht, nicht auf Zahlen.
Multi-User auf derselben Instanz ist technisch da, aber nicht unter Last getestet. Multi-Agent-Koordination im echten Sinn, mit konkurrierenden Schreibvorgängen und Konflikt-Auflösung, ist nicht implementiert. Heute gilt: ein API-Key pro Project, eine Identität pro Aktor.
Der heutige Zugriff ist ein Einzel-User-Modus. Der Agent ruft die Graph-Tools direkt, weil ich der einzige Nutzer bin und das Vokabular kenne. Für mehrere Agenten oder andere Eingangs-Kanäle, etwa ein Chat-Frontend oder einen anderen Coder, reicht das nicht. Es braucht eine Mittlerschicht, die aus einer Text-Anfrage einen Subgraphen zieht und daraus wieder Text macht. Diese Schicht steht noch nicht.
Die ehrliche Grenze. Schreiben ist im Graph teurer als in Markdown. Ein Eintrag braucht eine URI, eine Schema-Validierung, optional eine Einordnung in ein ConceptScheme, optional eine Provenance-Annotation. Das ist mehr Disziplin als ein # Heading in einer .md-Datei. Wer Wissen sammelt und nichts abfragt, sondern nur scrollt, ist mit Markdown besser bedient. Der Graph zahlt sich aus, wenn Abfragen den Wert tragen. Bei Agent-Memory mit Anspruch auf transitive Hierarchie und Cross-Topic-Verbindungen ist das der Normalfall, nicht die Ausnahme.
Diese Grenze ist nicht gegen den Graph, sie ist gegen die Vorstellung, dass jedes Memory ein Graph sein müsste. Wer für sich allein Notizen führt und alles per grep findet, braucht keinen Triplestore. Wer einen Agenten arbeitsfähig halten will, der über Sessions hinweg lernt, semantisch verknüpft und über Bereichsgrenzen hinweg argumentiert, kommt mit Markdown an einen Punkt, an dem die Konvention nicht mehr reicht.
5. Wofür ich das halte und wofür nicht
Was sich aus diesem Versuch übertragen lässt, ist nicht “benutze RDF”. Übertragbar ist das Muster: typisierter Speicher mit Schema, transitive Hierarchie über SKOS oder ein äquivalentes Vokabular, Cross-Topic-Verbindungen explizit modelliert statt im Fließtext versteckt, Provenance erstklassig statt als Freitext-Fußnote. Diese Eigenschaften lassen sich auch mit anderen Technologien herstellen, eine Property-Graph-Datenbank könnte das genauso. RDF ist nicht die einzige Antwort, aber eine, deren Werkzeugkasten standardisiert ist und seit zwanzig Jahren von der Semantic-Web-Community gepflegt wird.
Wer das nicht braucht: für ein Solo-Setup mit überschaubarer Tiefe und ohne Cross-Topic-Anspruch bleibt Markdown die richtige Wahl. Die Setup-Kosten lohnen sich nicht. Wer im selben Maße scrollt wie schreibt, hat keinen Hebel.
Wer das braucht: für Agent-Memory in mehreren Themenbereichen, mit Anspruch auf abfragbare Querverbindungen und auf reproduzierbare Provenance, ist ein typisierter Speicher die ehrliche Antwort. Das Vokabular ist standardisiert, der Werkzeugkasten ist da, die Lernkurve ist real, aber nicht steil im Vergleich zu dem, was man danach abfragen kann.
Die offene Forschungsfrage, die ich gerne weitergeben würde: Wie misst man die Qualität eines Agent-Memorys jenseits von “der Agent fühlt sich schlauer an”? Für Vektor-RAG existieren Benchmarks, Retrieval-Precision und Recall, Hit-Rate auf Goldstandard-Fragen. Für SKOS-basierte Hierarchie-Abfragen in Agent-Setups habe ich noch keine vergleichbare Benchmark-Sammlung gefunden. Das wäre ein lohnendes Stück Arbeit, weil ohne Messung jede Architektur-Entscheidung in diesem Feld auf Intuition steht.
Wer Ähnliches versucht hat oder versucht, kann sich gerne melden. Der hier beschriebene Weg ist eine laufende Forschung, kein Endprodukt. An den Stellen, an denen er noch nicht trägt, hilft jeder Hinweis von außen.