Skip to main content
Glama

蒸留蔵 — distill-kura

Ein Langzeitgedächtnis für Agenten, das destilliert, nicht akkumuliert. Abruf funktioniert über Bedeutung, Schreiben ist durch Belege abgesichert, und ein Server kann mehrere getrennte Gedächtnisse halten — eines pro Agentenmodus — sodass ein Moduswechsel auch das Gedächtnis wechselt.

Wird als DeepSeek Harness-Plugin, als MCP-Server für jeden anderen Host, als HTTP-Dienst und als Python-Bibliothek ausgeliefert. Nur Standardbibliothek; keine Vektordatenbank, keine Embeddings, kein Framework.

        ┌── recall ──────────────────────────────────────────────┐
        │  question → whole index in one prompt → picked slugs   │
        │           → walk [[links]] → the neighbourhood         │  ~0.4 s
        └────────────────────────────────────────────────────────┘
        ┌── distil ──────────────────────────────────────────────┐
        │  journal → classed evidence → candidates → GATE        │
        │  → new? → composed → draft → judged → poured           │
        └────────────────────────────────────────────────────────┘

Warum es das gibt

Zwei Fehler zerstören das Langzeitgedächtnis eines Agenten, und sie zerstören es von gegenüberliegenden Seiten.

Abruf per Schlüsselwort verfehlt das, was du brauchst. Eine Frage nach "SSD-Inferenz- Chips" teilt kein Wort mit einer Erinnerung mit dem Titel "das 2,6-T-Modell von einer SSD-Stufe ausführen" — und doch sind es dasselbe Thema. Die Wortsuche liefert nichts; der Agent antwortet aus dem Nichts. Die Lösung hier sind nicht Embeddings, sondern Erkennung: Der gesamte Index (eine Zeile pro Erinnerung, geschrieben als Erkennungsauslöser) geht in einen Prompt, und ein kleines Modell benennt, was für die Frage relevant ist. Ein Index von ~500 Erinnerungen sind etwa 6k Tokens — ein paar Prozent eines modernen Kontextfensters, und er sitzt im Präfix-Cache.

Alles aufzuschreiben vergiftet den Speicher. Ein Agent behauptet etwas; ein naiver Destillierer zeichnet die Behauptung als Tatsache auf; der nächste Agent liest sie als Grundwahrheit zurück und wiederholt sie mit mehr Selbstvertrauen. Diese Schleife verstärkt sich selbst, und Prompt-Anweisungen stoppen sie nicht — gemessen, nicht angenommen. Deshalb ist der Schreibpfad durch deterministisches Python abgesichert: Jeder Kandidat für eine Erinnerung muss Zitate enthalten, die zeichengenau im Rohmaterial existieren, gekennzeichnet mit ihrer Herkunft.

Klasse

was es ist

was es erlaubt

[USER]

die eigenen Worte des Menschen

"sie haben entschieden", "sie haben gefragt"

[TOOL]

Maschinenausgabe

Zahlen — die einzige Quelle

[ACT]

ein aufgerufenes Werkzeug

"das wurde getan"

[SELF]

die eigene Prosa des Agenten

ein Urteil, in der ersten Person, niemals eine nackte Tatsache

Ein Zitat, das nicht wörtlich gefunden wird, wird verworfen. Ein Kandidat ohne überlebendes Zitat wird weggeworfen. Eine Zahl ohne [TOOL] dahinter wird entfernt. Text, der dem Menschen eine Entscheidung zuschreibt, wenn kein [USER]-Zitat überlebt hat, wird am letzten Tor abgelehnt. Ideen sind willkommen — sie gehen in eine Seed-Datei, nie in den Speicher, und graduieren erst, wenn spätere Belege sie bestätigen.


Related MCP server: Synapto

Schnellstart

git clone https://github.com/lna-lab/distill-kura && cd distill-kura
pip install -e .                       # or just run: python3 -m distill_kura.cli

cp kura.example.toml kura.toml         # edit: one model endpoint is enough to start
kura init main --path ~/kura/main      # create an empty store
kura serve                             # http://127.0.0.1:8085
curl -s -X POST localhost:8085/recall -H 'content-type: application/json' \
     -d '{"question":"what did we decide about the archive disk?","hops":1}'

Trage den Index, damit der Agent immer weiß, was bekannt ist:

kura weave                             # build the three-layer cloth
kura prefill                           # the block to put in the system prompt

Füttere ihn mit deinen Agenten-Transkripten:

kura distill run      # drink a batch → candidates → gate → drafts
kura distill drafts   # look at what it wants to write
kura distill drain    # the scribe re-reads each draft cold: pour / fix / toss
kura distill night    # stay resident and do it whenever things go quiet

