Zwanzig Jahre Daten, vier Silos, null Antworten
Ich handle mit antiken Uhren und scanne jedes Blatt Papier, das bei mir ankommt. Über die Jahre sind so 9.351 Dokumente in Paperless zusammengekommen. Dazu kommen 484 Notizen in meinem Obsidian-Vault, eine Warenwirtschaft mit 7.147 Uhren und Schmuckstücken und 1.056 YouTube-Videos aus vier Kanälen, die ich lokal mit Whisper vollständig transkribiert habe. Vier Systeme, alle durchsuchbar.
Dann habe ich eines Abends eine einfache Frage gestellt: „Was habe ich 2024 an die Telekom bezahlt?“ Keines der vier Systeme konnte sie beantworten.
Daraus ist mein Second Brain geworden: alle Quellen in einer Datenbank, zwei lokale Modelle auf meinem Mac, keine Cloud. Am 14. Oktober habe ich es auf der In the Loop 2026 in Berlin vorgestellt, nach der Premiere beim n8n Meetup in Hamburg im August. Dieser Artikel ist die schriftliche Fassung des Berliner Vortrags, mit den vier Workflows, die ich auf der Bühne live geöffnet habe.
Die These steht im Titel: Agenten können denken, aber sie können nicht handeln. Die Hände sind Workflows. Und je länger ich gebaut habe, desto wichtiger wurde n8n dabei, nicht unwichtiger.
Vier Gedächtnisse, eine Datenbank
Das System unterscheidet vier Arten von Gedächtnis, und jede wird anders gefragt:
→ Semantisch, was ich weiß: Notizen, YouTube-Transkripte, Lektionen. Gefunden über die Bedeutung.
→ Episodisch, was passiert ist: Belege und Briefe. Gefunden über die Bedeutung und über exakte Wörter, denn eine Rechnungsnummer hat keine Bedeutung.
→ Geschäftlich, was ein Ding ist: der ganze Lebenslauf einer Uhr, gekauft, repariert, verkauft. Das ist ein exakter SQL-Lookup, kein Raten.
→ Meta, wie geantwortet wird: 72 Beispielfragen, die entscheiden, welches Gedächtnis eine Frage bekommt, und ein Protokoll jeder gestellten Frage.
Alle vier liegen in CrateDB, weil dort Vektorsuche, Volltextsuche und SQL in einer einzigen Abfrage gehen. Die Wahrheit liegt aber woanders: Markdown ist die Wahrheit, die Datenbank nur der kompilierte Index. Ich kann sie wegwerfen und neu bauen. Das ist Andrej Karpathys Idee vom LLM-Wiki: dicht verlinktes Markdown, das jeder fremde Agent lesen kann, und daneben ein Index als zweites Build-Ziel.
Eine Kaskade, in der kein Modell die Route wählt
Vier Gedächtnisse heißt: Jede Frage braucht zuerst eine Entscheidung, wohin sie geht. Die habe ich anfangs vom Sprachmodell treffen lassen, weil das naheliegend ist. Es war langsam, launisch und nicht erklärbar. Heute entscheidet eine langweilige Kaskade:
→ Stufe 0, bekannte Kennung: Steht eine Uhrennummer in der Frage, findet ein Lookup im gespiegelten Warenwirtschafts-Index sie exakt.
→ Stufe 1, Regelmarker: Ein regulärer Ausdruck in einem Code-Node erkennt Summenfragen wie „wieviel habe ich … bezahlt“.
→ Stufe 2, Mehrheit der Nachbarn: Die Frage wird eingebettet und mit 72 gelabelten Beispielfragen verglichen. Zwei von drei Nachbarn entscheiden.
→ Stufe 3, Rückfall: Gibt es keine Mehrheit, wird in beiden Gedächtnissen gesucht. Keine Sackgasse.
Im Leave-one-out-Test landen alle 72 Beispielfragen dort, wo sie hingehören: 72 von 72. Das ist reproduzierbar, das Execution-Log ist die Begründung, und der teure Zweig läuft zuletzt. Wenn der Router im echten Leben danebengreift, ist der Fix schlicht. Als „wo stehen wir beim Kunden X“ an die Belege statt an meine Notizen ging, brauchte es vier gelabelte Beispiele in einer Tabelle. Keine Prompt-Chirurgie, vier Zeilen.
Der Router in n8n: 32 Nodes, zwei Türen, zwei Wächter
Der Workflow frag_second_brain beantwortet selbst nichts. Er leitet. Er hat zwei Eingänge: Meine 3D-Galaxie im Browser schickt Fragen per Webhook, ein Agent kommt über den MCP-Server. Hinter beiden Türen liegt derselbe Weg, der Router weiß nicht, wer fragt.
Ein paar Details aus dem Canvas, die ich auf der Bühne gezeigt habe:
→ Die Sparweiche. Ein IF-Node prüft, ob Stufe 0 oder 1 schon entschieden hat. Nur wenn nicht, läuft die teure Kette darunter. Bei einer Frage nach Uhr 20393 bleibt der untere Ast in der Execution grau. Er ist nie gelaufen. Kein Modell, unter einer Sekunde.
→ Maskieren vor dem Abstimmen. Firmennamen werden durch [Firma] ersetzt, Jahre durch [Jahr]. Für die Route zählt die Art der Frage: „Telekom 2023“ und „Vodafone 2024“ sind dieselbe Frage. Ohne Maskierung zöge „Telekom“ die Suche womöglich zu meinen Notizen über die Telekom-Fritzbox. Gesucht wird danach wieder mit der Originalfrage.
→ Abstimmen ohne Modell. Das Embedding kommt von bge-m3, 1.024 Zahlen, gleiche Frage, gleicher Vektor. Eine Datenbankabfrage holt die 15 nächsten der 72 Beispielfragen, die besten drei stimmen ab.
→ Ein Switch statt einer IF-Kette. Fünf Ausgänge: Uhr, Summe, Wissen, Beleg und als Rückfall hybrid.
Dazu kommen zwei Wächter. Der erste verhindert blinde Summen. Das einzige Sprachmodell im ganzen Router liest bei einer schon erkannten Summenfrage Firma, Jahr und Thema heraus. Es entscheidet nicht die Route. Ein IF-Node prüft danach, ob überhaupt eine Firma oder ein Thema da ist. Ohne diesen Wächter kam einmal 127.551 € heraus, die Summe aller Belege eines Jahres. Gerechnet wird die Summe von SQL, nie vom Modell.
Der zweite Wächter gibt eine zweite Chance. Liegt der beste Treffer im gewählten Gedächtnis unter der Untergrenze 0,5, meldet das Werkzeug „dünn“. Dann sucht der Router einmal in den anderen Schubladen. Ein dünnes Ergebnis heißt nicht „gibt es nicht“, sondern „nicht in der Schublade, die der Router gewählt hat“. Findet auch der zweite Lauf nichts, sagt das System ehrlich: Ich weiß es nicht.
Am Ende schreibt der Router jede Frage samt Route ins Fragen-Log, mit Parametern statt zusammengesetztem SQL. Scheitert das Protokollieren, kommt die Antwort trotzdem.
Jeder Workflow ist jetzt ein Werkzeug
Ein einziger Node hat für mich alles verändert: der MCP Server Trigger. Er macht aus meiner n8n-Instanz einen Werkzeugkasten, den jedes Modell benutzen kann. Hermes auf einem Raspberry Pi nutzt ihn heute, Claude könnte es morgen: gleicher Endpunkt, Bearer-Auth, fertig.
Insgesamt sind es neun Werkzeuge. frag_second_brain ist der Router, die anderen acht sind seine Hände: Wissen suchen und lesen, Belege suchen und lesen, semantische Suche, offene Posten, Uhren-Suche und der Prüfer. Jedes davon ist einfach ein Workflow und auch einzeln aufrufbar. Deshalb habe ich nie einen eigenen API-Server gebaut:
→ Die Zugangsdaten leben in n8n. Der Agent sieht nie ein Datenbank-Passwort.
→ Ich ändere ein Werkzeug im Browser, während Telegram weiter antwortet.
→ Jeder Aufruf ist eine Execution, die ich ansehen und erneut abspielen kann.
Sechs Nodes: die Bauform jedes Werkzeugs
uhr_suchen ist eine gerade Kette ohne Verzweigung: Trigger, Prep, Embed, SQL bauen, ein Datenbankaufruf, Format. Jedes meiner Werkzeuge hat diese Form, nur die Abfrage ändert sich.
Mit Uhrennummer baut der Code-Node eine exakte Abfrage. Ohne Nummer, etwa bei „Welche Uhren haben ein schwarzes Zifferblatt?“, wird es eine Bedeutungssuche plus Volltextsuche in einem einzigen SQL. Vorher fliegen Allerweltswörter wie „Uhr“, „welche“, „haben“ raus, denn „Uhren“ passt auf jeden Datensatz und spülte sonst die dünnsten Einträge nach oben.
Genau diese Zifferblatt-Frage hat mir eine meiner liebsten Lektionen beschert. Die Suche lieferte dünne Datensätze, Titel wie „russische Uhr“, ohne jede Angabe zum Zifferblatt. Der Agent folgerte: Das Werkzeug hat sie auf meine Schwarz-Anfrage zurückgegeben, also müssen sie schwarz sein. Vollkommen logisch, komplett falsch. Der Fix war kein Prompt, sondern ein Hinweis-Feld im Output des Werkzeugs: Eine Eigenschaft gilt nur als belegt, wenn sie wörtlich in den Details steht. Ein Werkzeug-Output erzieht Agenten besser zur Ehrlichkeit als jeder System-Prompt, weil er bei jedem einzelnen Aufruf direkt neben den Daten steht.
Drei Nodes kamen später dazu, damit eine Uhr auch ihre Belege zeigt. Ein Code-Node ordnet jeden Paperless-Beleg ein: Die Nummer muss als eigene Zahl dastehen (eine Rechnungsnummer 12201711 enthält 20171, zählt aber nicht), Uhrmacher-Vokabular wie „Uhrwerk“ oder „Stellwelle“ macht eine Reparatur daraus, und ein Beleg von vor dem Einkauf kann keine Reparatur sein. Deshalb steht bei Uhr 20393 die Reparaturrechnung des Uhrmachers über 90 € in der Antwort. Eingebaut habe ich das im Browser. Der Agent war nie offline.
Das Modell arbeitet nur dort, wo Sprache ist
Das sieht man am besten an semantisch_suchen, dem Werkzeug hinter der Wohnzimmer-Frage aus der Demo. 16 Nodes, drei Schritte:
→ Erweitern. Das lokale Qwen schreibt zwei Umformulierungen im Dokumentendeutsch. Das überbrückt Wortlücken: Die Frage sagt „PV produziert“, der Beleg sagt „Einspeisung“.
→ Finden, in einer Abfrage. Drei Vektoren (Originalfrage und zwei Varianten) plus Volltextsuche. Wie selten ein Wort ist, wird gemessen, nicht geraten: Ein Code-Node zählt, in wie vielen Dokumenten es vorkommt. Die zwei seltensten Wörter bekommen eine eigene Suche. Ein Datenbankaufruf, bis zu rund 250 Kandidaten.
→ Ordnen, nie verwerfen. Eine deterministische Bewertung nominiert das beste Stück je Dokument. Dann sortiert das Modell die Kandidaten nach Relevanz, und es darf nichts streichen.
Diese letzte Regel hat mich einen Tag gekostet. Früher ließ ich das Modell die Liste kürzen, und es urteilte nach kurzen Vorschauen. Es warf den einen Beleg weg, der die Antwort enthielt, zweimal am selben Tag. Seitdem hängt der Format-Node alle Treffer, die das Modell vergessen hat, hinten an, und der Bedeutungssieger bleibt garantiert im Fenster, auch wenn das Modell ihn nach hinten sortiert. Einmal wäre sonst ausgerechnet die Raumtabelle mit den 30,47 m² Wohnzimmer rausgeflogen.
Bei Summenfragen gilt dasselbe Muster: Das Modell liest Firma und Jahr aus der Frage, SQL rechnet. Sprachmodelle sind miserable Buchhalter.
Ein Ausfall ist nicht „nicht gefunden“
Ein Betriebssystem, das Gerätefehler verschweigt, ist kein Betriebssystem. Der erste Lauf meines neuen Status-Panels meldete: SSH-Tunnel war weg, neu aufgebaut. Er war seit Tagen tot. Und Fragen zu Uhren hatten die ganze Zeit selbstbewusst falsche Antworten bekommen, denn die tote Datenbank hatte geantwortet: diese Uhr gibt es nicht.
Daraus sind drei Regeln geworden:
→ Fünf Dienste, fünf Gesundheitschecks. Ein try/except um alles verdeckt, was kaputt ist.
→ Ausfall ist nicht „nicht gefunden“. Eine tote Datenbank wirft jetzt einen Fehler, und die Oberfläche sagt: Dieses Gedächtnis ist offline.
→ Eine kalibrierte Untergrenze. Liegt der beste inhaltliche Treffer unter 0,5 und gibt es keine exakte Kennung, lautet die Antwort „Ich weiß es nicht“, und das wird protokolliert. Den Wert habe ich an echten Fragen und an Unsinnsfragen gemessen.
Verschluckte Fehler waren die Ursache jeder falschen Antwort, die mir dieses System je gegeben hat.
Ein zweites Modell, angestellt zum Widersprechen
Ehrliche Fehler sind die eine Hälfte. Die andere sind Antworten, die richtig aussehen und es nicht sind. Deshalb prüft der Workflow antwort_pruefen jede Antwort, nachdem sie gesendet wurde. Niemand wartet darauf, und die Antwort bleibt unverändert.
→ Andere Familie. Ein Gemma prüft ein Qwen, weil verschiedene Modellfamilien verschiedene blinde Flecken haben.
→ Exakt derselbe Kontext. Die Galaxie liefert die Auszüge mit, die das Antwortmodell gesehen hat, samt Nummern [1], [2]. So lässt sich prüfen, ob „laut [2]“ wirklich in [2] steht. Eine zweite Suche würde anders nummerieren, und der Prüfer meldete Fehlzitate, die keine sind. Nur wenn ein Agent fragt, holt der Prüfer die Auszüge selbst über den Router.
→ Erst Code, dann Modell. Jede Zahl der Antwort wird per Code mit den Auszügen abgeglichen, exakt oder als Anfang mit mindestens drei Ziffern (177 passt zu 177,44). Ob eine Zahl in einem Text steht, ist keine Meinungsfrage.
→ Beweispflicht. Das Modell muss erst jeden Namen, jedes Datum, jeden Betrag als belegt oder fehlend aufzählen und dann urteilen. Jeder Einwand muss die Auszüge zitieren. Sagt es im Pflichtdurchgang „fehlt“ und am Ende trotzdem „ok“, gilt das nicht als ok.
Die Beweispflicht ist der Kern. Naiver Zweifel ist Sycophancy rückwärts: Er kippt auch richtige Antworten. Gemessen habe ich null Fehlalarme bei zehn korrekten Antworten und eine Fangquote von 80 Prozent. Das Urteil landet im Fragen-Log, und ich sehe es erst, nachdem ich die Antwort selbst bewertet habe. Sonst würde der Prüfer genau die Bewertungen prägen, an denen er gemessen wird. Gestartet habe ich ihn als zweiwöchiges Schattenexperiment mit einer klaren Regel: kein messbarer Effekt, dann wird er gelöscht.
Am ersten Tag hat er eine falsche Antwort widerlegt. Der zitierte Beleg gehörte zu einer anderen Adresse. Das Antwortmodell konnte das nicht sehen, der Prüfer schon.
Eine bekannte Schwäche gehört dazu: Zahlen, die schon in der Frage stehen, etwa eine Hausnummer oder ein Jahr, kennt der Zahlen-Check noch nicht als erlaubt. Das kann einen Fehlalarm auslösen.
Was ich ausprobiert und verworfen habe
→ Das Modell routen lassen? Zuerst gemacht, siehe oben. Langsam, launisch, nicht erklärbar.
→ Eine Graphdatenbank? Die Links leben im Markdown selbst. Der Kampf hieß Retrieval-Qualität, nie Graph-Traversierung.
→ Eine eigene Vektor-Datenbank? Der Join mit meinen Geschäftsdaten ist der ganze Sinn einer einzigen Datenbank.
→ Automatisch speichern, was der Agent lernt? Das verseucht das Gedächtnis mit Halbwissen. Geschrieben wird nur auf ausdrücklichen Befehl.
Warum n8n im Agenten-Zeitalter wichtiger wird
→ MCP hat n8n zum Werkzeugkasten gemacht. Jeder Workflow, den du je gebaut hast, kann jetzt von einem Modell aufgerufen werden.
→ Determinismus, wo er zählt. Die zuverlässige Hälfte eines KI-Systems ist ein Graph, kein Prompt.
→ Beobachtbarkeit. Über das Execution-Log habe ich meinen Agenten dabei erwischt, wie er den Router umging. Versuch das mal mit einer Blackbox.
→ Live ändern, Zugangsdaten isolieren. Ich repariere ein Werkzeug, während Telegram weiter antwortet.
Dazu passt eine Nachricht vom Sommer: Flowise wurde im August eingestellt. Die eigene Begründung der Macher: Die Modelle sind beim Schlussfolgern über visuelles Low-Code hinausgewachsen. Das ist kein Argument gegen Workflow-Werkzeuge. Es ist ein Argument dafür, auf welcher Schicht man baut. Flowise hat das Denken verpackt. n8n bewegt die Hände. Genau deshalb entscheidet bei mir nie ein Sprachmodell die Route.
Agenten sind probabilistisch. Produkte brauchen deterministische Kanten. n8n ist der Ort, an dem ich die deterministische Hälfte kodiere.
Das gilt nicht für jeden Fall. Wenn ein Agent bei dir für eine einzelne Aufgabe zuverlässig läuft, brauchst du n8n dafür nicht. Bei Abläufen, die jedes Mal gleich ablaufen müssen, mit Trigger, Zugangsdaten, Wiederholungen und einem Protokoll, würde ich es davorhängen.
Was ich mitnehme
Drei Sätze, mit denen ich in Berlin geschlossen habe:
→ Agenten brauchen Hände. n8n ist die Hand.
→ Behalte den Determinismus, wo er zählt, und gib das Sprachmodell nur für Sprache aus.
→ Mach Scheitern sichtbar. Ein ehrliches „Ich weiß es nicht“ schlägt plausible Fiktion.
Die Folien gibt es unter michaelgross.net/talk.