kura
蒸留蔵 — distill-kura
Una memoria a largo plazo para agentes que está destilada, no acumulada. El recuerdo funciona por significado, la escritura está controlada por evidencia, y un mismo servidor puede tener varias memorias separadas — una por cada modo de agente — de modo que cambiar de modo cambia lo que el agente recuerda.
Se distribuye como un plugin de DeepSeek Harness, un servidor MCP para cualquier otro host, un servicio HTTP y una librería de Python. Solo con la biblioteca estándar; sin base de datos vectorial, sin embeddings, sin 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 │
└────────────────────────────────────────────────────────┘Por qué existe esto
Dos fallos matan la memoria a largo plazo de un agente, y la matan desde lados opuestos.
Recuperar por palabra clave pierde lo que necesitabas. Una pregunta sobre “chips de inferencia SSD” no comparte ninguna palabra con una memoria titulada “ejecutando el modelo de 2.6T desde un nivel de almacenamiento SSD” — y sin embargo son el mismo tema. La búsqueda de palabras no devuelve nada; el agente responde desde la nada. La solución aquí no son los embeddings sino el reconocimiento: el índice completo (una línea por memoria, escrita como un desencadenador de reconocimiento) va en un solo prompt, y un modelo pequeño nombra lo que tiene relación con la cuestión. Un índice de ~500 memorias ocupa unos 6k tokens — un pequeño porcentaje de una ventana de contexto moderna, y se queda en la caché de prefijo.
Escribirlo todo envenena el almacén. Un agente afirma algo; el sistema de destilado registra la afirmación como un hecho; el siguiente agente lo lee como verdad absoluta y lo repite con más confianza. Ese bucle se auto-refuerza, y las instrucciones no lo detienen — eso está medido, no asumido. Así que la ruta de escritura está controlada por Python determinista: toda memoria candidata debe llevar citas que existan carácter por carácter en el material de origen, etiquetadas con su procedencia.
clase | qué es | qué autoriza |
| las palabras del propio usuario | “ellos decidieron”, “ellos pidieron” |
| salida de máquina | los números — la única fuente |
| una herramienta que fue invocada | "esto ocurrió", "esto se hizo" |
| la prosa del propio agente | un juicio, en primera persona, nunca un dato crudo |
Una cita que no se encuentra textualmente se descarta. Un candidato sin ninguna cita superviviente se elimina. Un número sin un [TOOL] que lo respalde se suprime. El texto que atribuye una decisión a la persona, si no sobrevive ninguna cita de [USER], es rechazado en la última puerta. Las ideas son bienvenidas — van a un archivo semilla, nunca al almacén, y se convierten en memoria solo cuando a evidencia posterior las confirme.
Related MCP server: Synapto
Inicio rápido
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:8085curl -s -X POST localhost:8085/recall -H 'content-type: application/json' \
-d '{"question":"what did we decide about the archive disk?","hops":1}'Incorpora el índice para que el agente siempre sepa lo que sabe:
kura weave # build the three-layer cloth
kura prefill # the block to put in the system promptDele las transcripciones de tus agentes:
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 quietNada entra en el almacén hasta drain (o un pour manual). Los borradores llevan su evidencia en un comentario HTML, así siempre puedes ver por qué existe una memoria.
El mapa residente
La recuperación como herramienta responde a “¿qué sabes sobre X?” — pero solo una vez que el agente ha decidido preguntar. Nunca responde a la pregunta que el agente no piensa en hacer: ¿hay algo aquí o no? Un agente que no ve el mapa no sabe qué está perdiéndose, así que se pone a adivinar, y una suposición segura sobre tu propio contexto es exactamente la falla que este proyecto existe para prevenir.
Por eso el índice también está presente: es un bloque permanente en el prompt del sistema, en cada turno.
kura weave # re-weave the index into the three-layer cloth
kura prefill # print the block a host should injectTres capas, porque el detalle solo paga para lo reciente
Una prueba A/B a ciegas — 20 preguntas, índice amplio contra índice reducido, corregido sin saber cuál era cuál — determinó la forma:
banda | amplio | ligero |
general | 9 | 11 |
eventos recientes | 4 | 1 |
doctrina | 1 | 4 |
saltos entre dominios | 1 | 4 |
Las líneas de doctrina eran byte idénticas en los dos índices, y el índice más reducido aun así ganó esa categoría: un entorno más ligero deja ver mejor las líneas fijas. El detalle no esa fuente de comprensión. Se gana su lugar solo donde las cosas siguen en movimiento.
capa | regla | línea |
fija | el | se conserva por completo |
reciente | tocado dentro de | se conserva por completo |
disparador | todo lo demás | comprimido a |
Las líneas de activación las escribe el modelo scribe y se guardan en un registro con una clave basada en la descripción y en el presupuesto, de manera que un re-tejido en el estado estable no cueste nada. Si no hay ningún modelo disponible, el telar recorta mecánicamente en su lugar — un sistema de memoria nunca debe quedar en blanco porque una GPU se haya caído.
La edad no es el mtime. Un cp -r, una restauración o un checkout activa todas las marcas de tiempo, todo el índice se vuelve "reciente", no se descarta nada, y el mecanismo se ha deshabilitado silenciosamente. Por eso el telar prefiere una fecha escrita dentro de la memoria, y rechaza cualquier mtime que una quinta parte del almacén esté compartiendo con el mismo día del calendario.
Dónde va y por qué es una decisión sobre la caché
- id: kura
name: distill-kura
config: { store: eq, promptOrder: -50 } # before the personaUna caché de prefijo se pierde desde el primer byte que cambia — como se midió en un servidor local: un preámbulo idéntico de 4.029 tokens cambia de 0.68 s a 0.14 s, añadir al final sigue siendo 0.14 s, y añadir una palabra al principio cuesta toda la caché (0.66 s). La persona que usa el sistema suele tener un reloj, así que cambia cada minuto; el mapa es el bloque más grande del prompt y cambia un puñado de veces al año. Lo grande y estable va delante de lo que da tic y tac.
Por eso el bloque no contiene fecha, ni hora, ni contador — y build() rechaza un encabezado que la tuviera, en tiempo de construcción y no a través de turnos misteriosamente lentos tres semanas después.
Nunca entrega medio mapa
situación | qué recibe el agente |
todo está bien | el mapa completo, entre los marcadores |
se supera | todo el mapa, y una advertencia en el JSON (nunca en texto, porque un banner es contenido volátil) |
se supera | un stub sin líneas de índice, que dice que el mapa falta, no no que está vacío |
kura inaccesible | una nota explícita de que el mapa falta, nunca una cadena vacía |
Un mapa truncado es el peor artefacto posible: parece completo, y cualquier memoria que quede por debajo del corte aparentemente no existir. weave acortará la ventana de frescos para que quepa, pero nunca eliminará una línea; y si ningún ajuste llega al presupuesto, lo dice, y mantiene el mejor mapa que pueda y indica dónde está el peso.
Cómo integrarlo en un host
Host | Uso/Téc de implementación |
DSH | plugin nativo — un |
Claude Code, VS Code, Goose | El campo |
Claude Desktop, Claude.ai | ignoran por completo |
cualquier otro |
|
El campo instructions de MCP es un MAY en la especificación, y un índice de 9000 tokens no puede viajar a través de un límite de 2 KB de ningún forma, así que este proyecto no lo oculta.
Modos: más de un kura
Una sola memoria que sirve tanto para "ayúdame a construir esto" como para "ayúdame a pensar en esto" no sirve bien para ninguna de las dos: lo que te ayuda a depurar es ruido en una conversación sobre qué hacer a continuación. Por eso un almacén es un directorio, y un modo está asociado a un almacén.
[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"Cada ruta toma un selector, así que un mismo proceso puede servirlos todos:
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 URLLos almacenes no comparten ni memorias, ni índice, ni marca de agua del destino. Cambiar de modo cambia de verdad lo que se recuerda — no es la misma memoria dicha de otra forma.
Independientes como enrutamiento, no como confidencialidad. El servidor no tiene autenticación, así que cualquier proceso que pueda llegar a su puerto puede nombrar cualquiera de los almacenes que contenga. Atar un agente mantiene a un modelo dentro de su carril; no mantiene a un proceso fuera. Hay un solo nivel de confianza por proceso; docs/TRUST.md es solo breve y vale la pena leerlo antes de poner un almacén privado. Ahí se trata también los dos límites que son fáciles de pasar por alto: dos almacenes que beben de la misma raíz del diario, y dos almacenes que están detrás de un mismo servidor de modelo.
Con DeepSeek Openark
DSH cambia la persona y las herramientas mediante el preajuste del agente. distill-kura cambia la arquitectura mediante el almacén. Visona un preajuste y todo el ser se mueve:
# .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.)Deja allowSwitch en su valor predeterminado y el agente también tienes kura_use, así puede desplazarse entre kura en el transcurso de la conversación sin cambiar de preajuste de herramientas: kura_recall, kura_read, kura_doctor, kura_list, kura_use y kura_remember (solo cuando el almacén es escribible). La integración completa, incluyendo el puente MCP y la regla de aislamiento del dominio isolate para filas de servicio, está en examples/pre~remote/.
La persona es asunto del anfitrión, no nuestra. Este proyecto nunca niche render ni inyecta una persona; solo registra, por almacén, qué archivo de persona le corresponde, que se puede leer en GET /profile?store=eq, para que las dos mitades puedan mantenerse en sincronía por quien controle el preajuste. Las instrucciones del agente también se quedan con el mecanismo AGENTS.md del anfitrión; ver AGENTS.md en este repo para las convenciones que debe seguir un agente que trabaja en este código.
Con cualquier host MCP
{ "mcpServers": { "kura": {
"command": "python3", "args": ["-m", "distill_kura.mcp"],
"env": { "KURA_URL": "http://127.0.0.1:8085", "KURA_STORE": "eq", "KURA_READONLY": "1" }
}}}Deje KURA_STORE libre sin configurar para el modo libre: las herramientas aceptan una store opcional, y kura_use switch de sesión.
Modelos: uno por defecto, reparto ese número a la vez
Son tres roles, no tres personas:
rol | cuándo se ejecuta | necesita * |
| cada vez que se hace una búsqueda | pequeño y rápido; debe juzgar relevancia por el significado |
| destilando: lee una edición completa del diario | longitud de contexto y paciencia |
| destilando: escribe el recuerdo y luego juzga los conocimientos | buena prosa en tu idioma y buen juicio |
Declara solo [models.thinker] y un solo modelo se queda con los tres roles. Eleva de nivel a cualquiera de los otros dos independientemente — un modelo local más grande, o una API en línea (cualquiera compatible con /chat/completions; la clave se lee de una variable de entorno que tú nombre, no se guarda nunca en la configuración):
[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"Dos cosas que este sistema maneja por ti: los dialectos de esfuerzo de razonamiento difieren por familia de modelos (reasoning_effort, thinking_effort, enable_thinking), así que se envían todos — las desconocidas se ignoran en la plantilla, y un modelo que por defecto queda en el modo de pensamiento profundo puede gastar todo su presupuesto en razonar y no devolver nada. Also el texto de la carta se coloca idéntico byte a byte al frente del prompt de cada rol, de manera que en un modelo local lento los tres model usen una sola caché de prefijo en lugar de hacer tres prefijos diferencias.
Si el pensador está caído, recall no se queda en silencio — recurre a la superposición
de palabras y etiqueta la respuesta como how=words, que las herramientas muestran como
⚠ degraded. La degradación silenciosa es peor que la degradación.
Cómo es una memoria
Un archivo, un hecho.
---
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]]Y una línea en MEMORY.md:
- [Archive on the slow disk](archive-on-slow-disk.md) — the archive lives on the slow disk; the fast one stays scratchEsa línea es lo único que se lee absolutamente siempre. Es un disparador de
reconocimiento, no un resumen: nombres propios, números, ⚠️ minas, la conclusión
alcanzada. Si una línea pudiera intercambiarse con la línea de otra memoria y seguir
leyéndose bien, no está haciendo su trabajo — kura distill tidy encuentra los casos
mecánicamente detectables y los reescribe.
kura doctor informa de recuentos, enlaces muertos, islas (memorias a las que nada
enlaza) y deriva del índice. Es el ojo que el metabolismo necesita.
La superficie HTTP
ruta | qué hace |
|
|
|
|
| el índice sin procesar |
| el bloque residente, listo para inyectar ( |
| una memoria completa |
| salud de un almacén ( |
| almacenes, modos y qué modelo desempeña cada rol |
| la carta del almacén y un puntero a su persona (nunca se renderiza aquí) |
| disponibilidad |
Cualquier ruta acepta ?store= / ?mode=, un campo store/mode en el cuerpo, o el
prefijo de ruta /s/<name>/…. No hay autenticación: enlázalo a loopback o pon algo delante.
Notas de diseño que conviene leer antes de cambiar nada
docs/DESIGN.md — por qué el reconocimiento supera a la búsqueda, qué aporta la compuerta y el fallo que motivó cada mecanismo.
docs/OPERATING.md — ejecutarlo residente, planificadores y códigos de salida, copias de seguridad, qué vigilar.
docs/TRUST.md — qué es y qué no es un límite de almacén, políticas de escritura y los dos límites que son fáciles de pasar por alto (diarios compartidos, modelos compartidos). Léelo antes de poner en marcha un almacén privado.
Algunas decisiones que parecen extrañas hasta que te topas con lo que evitan:
Reservar antes de beber. El destilador reclama un tramo del diario antes de leerlo, bajo un bloqueo, y las marcas de agua solo avanzan. Dos destiladores que escribían cada uno su propia instantánea borraron el progreso del otro y volvieron a beber la misma agua una docena de veces.
Las marcas de agua son unidades por adaptador. Desplazamientos de bytes para transcripciones de solo añadir, números de secuencia para archivos que se reescriben (un desplazamiento de bytes dentro de un archivo recompimido es una mentira).
Supresión de eco. Una cita que ya existe en el almacén no es material nuevo: es el almacén leyéndose a sí mismo a través del resultado de una herramienta. Sin esto, un sistema de memoria redescubre y vuelve a registrar sus propios contenidos para siempre.
La última compuerta es un modelo, no un humano. Si una persona debe aprobar cada borrador, el sistema ha convertido silenciosamente a esa persona en su cuello de botella, y los borradores se acumulan para siempre. Nada en el bucle puede requerir a alguien que no esté siempre presente.
kura distill runsale con el código 2 cuando no había nada que hacer. Un planificador debe poder distinguir "hizo trabajo" de "no encontró nada", o un vigilante gira en una cola vacía y priva de recursos a los pasos que necesitan el tiempo de inactividad.
Medirlo, en lugar de afirmarlo
Dos preguntas se responden con un solo número y no deberían.
¿Cuánto más pequeño? store_ratio = tokens en las memorias y el índice / tokens del diario
bruto realmente consumido. ¿Qué se perdió? Esa es una medición diferente, y un almacén que
guarda una memoria de cada cien obtiene una puntuación magnífica en la primera mientras es inútil.
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.jsonMedido aquí, con los datos de prueba incluidos y el estimador integrado:
corpus |
|
| 0.18 |
| 1.14 |
El segundo no es un error. Con material donde nada es relleno, destilar no comprime: cada memoria añade su porqué y su cómo aplicarlo, y el almacén sale ligeramente más grande que la transcripción. La proporción es una propiedad del corpus, no de esta herramienta, por lo que aquí no hay una cifra destacada y por lo que el comando informa de con qué ha contado.
La retención se puntúa sin modelos: cada hecho plantado lleva un marcador que debe aparecer en lo
que devuelve recall, de modo que la puntuación es reproducible en la máquina de otro. Los distractores
invierten la puntuación: un hecho marcado con must_not_store cuesta un punto si el almacén lo ha
conservado, porque un sistema de memoria se juzga tanto por lo que rechaza como por lo que conserva.
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/2Eso son diez hechos plantados en un banco de pruebas sintético, destilados por un Qwen3.8-27B local
(NVFP4) como cerebro y escriba con max_items = 8, coverage_passes = 2, y puntuados con el mismo
modelo como pensador. Un modelo diferente dará una puntuación diferente: la puntuación mide un
pipeline más modelo, y el banco de pruebas existe para que el modelo sea lo único que varíe. Mide si
un hecho es encontrable, no si la respuesta se lee bien: juzgar la prosa necesita un modelo, y
entonces el benchmark deja de ser reproducible.
kura distill run escribe una línea por lote en _still/metrics.jsonl, que es de donde proviene el
lado bruto. El lado canónico cuenta solo las memorias cuyo manifiesto de evidencia apunta a un lote
registrado — dividir un almacén entero por el material bruto de unos pocos lotes da un número
desviado por un orden de magnitud, y la primera versión de este comando hizo exactamente eso. Las
memorias anteriores a los manifiestos se notifican como unattributed, no se incluyen
silenciosamente. El lado bruto es siempre la estimación del destilador en el momento de beber, así que
con --tokenizer-command la proporción se etiqueta como mixed.
Contra qué se ejecuta
requisito | |
Python | 3.11+ (sin dependencias; |
Node | 20+, solo para el plugin DSH |
| solo para leer archivos de sesión DSH |
endpoint de modelo | cualquier cosa que responda a |
"OpenAI-compatible" es más estricto que "cualquier proveedor". La API nativa de un proveedor
necesita una pasarela compatible con OpenAI delante; su propia URL no sirve. Un servicio estricto
también rechaza campos de nivel superior desconocidos, así que configura dialect = "openai" (o
"generic") — el valor predeterminado "vllm" envía chat_template_kwargs, que los servidores
locales quieren y uno estricto responde con 400. El cliente reintenta una vez con un cuerpo simple y
registra por qué falló una llamada, en lugar de reducir cada causa a un None silencioso.
Pruebas
python3 -m pytest tests -q # 145 tests, no model required
cd dsh-plugin && npm test # 24 more for the pluginLa compuerta se prueba de forma adversarial: cada caso es una forma en que un modelo real intentó
realmente colar algo. test_containment.py está escrito de la misma manera — cada caso es un intento
de escape, no un camino feliz — porque protege un agujero que era real: un almacén solía responder por
cualquier archivo cuya ruta pudieras escribir. La prueba de extremo a extremo ejecuta un ciclo completo
de distil→drain contra un servidor de modelos con guion en un socket real.
Licencia
MIT.
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides 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
- AlicenseNot gradedqualityAmaintenanceProvides persistent, searchable memory for MCP-compatible agents, enabling recall by meaning, automatic decay, trust scoring, and cross-agent handoffs.4MIT

Hebbrix MCP Serverofficial
AlicenseAqualityAmaintenanceProvides long-term memory and a temporal knowledge graph for AI agents, enabling persistent memory and reasoning across sessions.261MIT- AlicenseNot gradedqualityAmaintenanceRole-aware long-term Agent memory with cross-session recall, durable writes, and multi-Agent project scope.Apache 2.0
Related MCP Connectors
Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.
Persistent memory for AI agents. Search, store, and recall across sessions.
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/kisaragi-mochi/distill-kura'
If you have feedback or need assistance with the MCP directory API, please join our Discord server