Nichts gelangt in den Speicher, bis drain (oder ein manuell ausgeführtes pour) läuft. Entwürfe tragen ihre Belege in einem HTML-Kommentar, sodass du immer sehen kannst, warum eine Erinnerung existiert.


Die residente Karte

Abruf-per-Werkzeug beantwortet "Was weißt du über X?" — aber nur, wenn der Agent entschieden hat zu fragen. Es beantwortet nie die Frage, die der Agent nicht zu stellen denkt: gibt es hier überhaupt etwas? Ein Agent, der die Karte nicht sehen kann, weiß nicht, was ihm fehlt, also rät er, und eine selbstbewusste Vermutung über deinen Haushalt ist genau das Versagen, das dieses Projekt verhindern soll.

Deshalb wird der Index auch getragen: ein fester Block im System-Prompt, bei jeder Runde.

kura weave      # re-weave the index into the three-layer cloth
kura prefill    # print the block a host should inject

Drei Ebenen, weil Detail nur für Neues etwas bringt

Ein blinder A/B-Test — 20 Fragen, dicker Index gegen schlanken Index, bewertet ohne zu wissen, welcher welcher war — legte die Form fest:

Band

dick

schlank

gesamt

9

11

aktuelle Ereignisse

4

1

Doktrin

1

4

Querschnitts-Sprünge

1

4

Die Doktrin-Zeilen waren in beiden Indizes byte-identisch, und der schlanke Index gewann trotzdem in diesem Band: Eine leichtere Umgebung macht die stehenden Zeilen besser. Detail ist nicht die Quelle der Einsicht. Es verdient seinen Platz nur dort, wo sich noch etwas bewegt.

Ebene

Regel

Zeile

gepinnt

Frontmatter type in pinned_types

vollständig behalten

frisch

geändert innerhalb fresh_days

vollständig behalten

Auslöser

alles andere

komprimiert auf ~trigger_tokens

Auslöser-Zeilen werden vom scribe-Modell geschrieben und in einem Ledger zwischengespeichert, das auf Beschreibung und Budget schlüsselt, sodass ein Neu-Weben im stationären Zustand nichts kostet. Wenn kein Modell erreichbar ist, schneidet der Webstuhl stattdessen mechanisch zu — ein Gedächtnissystem darf nicht leer werden, nur weil eine GPU ausfällt.

Alter ist nicht mtime. cp -r, eine Wiederherstellung oder ein Checkout setzt jeden Zeitstempel zurück, der ganze Index wird "frisch", nichts wird beschnitten, und der Mechanismus hat sich stillschweigend abgeschaltet. Deshalb bevorzugt der Webstuhl ein Datum, das innerhalb der Erinnerung geschrieben ist, und misstraut jeder mtime, die ein Fünftel des Speichers mit einem Kalendertag teilt.

Wo es hingeht, und warum das eine Cache-Entscheidung ist

- id: kura
  name: distill-kura
  config: { store: eq, promptOrder: -50 }   # before the persona

Ein Präfix-Cache geht ab dem ersten geänderten Byte verloren — gemessen auf einem lokalen Server: Ein identischer 4.029-Token-Präambel wird von 0,68 s auf 0,14 s umgerechnet, das Anhängen am Ende bleibt bei 0,14 s, und ein Wort vorne hinzugefügt kostet den gesamten Cache (0,66 s). Die Persona trägt normalerweise eine Uhr, also ändert sie sich jede Minute; die Karte ist der größte Block im Prompt und ändert sich ein paar Mal am Tag. Der große stabile Block kommt vor das, was tickt.

Der Block selbst enthält daher kein Datum, keine Uhr, keinen Zähler — und build() verweigert einen Header, der eines enthält, zur Build-Zeit statt durch mysteriös langsame Runden drei Wochen später.

Es übergibt nie eine halbe Karte

Situation

was der Agent bekommt

alles gut

die Karte, zwischen <<<KURA-MAP>>>-Markierungen

über budget_fraction

die ganze Karte und eine Warnung im JSON (nie im Text — ein Banner ist flüchtiger Inhalt)

über hard_fraction

einen Stub ohne Indexzeilen, der sagt, die Karte fehlt, statt leer zu sein

kura nicht erreichbar

einen expliziten Hinweis, dass die Karte fehlt, niemals einen leeren String

Eine abgeschnittene Karte ist das schlechteste verfügbare Artefakt: Sie sieht vollständig aus, und jede Erinnerung unterhalb des Schnitts scheint nicht zu existieren. weave verkürzt das Frische-Fenster, um zu passen, aber es lässt nie eine Zeile fallen — und wenn keine Einstellung das Budget erreicht, sagt es das, behält die bessere Karte und zeigt dir, wo das Gewicht liegt.

Wie man sie in einen Host bekommt

Host

Mechanismus

DSH

natives Plugin — ein systemPrompt.section, im Hintergrund aktualisiert

Claude Code, VS Code, Goose

MCP instructions trägt einen kurzen Zeiger (2KB-Cap); die Karte selbst kommt vom kura_map-Werkzeug oder einem Session-Hook, der kura prefill ausführt

Claude Desktop, claude.ai

ignoriert instructions vollständig — nutze kura_map

alles andere

GET /prefill?format=text, oder kura prefill in einem Shell-Hook

Das MCP-Feld instructions ist ein MAY in der Spezifikation, und ein 9.000-Token- Index kann ohnehin nicht durch ein 2KB-Cap reisen, also tut dieses Projekt nicht so, als wäre es anders.


Modi: mehr als ein kura

Ein einzelnes Gedächtnis, das sowohl "hilf mir, das zu bauen" als auch "hilf mir, das durchzudenken" bedient, dient keinem gut: Der Abruf, der dir beim Debuggen hilft, ist Rauschen in einem Gespräch darüber, was als Nächstes zu tun ist. Also ist ein Speicher ein Verzeichnis, und ein Modus bildet auf einen Speicher ab.

[stores.maker]
path = "~/kura/maker"
label = "maker mode — building things"

[stores.eq]
path = "~/kura/eq"
label = "EQ mode — talking things through"

[modes]
maker = "maker"
eq    = "eq"

Jede Route nimmt einen Selektor, also bedient ein Prozess alle:

curl -s -X POST localhost:8085/recall -d '{"question":"...","mode":"eq"}'
curl -s localhost:8085/index?store=maker
curl -s localhost:8085/s/eq/doctor          # path form, for clients that only vary a base URL

Die Speicher teilen keine Erinnerungen, keinen Index und kein Destillierer-Wasserzeichen. Der Moduswechsel ändert wirklich, was erinnert wird — nicht dieselbe Erinnerung in einer anderen Stimme.

Unabhängig als Routing, nicht als Vertraulichkeit. Der Server hat keine Authentifizierung, also kann jeder Prozess, der seinen Port erreicht, jeden Speicher benennen, den er hält. Einen Agenten zu binden hält ein Modell in seiner Spur; es hält keinen Prozess fern. Eine Vertrauensstufe pro Prozess — docs/TRUST.md ist kurz und lesenswert, bevor ein privater Speicher eingerichtet wird. Es behandelt auch die zwei Grenzen, die leicht übersehen werden: zwei Speicher, die aus einer Journal-Wurzel trinken, und zwei Speicher hinter einem Modell-Endpunkt.

Mit DeepSeek Harness

DSH wechselt Persona und Werkzeuge über Agent-Presets. distill-kura wechselt Gedächtnis über Speicher. Binde sie, und ein Preset-Wechsel bewegt das ganze Selbst:

# .agent-presets/eq/agent.cordis.yml
- id: kura-eq
  name: distill-kura
  config:
    url: http://127.0.0.1:8085
    store: eq            # this preset's memory
    readonly: true       # the CLIENT's own switch: do not even offer a write tool
    # (the store's own `write_policy` is the authority; this just keeps the tool
    #  out of the model's hands. Naming a store already binds the preset.)

Lass allowSwitch auf seinem Standard, und der Agent bekommt auch kura_use, sodass er sich mitten im Gespräch zwischen kuras bewegen kann, ohne einen Preset-Wechsel. Werkzeuge: kura_recall, kura_read, kura_doctor, kura_list, kura_use und kura_remember (nur wenn der Speicher beschreibbar ist). Vollständige Verdrahtung, einschließlich der MCP-Brücke und der isolate-Realm-Regel für Dienstzeilen, findest du in examples/dsh-presets/.

Persona ist Sache des Hosts, nicht unsere. Dieses Projekt rendert oder injiziert nie eine Persona; es zeichnet nur pro Speicher auf, welche Persona-Datei dazugehört, lesbar unter GET /profile?store=eq, damit die beiden Hälften von dem, der das Preset besitzt, in Schritt gehalten werden können. Agenten-Anweisungen bleiben ebenfalls beim AGENTS.md-Mechanismus des Hosts — siehe AGENTS.md in diesem Repo für die Konventionen, die ein Agent, der an dieser Codebasis arbeitet, befolgen sollte.

Mit jedem MCP-Host

{ "mcpServers": { "kura": {
    "command": "python3", "args": ["-m", "distill_kura.mcp"],
    "env": { "KURA_URL": "http://127.0.0.1:8085", "KURA_STORE": "eq", "KURA_READONLY": "1" }
}}}

Lass KURA_STORE für den freien Modus ungesetzt: Die Werkzeuge nehmen ein optionales store-Argument, und kura_use wechselt für die Sitzung.


Modelle: eins als Standard, Rolle für Rolle aufrüsten

Drei Rollen, nicht drei Maschinen:

Rolle

wann sie läuft

braucht

thinker

bei jedem Abruf

klein und schnell; muss Relevanz nach Bedeutung beurteilen

brain

beim Destillieren: liest ein ganzes Journal-Batch

Kontextlänge und Geduld

scribe

beim Destillieren: schreibt die Erinnerung, beurteilt dann Entwürfe

gute Prosa in deiner Sprache, Urteilsvermögen

Deklariere nur [models.thinker], und ein Modell macht alle drei. Rüste die anderen unabhängig auf — ein größeres lokales Modell oder eine Online-API (jedes OpenAI-kompatible /chat/completions; der Schlüssel wird aus einer Umgebungsvariable gelesen, die du benennst, nie in der Konfiguration gespeichert):

[models.thinker]                       # always-on, local, small
url = "http://127.0.0.1:8000/v1"
model = "local-small"

[models.scribe]                        # upgrade just the writing
url = "https://api.example.com/v1"
model = "big-model"
api_key_env = "EXAMPLE_API_KEY"

Zwei Dinge übernimmt das für dich: Reasoning-Effort-Dialekte unterscheiden sich pro Modellfamilie (reasoning_effort, thinking_effort, enable_thinking), also werden alle gesendet — ein unbekanntes wird von der Vorlage ignoriert, während ein Modell, das standardmäßig auf Tiefen-Denken steht, sein ganzes Budget für Reasoning ausgeben und nichts zurückgeben kann. Und der Charta-Text wird byte-identisch an den Kopf jedes Rollen-Prompts gesetzt, sodass bei einem langsamen lokalen Modell die drei Rollen einen gemeinsamen gecachten Präfix teilen, statt drei Prefills zu zahlen.

Wenn der Denker ausfällt, verstummt die Erinnerung nicht — sie fällt zurück auf Wortüberschneidung und kennzeichnet die Antwort als how=words, was die Werkzeuge als ⚠ degraded anzeigen. Leise Verschlechterung ist schlimmer als lauter Ausfall.


Was eine Erinnerung ist

Eine Datei, eine Tatsache.

---
name: archive-on-slow-disk
description: the archive lives on the slow disk; the fast one stays scratch
metadata:
  type: project          # user | feedback | project | reference
---

The archive goes on the slow disk. The fast disk is scratch space.

**Why:** the other way round burns write endurance for nothing.
**How to apply:** check which disk a target directory is on before writing there.
Related: [[disk-layout]]

Und eine Zeile in MEMORY.md:

- [Archive on the slow disk](archive-on-slow-disk.md) — the archive lives on the slow disk; the fast one stays scratch

Diese Zeile ist das Einzige, was jedes Mal gelesen wird. Sie ist ein Erkennungsauslöser, keine Zusammenfassung: Eigennamen, Zahlen, ⚠️ Stolpersteine, die gezogene Schlussfolgerung. Wenn eine Zeile mit der Zeile einer anderen Erinnerung getauscht werden könnte und immer noch korrekt funktioniert, erfüllt sie ihre Aufgabe nicht — kura distill tidy findet die mechanisch erkennbaren Fälle und korrigiert sie.

kura doctor meldet Zählwerte, tote Verweise, Inseln (Erinnerungen, auf die nichts verweist) und Indexabweichungen. Es ist das Auge, das der Stoffwechsel braucht.


Die HTTP-Oberfläche

Route

Funktion

POST /recall

{question, hops, top, chars, total_chars, store|mode} → ausgewählt, durchlaufen, Kontext. chars gilt pro Erinnerung; total_chars ist eine harte Obergrenze für den gesamten Kontext

POST /remember

{slug, description, body, type, title} — ein direkter Schreibvorgang, verweigert, sofern nicht write_policy = "direct-allowed"

GET /index

der rohe Index

GET /prefill

der residente Block, bereit zum Einfügen (&format=text für einen Hook)

GET /memory/<slug>

eine Erinnerung vollständig

GET /doctor

Zustand eines Speichers (?all=1 für alle)

GET /stores

Speicher, Modi und welches Modell welche Rolle ausfüllt

GET /profile

die Satzung des Speichers und ein Verweis auf seine Persona (wird hier nie gerendert)

GET /health

Betriebsbereitschaft

Jede Route akzeptiert ?store= / ?mode=, ein store/mode-Feld im Body oder das /s/<name>/…-Pfadpräfix. Keine Authentifizierung: Binden Sie an Loopback oder setzen Sie etwas davor.


Entwurfsnotizen, die man lesen sollte, bevor man etwas ändert

  • docs/DESIGN.md — warum Erkennung besser ist als Suche, was die Schleuse erkauft und welcher Fehler jedes Verfahren motiviert hat.

  • docs/OPERATING.md — Betrieb als residenter Dienst, Planer und Exit- Codes, Backups, worauf man achten muss.

  • docs/TRUST.md — was eine Speichergrenze ist und was nicht, Schreib- richtlinien und die zwei Grenzen, die man leicht übersieht (gemeinsame Journale, gemeinsame Modelle). Lesen Sie es, bevor ein privater Speicher in Betrieb geht.

Ein paar Entscheidungen, die seltsam wirken, bis man auf den Fehler stößt, den sie verhindern:

  • Reservieren, bevor man trinkt. Der Destillierer beansprucht einen Journalabschnitt, bevor er ihn liest, unter einer Sperre, und Wasserstände bewegen sich nur vorwärts. Zwei Destillierer, die jeweils ihren eigenen Schnappschuss zurückschreiben, hätten sonst den Fortschritt des anderen gelöscht und denselben Abschnitt ein Dutzend Mal erneut gelesen.

  • Wasserstände sind pro Adapter. Byte-Offsets für reine Anhänge-Protokolle, Sequenznummern für Archive, die neu geschrieben werden (ein Byte-Offset in einer neu komprimierten Datei ist eine Lüge).

  • Echo-Unterdrückung. Ein Zitat, das bereits im Speicher existiert, ist kein neues Material — es ist der Speicher, der sich selbst durch ein Werkzeugergebnis zurückliest. Ohne dies würde ein Speichersystem seine eigenen Inhalte endlos neu aufzeichnen.

  • Die letzte Schleuse ist ein Modell, kein Mensch. Wenn ein Mensch jeden Entwurf genehmigen muss, hat das System diesen Menschen heimlich zum Engpass gemacht, und Entwürfe stapeln sich endlos. Nichts im Ablauf darf jemanden erfordern, der nicht ständig anwesend ist.

  • kura distill run endet mit Exit-Code 2, wenn es nichts zu tun gab. Ein Planer muss unterscheiden können zwischen „hat Arbeit erledigt" und „hat nichts gefunden", sonst dreht eine Überwachung durch und hungert die Schritte aus, die auf den Ruhezustand angewiesen sind.

Messen statt behaupten

Zwei Fragen werden mit einer Zahl beantwortet und sollten es nicht.

Wie viel kleiner? store_ratio = Token in den Erinnerungen und im Index / Token des tatsächlich verbrauchten Journals. Was ging verloren? Das ist eine andere Messgröße, und ein Speicher, der eine von hundert Erinnerungen aufbewahrt, glänzt bei der ersten Frage, während er bei der zweiten nutzlos ist.

kura bench compress                       # what this store cost, from the distiller's own metrics
kura bench compress --tokenizer-command "./count-tokens"   # exact, not estimated
kura bench retention --questions bench/fixtures/questions.json

Gemessen mit den mitgelieferten Testdaten und dem eingebauten Schätzer:

Korpus

store_ratio

scripts/demo-clean-room.sh (gewöhnlicher Chat, meist Füllmaterial)

0.18

bench/fixtures/corpus.jsonl (dicht: jede Zeile ist Information)

1.14

Der zweite Wert ist kein Fehler. Bei Material, in dem nichts Füllmaterial ist, verkleinert Destillation nicht — jede Erinnerung fügt ihr Warum und Wie anzuwenden hinzu, und der Speicher wird geringfügig größer als das Transkript. Die Kennzahl ist eine Eigenschaft des Korpus, nicht dieses Werkzeugs, weshalb es hier keine einzelne Headline-Zahl gibt und der Befehl stattdessen meldet, was er gezählt hat.

Bewertung ohne Modell

Die Bewertung ist modellfrei: jede eingepflanzte Tatsache trägt eine Markierung, die in dem erscheinen muss, was die Erinnerungssuche zurückgibt, sodass das Ergebnis auf einer fremden Maschine reproduzierbar ist. Ablenker kehren das Vorzeichen um — eine Tatsache, die mit must_not_store markiert ist, kostet einen Punkt, wenn der Speicher sie behalten hat, denn ein Speichersystem wird ebenso danach beurteilt, was es ablehnt, wie danach, was es bewahrt.

score 1.0 (10/10)   decision 1/1  number 2/2  negation 1/1  reversal 1/1
                    conditional 1/1  landmine 1/1  returning 1/1  distractor 2/2

Das sind zehn eingepflanzte Tatsachen in einem synthetischen Testaufbau, destilliert von einem lokalen Qwen3.8-27B (NVFP4) als Gehirn und Schreiber mit max_items = 8, coverage_passes = 2, und bewertet mit demselben Modell als Denker. Ein anderes Modell ergibt eine andere Bewertung: Die Bewertung misst eine Pipeline-plus-Modell-Kombination, und der Testaufbau existiert, damit das Modell das einzige ist, was sich unterscheidet. Sie misst, ob eine Tatsache auffindbar ist, nicht ob die Antwort gut formuliert ist — die Beurteilung von Prosa braucht ein Modell, und dann ist die Messung nicht mehr reproduzierbar.

kura distill run schreibt eine Zeile pro Stapel in _still/metrics.jsonl, und dorther kommen die Rohdaten. Die kanonische Seite zählt nur Erinnerungen, deren Evidenz- manifest auf einen aufgezeichneten Stapel verweist — das Dividieren durch das Rohmaterial eines einzelnen Stapels ergäbe eine Zahl in die falsche Richtung um eine Größenordnung, und die erste Version dieses Befehls tat genau das. Erinnerungen, die älter sind als die Manifeste, werden gemeldet als unattributed, nicht stillschweigend einbezogen. Die Rohdaten-Seite ist immer die Seite des Destillierers, also wird bei --tokenizer-command das Verhältnis als mixed gekennzeichnet.

Voraussetzungen

Anforderung

Python

3.11+ (keine Abhängigkeiten; pip install -e ".[dev]" fügt nur pytest hinzu)

Node

20+, nur für das DSH-Plugin

zstd

nur zum Lesen von DSH-Sitzungsarchiven

Modell-Endpunkt

alles, das POST <url>/chat/completions im OpenAI-Format beantwortet

„OpenAI-kompatibel" ist enger als „beliebiger Anbieter". Die native API eines Anbieters braucht ein OpenAI-kompatibles Gateway davor; seine eigene URL reicht nicht. Ein strenger Dienst lehnt auch unbekannte Felder auf oberster Ebene ab, also setzen Sie dialect = "openai" (oder "generic") — der Standardwert "vllm" sendet chat_template_kwargs, was lokale Server wollen, ein strenger jedoch mit 400 beantwortet. Der Client wiederholt einmal mit einem schlichten Body und protokolliert, warum ein Aufruf fehlschlug, anstatt jede Ursache in einem stillen None verschwinden zu lassen.

Tests

python3 -m pytest tests -q                              # 145 tests, no model required
cd dsh-plugin && npm test                               # 24 more for the plugin

Die Schleuse wird adversariell getestet: Jeder Fall ist eine Art, wie ein echtes Modell tatsächlich versucht hat, etwas an ihr vorbeizuschmuggeln. test_containment.py ist auf dieselbe Weise geschrieben — jeder Fall ist ein Ausbruchsversuch, kein glücklicher Pfad — weil es ein Loch bewacht, das real war: Ein Speicher antwortete früher für jede Datei, deren Pfad man buchstabieren konnte. Der End-to-End-Test führt einen vollständigen Distill→Drain-Zyklus gegen einen skriptgesteuerten Modellserver auf einem echten Socket aus.

Lizenz

MIT.

Available Tools

6 tools
kura_doctorA

Health check of the kura: how many memories, resolved and dead [[links]], islands (memories nothing links to), index drift. Call when recall behaves oddly, or when asked about the memory system itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeNoWhich kura. Omit for the current one.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It does well by naming the diagnostic nature ('health check'), the categories of data inspected, and the symptom-triggered use case. It does not explicitly state whether the tool is read-only or whether any repair/reindexing occurs, but 'health check' strongly implies diagnostic rather than mutating behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact: two sentences, front-loaded with the core purpose, followed by a concise list of diagnostic metrics and explicit usage triggers. Every clause earns its place, with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with zero required parameters and a fully documented optional parameter, the description provides enough context to select and invoke the tool correctly. It explains what will be inspected and when to use it. The only gap is that it does not describe the return format or explicitly confirm the absence of side effects, but neither is critical for a diagnostic health-check tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the description provides no additional parameter-level meaning beyond what the schema already states. The optional 'store' parameter is fully documented in the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb-resource pairing: 'Health check of the kura', and enumerates concrete diagnostic outputs (memory counts, resolved/dead links, islands, index drift). This clearly differentiates it from the sibling tools like kura_read or kura_recall, which focus on reading or retrieving memories rather than diagnosing system health.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: 'Call when recall behaves oddly, or when asked about the memory system itself.' This provides clear invocation context. However, it does not explicitly mention alternatives or when not to use it, so it stops just short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kura_listA

List the kura this server holds and which agent mode each one belongs to. Call it when you are unsure which memory you are speaking from, or before switching.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It states the operation (list) and the output (kura and agent modes) but does not mention side effects, read-only nature, performance, or any edge cases. Adequate but not rich for a tool without annotation safety signals.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero wasted words. The first sentence states the core function; the second provides immediate usage context. Information is front-loaded and every word serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter list tool with no output schema, the description explains what is listed and exactly when to invoke it. It could mention what 'kura' refers to or if results are ordered, but the definition is sufficient for an agent to decide and call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the schema coverage is trivially 100%. Per the rubric, 0 params earns a baseline of 4. The description does not need to add parameter details since none exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'list', the resource 'kura', and what is listed (which agent mode each belongs to). It implies a distinction from siblings like kura_read or kura_recall by focusing on the server's collection and mode mapping, though it does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: 'Call it when you are unsure which memory you are speaking from, or before switching.' It lacks explicit when-not-to-use or named alternative tools, but the usage context is concrete and helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kura_mapA

Show the whole index of the kura — every memory's one-line recognition trigger, in one answer. Use it when you need to see WHAT EXISTS rather than look something up: before claiming a topic was never discussed, when choosing which memory to open, or right after switching kura. It is a map, not the contents: open a memory with kura_read for the detail.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeNoWhich kura. Omit for the current one.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden. It clearly frames a display operation ('Show the whole index... in one answer') and sets output expectations ('map, not the contents'). It does not discuss permissions or exact formatting, but for a non-mutating index tool the core behavioral disclosure is present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the first states the action and scope, the second gives concrete use cases, and the third clarifies depth and names the sibling for details. It is front-loaded and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity tool with one optional parameter and no output schema, the description provides the essential context: what it returns, when to use it, what it is not, and where to go for detail. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the single 'store' parameter is already documented as 'Which kura. Omit for the current one.' The description adds no parameter-level detail beyond that, so it meets the baseline but does not exceed it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Show the whole index of the kura - every memory's one-line recognition trigger.' It also distinguishes itself from siblings by saying it is 'a map, not the contents' and explicitly directs details to kura_read, so an agent can tell it apart from the other tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use conditions ('when you need to see WHAT EXISTS... before claiming a topic was never discussed, when choosing which memory to open, or right after switching kura') and an explicit alternative ('open a memory with kura_read for the detail'). This is clear routing guidance rather than leaving usage to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kura_readA

Read one whole memory from the kura by its slug (e.g. 'storage-doctrine'). Use after kura_recall when a summary is not enough and you need the full text.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugYesMemory slug, without .md
storeNoWhich kura. Omit for the current one.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations available, the description carries the burden of behavior. It clearly indicates a read operation fetching the full memory text, which is sufficient for this simple tool. It could add detail about return format or failure behavior, but the core behavior is transparent enough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The primary behavior is front-loaded, and the usage guidance, alternative, and selection condition are packed efficiently into the second sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-by-slug tool with only two parameters, no output schema, and full schema coverage, the description is complete. It tells the agent what it does, when to use it, and provides an example. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds a useful example slug ('storage-doctrine') but otherwise does not need to add much beyond what the schema already documents for 'slug' and 'store'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Read'), the resource ('one whole memory'), and the retrieval key ('by its slug'), with a concrete example. It also names the sibling tool it complements, distinguishing it from kura_recall without needing to inspect the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool: 'Use after kura_recall when a summary is not enough and you need the full text.' This directly routes the agent to the appropriate alternative and gives a clear selection condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kura_recallA

Recall from the kura — long-term memory retrieved by MEANING rather than keyword, then following [[links]] between memories. Call it whenever the question touches past decisions, measurements, people, machines, or anything done before — prefer it over guessing. An empty result means it is simply not remembered yet: say so plainly and never fill the gap with invention. Pass store to reach a different kura, or call kura_use to switch for the session.

ParametersJSON Schema
NameRequiredDescriptionDefault
hopsNoHow many [[link]] hops to walk (default 1)
storeNoWhich kura to ask (store or mode name). Omit for the current one.
questionYesWhat you want to remember, as a natural question

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are absent, so the description carries the full burden of behavioral disclosure. It does reveal important behavior: it retrieves by meaning, follows links, and emphasizes not to fabricate when no result is found. However, it does not disclose potential side effects, rate limits, or what happens with the hops parameter (e.g., how deep the search goes and whether more hops affect latency). It also doesn't specify if the tool is read-only, though recall implies reading. Overall, it gives useful context but leaves some behavioral aspects unmentioned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, dense paragraph but contains no filler. It front-loads the core purpose and usage guidance, then addresses edge cases and parameter use. It is appropriately sized for a tool with multiple interconnected behaviors (meaning-based recall, link-following, empty result handling). It could be slightly more structured (e.g., bullet points for handling empty results or parameter variants), but it is efficient and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 parameters (1 required), no output schema, and moderate complexity due to link-following and alternate stores, the description covers the essential aspects: what it does, when to use it, how to handle empty results, and how to use parameters. It does not explicitly describe return format (e.g., whether it returns text or a list of memories), but with no output schema, it could have provided more on that. Missing details on hops behavior and potential limitations are minor gaps. Overall, it is fairly complete for an agent to use it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents all three parameters (question, hops, store) with descriptions, and coverage is 100%, so the baseline for parameter semantics is 3. The description adds value by explaining the semantics of 'store' ('reach a different kura') and hints that 'question' should be phrased as a natural question. It also implies the meaning of 'hops' (following [[links]]). It doesn't detail the format or constraints beyond the schema, but it enriches the meaning of each parameter sufficiently.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Recall from the kura — long-term memory retrieved by MEANING rather than keyword, then following [[links]] between memories.' It differentiates itself from siblings by emphasizing meaning-based retrieval over keyword, which distinguishes it from tools like kura_read or kura_list. It also mentions specific use cases, making it easy for an agent to understand what it does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent when to use this tool: 'Call it whenever the question touches past decisions, measurements, people, machines, or anything done before — prefer it over guessing.' It also explains what to do on empty results ('An empty result means it is simply not remembered yet: say so plainly and never fill the gap with invention') and mentions alternatives or related actions ('Pass store to reach a different kura, or call kura_use to switch for the session'). This provides clear guidance on selection and behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kura_useA

Switch which kura the following calls read from, for the rest of this session. Use when the conversation moves to a different mode of work (for example from building things to talking things through). Has no effect on a bridge that was bound to a single kura at startup — it will say so.

ParametersJSON Schema
NameRequiredDescriptionDefault
storeYesStore or mode name

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It does this well by revealing that the switch persists for the session, affects subsequent calls, and has no effect on a single-kura bridge (and that it will say so). It does not cover every possible error or side effect, but the key stateful behavior is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no wasted words. The main effect and scope are front-loaded, the usage condition follows, and the edge case is placed last. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter state-switching tool with no annotations and no output schema, this description is complete enough. It explains what the tool does, when to invoke it, how long the effect lasts, and the one major exception an agent needs to know about.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% — 'store' is already described as 'Store or mode name.' The description adds some context by suggesting that stores correspond to modes of work, but it does not enumerate valid values or add meaningful parameter detail beyond the schema. This is the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Switch') and names both the resource ('which kura the following calls read from') and the scope ('rest of this session'). This clearly distinguishes it from the sibling read/analysis tools like kura_read and kura_map, which retrieve data rather than change the active context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use it: 'Use when the conversation moves to a different mode of work,' with a concrete example. It also discloses a limitation about bridges bound to a single kura. It does not explicitly name sibling alternatives or state when not to use it, but the intended context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.1.0
    • First observedkura_doctor
    • First observedkura_list
    • First observedkura_map
    • First observedkura_read
    • First observedkura_recall
    • First observedkura_use

TDQS

A4.3/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a distinct purpose: recall for meaning-based search, read for slug-based retrieval, map for index views, doctor for health checks, list for enumerating kuras, and use for switching. No overlap in functionality.

Naming Consistency5/5

All tools follow the same `kura_` prefix with a verb-based second part (recall, read, map, doctor, list, use), creating a consistent and predictable naming scheme.

Tool Count5/5

Six tools is a well-scoped number for a memory-management server, covering retrieval, inspection, maintenance, and context switching without excess or deficiency.

Completeness4/5

The set covers all read and management operations (recall, read, map, health, list, switch), but lacks an explicit write or delete capability, which is a minor gap for a full memory system. Agents can work around this by relying on existing memories.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents with persistent, searchable memory that survives across conversations using semantic search, temporal versioning, and smart organization. Enables long-term context retention and cross-session continuity for AI assistants.
    14
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides persistent, searchable memory for MCP-compatible agents, enabling recall by meaning, automatic decay, trust scoring, and cross-agent handoffs.
    5
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides long-term memory and a temporal knowledge graph for AI agents, enabling persistent memory and reasoning across sessions.
    33
    101 PyPI
    2
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Provides persistent memory for AI agents, including context storage, facts, plans, RAG search, code snippets, and conversation compaction, enabling state to survive across sessions and processes.
    14
    14 npm
    2
    MIT