Memoria
La memoria de OpenClaw es Markdown plano en el espacio de trabajo del agente. Los archivos son la fuente de la verdad; el modelo solo “recuerda” lo que se escribe en el disco. Las herramientas de búsqueda de memoria las proporciona el plugin de memoria activo (predeterminado:memory-core). Desactive los plugins de memoria con plugins.slots.memory = "none".
Archivos de memoria (Markdown)
El diseño predeterminado del espacio de trabajo usa dos capas de memoria:memory/YYYY-MM-DD.md- Registro diario (solo anexado).
- Lee hoy + ayer al inicio de la sesión.
MEMORY.md(opcional)- Memoria a largo plazo curada.
- Solo se carga en la sesión principal y privada (nunca en contextos de grupo).
agents.defaults.workspace, valor predeterminado
~/.openclaw/workspace). Consulte Espacio de trabajo del agente para el diseño completo.
Cuándo escribir memoria
- Las decisiones, preferencias y hechos duraderos van a
MEMORY.md. - Las notas del día a día y el contexto en curso van a
memory/YYYY-MM-DD.md. - Si alguien dice “recuerda esto”, escríbalo (no lo mantenga en RAM).
- Esta área aún está evolucionando. Ayuda recordarle al modelo que almacene memorias; sabrá qué hacer.
- Si quiere que algo perdure, pídale al bot que lo escriba en la memoria.
Vaciado automático de memoria (ping previo a la compactación)
Cuando una sesión está cerca de la auto-compactación, OpenClaw activa un turno silencioso y agéntico que le recuerda al modelo escribir memoria duradera antes de que el contexto se compacte. Los mensajes predeterminados dicen explícitamente que el modelo puede responder, pero normalmenteNO_REPLY es la
respuesta correcta para que el usuario nunca vea este turno.
Esto se controla con agents.defaults.compaction.memoryFlush:
- Umbral suave: el vaciado se activa cuando la estimación de tokens de la sesión cruza
contextWindow - reserveTokensFloor - softThresholdTokens. - Silencioso de forma predeterminada: los mensajes incluyen
NO_REPLYpara que no se entregue nada. - Dos mensajes: un mensaje de usuario más un mensaje del sistema agregan el recordatorio.
- Un vaciado por ciclo de compactación (seguido en
sessions.json). - El espacio de trabajo debe ser escribible: si la sesión se ejecuta en sandbox con
workspaceAccess: "ro"o"none", se omite el vaciado.
Búsqueda de memoria vectorial
OpenClaw puede crear un pequeño índice vectorial sobreMEMORY.md y memory/*.md para que
las consultas semánticas encuentren notas relacionadas incluso cuando la redacción difiere.
Valores predeterminados:
- Habilitado de forma predeterminada.
- Observa cambios en los archivos de memoria (con debounce).
- Configura la búsqueda de memoria en
agents.defaults.memorySearch(no en el nivel superiormemorySearch). - Usa incrustaciones remotas de forma predeterminada. Si
memorySearch.providerno está configurado, OpenClaw selecciona automáticamente:localsi hay unmemorySearch.local.modelPathconfigurado y el archivo existe.openaisi se puede resolver una clave de OpenAI.geminisi se puede resolver una clave de Gemini.voyagesi se puede resolver una clave de Voyage.- De lo contrario, la búsqueda de memoria permanece deshabilitada hasta configurarse.
- El modo local usa node-llama-cpp y puede requerir
pnpm approve-builds. - Usa sqlite-vec (cuando está disponible) para acelerar la búsqueda vectorial dentro de SQLite.
models.providers.*.apiKey o variables de entorno. Codex OAuth
solo cubre chat/completions y no satisface incrustaciones para la búsqueda de memoria. Para Gemini,
use GEMINI_API_KEY o models.providers.google.apiKey. Para Voyage, use VOYAGE_API_KEY o
models.providers.voyage.apiKey. Al usar un endpoint compatible con OpenAI personalizado,
configure memorySearch.remote.apiKey (y opcional memorySearch.remote.headers).
Backend QMD (experimental)
Configurememory.backend = "qmd" para cambiar el indexador SQLite integrado por
QMD: un sidecar de búsqueda local-first que combina
BM25 + vectores + reranking. El Markdown sigue siendo la fuente de la verdad; OpenClaw
invoca QMD para la recuperación. Puntos clave:
Requisitos previos
- Deshabilitado de forma predeterminada. Active por configuración (
memory.backend = "qmd"). - Instale el CLI de QMD por separado (
bun install -g https://github.com/tobi/qmdo descargue una versión) y asegúrese de que el binarioqmdesté en elPATHdel gateway. - QMD necesita una compilación de SQLite que permita extensiones (
brew install sqliteen macOS). - QMD se ejecuta completamente en local vía Bun +
node-llama-cppy descarga automáticamente modelos GGUF desde HuggingFace en el primer uso (no se requiere un daemon de Ollama separado). - El gateway ejecuta QMD en un hogar XDG autocontenido bajo
~/.openclaw/agents/<agentId>/qmd/configurandoXDG_CONFIG_HOMEyXDG_CACHE_HOME. - Soporte de SO: macOS y Linux funcionan listos para usar una vez que Bun + SQLite están instalados. Windows se soporta mejor vía WSL2.
- El gateway escribe un hogar QMD autocontenido bajo
~/.openclaw/agents/<agentId>/qmd/(configuración + caché + BD sqlite). - Las colecciones se crean vía
qmd collection adda partir dememory.qmd.paths(más los archivos de memoria predeterminados del espacio de trabajo), luegoqmd update+qmd embedse ejecutan al arranque y en un intervalo configurable (memory.qmd.update.interval, valor predeterminado 5 m). - El gateway ahora inicializa el gestor QMD al arrancar, por lo que los temporizadores de actualización periódica
se activan incluso antes de la primera llamada a
memory_search. - La actualización de arranque ahora se ejecuta en segundo plano de forma predeterminada para no
bloquear el inicio del chat; configure
memory.qmd.update.waitForBootSync = truepara mantener el comportamiento previo de bloqueo. - Las búsquedas se ejecutan vía
qmd query --json. Si el modo seleccionado rechaza flags en tu compilación de QMD, OpenClaw vuelve a intentarlo conqmd query. Si QMD falla o falta el binario, OpenClaw vuelve automáticamente al administrador SQLite integrado para que las herramientas de memoria sigan funcionando. - OpenClaw no expone hoy el ajuste del tamaño de lote de incrustaciones de QMD; el comportamiento por lotes lo controla el propio QMD.
- La primera búsqueda puede ser lenta: QMD puede descargar modelos GGUF locales (reranker/expansión de consulta)
en la primera ejecución de
qmd query.-
OpenClaw configura
XDG_CONFIG_HOME/XDG_CACHE_HOMEautomáticamente cuando ejecuta QMD. -
Si quiere predescargar modelos manualmente (y calentar el mismo índice que usa OpenClaw),
ejecute una consulta única con los directorios XDG del agente.
El estado QMD de OpenClaw vive bajo su directorio de estado (valor predeterminado
~/.openclaw). Puede apuntarqmdexactamente al mismo índice exportando las mismas variables XDG que usa OpenClaw:
-
OpenClaw configura
memory.qmd.*)
command(predeterminadoqmd): sobrescribe la ruta del ejecutable.searchMode(por defectosearch): elige qué comando QMD respaldamemory_search(search,vsearch,query).includeDefaultMemory(predeterminadotrue): autoindexaMEMORY.md+memory/**/*.md.paths[]: agrega directorios/archivos extra (path, opcionalpattern, opcional establename).sessions: habilita la indexación de JSONL de sesión (enabled,retentionDays,exportDir).update: controla la cadencia de actualización y la ejecución de mantenimiento: (interval,debounceMs,onBoot,waitForBootSync,embedInterval,commandTimeoutMs,updateTimeoutMs,embedTimeoutMs).limits: limita la carga útil de recuperación (maxResults,maxSnippetChars,maxInjectedChars,timeoutMs).scope: mismo esquema quesession.sendPolicy. El valor predeterminado es solo DM (denytodos,allowchats directos); relájelo para mostrar resultados de QMD en grupos/canales.match.keyPrefixcoincide con la clave de sesión normalizada (en minúsculas, con cualquier prefijo inicialagent:<id>:eliminado). Ejemplo:discord:channel:.match.rawKeyPrefixcoincide con la clave de sesión sin procesar (en minúsculas), incluyendoagent:<id>:. Ejemplo:agent:main:discord:.- Legado:
match.keyPrefix: "agent:..."todavía se trata como un prefijo de clave sin procesar, pero se prefiererawKeyPrefixpara mayor claridad.
- When
scopedenies a search, OpenClaw logs a warning with the derivedchannel/chatTypeso empty results are easier to debug. - Los fragmentos obtenidos fuera del espacio de trabajo aparecen como
qmd/<collection>/<relative-path>en los resultados dememory_search;memory_getentiende ese prefijo y lee desde la raíz de la colección QMD configurada. - Cuando
memory.qmd.sessions.enabled = true, OpenClaw exporta transcripciones de sesión saneadas (turnos Usuario/Asistente) a una colección QMD dedicada bajo~/.openclaw/agents/<id>/qmd/sessions/, de modo quememory_searchpueda recordar conversaciones recientes sin tocar el índice SQLite integrado. - Los fragmentos de
memory_searchahora incluyen un pie de páginaSource: <path#line>cuandomemory.citationsesauto/on; configurememory.citations = "off"para mantener los metadatos de ruta internos (el agente aún recibe la ruta paramemory_get, pero el texto del fragmento omite el pie y el mensaje del sistema advierte al agente que no lo cite).
memory.citationsaplica independientemente del backend (auto/on/off).- Cuando se ejecuta
qmd, etiquetamosstatus().backend = "qmd"para que los diagnósticos muestren qué motor sirvió los resultados. Si el subproceso de QMD sale o la salida JSON no se puede analizar, el administrador de búsqueda registra una advertencia y devuelve el proveedor integrado (incrustaciones Markdown existentes) hasta que QMD se recupere.
Rutas de memoria adicionales
Si quiere indexar archivos Markdown fuera del diseño predeterminado del espacio de trabajo, agregue rutas explícitas:- Las rutas pueden ser absolutas o relativas al espacio de trabajo.
- Los directorios se escanean recursivamente para archivos
.md. - Solo se indexan archivos Markdown.
- Los enlaces simbólicos se ignoran (archivos o directorios).
Incrustaciones Gemini (nativas)
Configure el proveedor comogemini para usar directamente la API de incrustaciones de Gemini:
remote.baseUrles opcional (por defecto, la URL base de la API de Gemini).remote.headersle permite agregar encabezados adicionales si es necesario.- Modelo predeterminado:
gemini-embedding-001.
remote con el proveedor OpenAI:
memorySearch.provider = "local" o configure
memorySearch.fallback = "none".
Fallbacks:
memorySearch.fallbackpuede seropenai,gemini,localonone.- El proveedor de fallback solo se usa cuando falla el proveedor primario de incrustaciones.
- Habilitada de forma predeterminada para incrustaciones de OpenAI y Gemini. Configure
agents.defaults.memorySearch.remote.batch.enabled = falsepara deshabilitar. - El comportamiento predeterminado espera a que se complete el lote; ajuste
remote.batch.wait,remote.batch.pollIntervalMsyremote.batch.timeoutMinutessi es necesario. - Configure
remote.batch.concurrencypara controlar cuántos trabajos por lotes enviamos en paralelo (predeterminado: 2). - El modo por lotes aplica cuando
memorySearch.provider = "openai"o"gemini"y usa la clave de API correspondiente. - Los trabajos por lotes de Gemini usan el endpoint asíncrono de lotes de incrustaciones y requieren disponibilidad de la API Batch de Gemini.
- Para rellenos grandes, OpenAI suele ser la opción más rápida que soportamos porque podemos enviar muchas solicitudes de incrustación en un solo trabajo por lotes y dejar que OpenAI las procese de forma asíncrona.
- OpenAI ofrece precios con descuento para cargas de trabajo de la API Batch, por lo que las ejecuciones de indexación grandes suelen ser más baratas que enviar las mismas solicitudes de forma sincrónica.
- Consulte los documentos y precios de la API Batch de OpenAI para más detalles:
memory_search— devuelve fragmentos con archivo + rangos de líneas.memory_get— lee el contenido del archivo de memoria por ruta.
- Configure
agents.defaults.memorySearch.provider = "local". - Proporcione
agents.defaults.memorySearch.local.modelPath(GGUF o URIhf:). - Opcional: configure
agents.defaults.memorySearch.fallback = "none"para evitar el fallback remoto.
Cómo funcionan las herramientas de memoria
memory_searchbusca semánticamente fragmentos Markdown (~400 tokens objetivo, superposición de 80 tokens) deMEMORY.md+memory/**/*.md. Devuelve texto del fragmento (limitado a ~700 caracteres), ruta del archivo, rango de líneas, puntuación, proveedor/modelo y si hubo fallback de incrustaciones locales → remotas. No se devuelve la carga útil completa del archivo.memory_getlee un archivo Markdown de memoria específico (relativo al espacio de trabajo), opcionalmente desde una línea inicial y por N líneas. Las rutas fuera deMEMORY.md/memory/se rechazan.- Ambas herramientas solo están habilitadas cuando
memorySearch.enabledse resuelve como verdadero para el agente.
Qué se indexa (y cuándo)
- Tipo de archivo: solo Markdown (
MEMORY.md,memory/**/*.md). - Almacenamiento del índice: SQLite por agente en
~/.openclaw/memory/<agentId>.sqlite(configurable víaagents.defaults.memorySearch.store.path, admite el token{agentId}). - Actualización: un observador en
MEMORY.md+memory/marca el índice como sucio (debounce 1.5s). La sincronización se programa al inicio de la sesión, en la búsqueda o en un intervalo y se ejecuta de forma asíncrona. Las transcripciones de sesión usan umbrales delta para activar la sincronización en segundo plano. - Disparadores de reindexación: el índice almacena el proveedor/modelo de incrustaciones + huella del endpoint + parámetros de fragmentación. Si cualquiera cambia, OpenClaw restablece y reindexa automáticamente todo el almacén.
Búsqueda híbrida (BM25 + vector)
Cuando está habilitada, OpenClaw combina:- Similitud vectorial (coincidencia semántica; la redacción puede diferir)
- Relevancia de palabras clave BM25 (tokens exactos como IDs, variables de entorno, símbolos de código)
¿Por qué híbrida?
La búsqueda vectorial es excelente para “esto significa lo mismo”:- “host del Gateway Mac Studio” vs “la máquina que ejecuta el gateway”
- “aplicar debounce a las actualizaciones de archivos” vs “evitar indexar en cada escritura”
- IDs (
a828e60,b3b9895a…) - símbolos de código (
memorySearch.query.hybrid) - cadenas de error (“sqlite-vec unavailable”)
Cómo combinamos resultados (diseño actual)
Boceto de implementación:- Recuperar un conjunto candidato de ambos lados:
- Vector: los primeros
maxResults * candidateMultiplierpor similitud coseno. - BM25: los primeros
maxResults * candidateMultiplierpor rango BM25 de FTS5 (más bajo es mejor).
- Convertir el rango BM25 en una puntuación aproximada 0..1:
textScore = 1 / (1 + max(0, bm25Rank))
- Unir candidatos por id de fragmento y calcular una puntuación ponderada:
finalScore = vectorWeight * vectorScore + textWeight * textScore
vectorWeight+textWeightse normaliza a 1.0 en la resolución de configuración, por lo que los pesos se comportan como porcentajes.- Si las incrustaciones no están disponibles (o el proveedor devuelve un vector cero), aun así ejecutamos BM25 y devolvemos coincidencias por palabras clave.
- Si FTS5 no se puede crear, mantenemos la búsqueda solo vectorial (sin fallo duro).
Embedding cache
OpenClaw puede almacenar en caché incrustaciones de fragmentos en SQLite para que la reindexación y las actualizaciones frecuentes (especialmente transcripciones de sesión) no vuelvan a incrustar texto sin cambios. Configuración:Búsqueda de memoria de sesión (experimental)
Opcionalmente puede indexar transcripciones de sesión y mostrarlas víamemory_search.
Esto está protegido por una bandera experimental.
- La indexación de sesión es opt-in (desactivada de forma predeterminada).
- Las actualizaciones de sesión se debounce y se indexan de forma asíncrona una vez que cruzan umbrales delta (mejor esfuerzo).
memory_searchnunca bloquea por indexación; los resultados pueden estar ligeramente desactualizados hasta que termine la sincronización en segundo plano.- Los resultados siguen incluyendo solo fragmentos;
memory_getpermanece limitado a archivos de memoria. - La indexación de sesión está aislada por agente (solo se indexan los registros de sesión de ese agente).
- Los registros de sesión viven en disco (
~/.openclaw/agents/<agentId>/sessions/*.jsonl). Cualquier proceso/usuario con acceso al sistema de archivos puede leerlos, así que trate el acceso al disco como el límite de confianza. Para un aislamiento más estricto, ejecute agentes bajo usuarios del SO o hosts separados.
Aceleración vectorial de SQLite (sqlite-vec)
Cuando la extensión sqlite-vec está disponible, OpenClaw almacena incrustaciones en una tabla virtual de SQLite (vec0) y realiza consultas de distancia vectorial en la
base de datos. Esto mantiene la búsqueda rápida sin cargar cada incrustación en JS.
Configuración (opcional):
enabledes verdadero por defecto; cuando se deshabilita, la búsqueda vuelve a la similitud coseno en proceso sobre incrustaciones almacenadas.- Si la extensión sqlite-vec falta o no se puede cargar, OpenClaw registra el error y continúa con el fallback en JS (sin tabla vectorial).
extensionPathsobrescribe la ruta incluida de sqlite-vec (útil para compilaciones personalizadas o ubicaciones de instalación no estándar).
Descarga automática de incrustaciones locales
- Modelo de incrustación local predeterminado:
hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf(~0.6 GB). - Cuando
memorySearch.provider = "local",node-llama-cppresuelvemodelPath; si el GGUF falta, se descarga automáticamente a la caché (olocal.modelCacheDirsi está configurado) y luego se carga. Las descargas se reanudan al reintentar. - Requisito de compilación nativa: ejecute
pnpm approve-builds, elijanode-llama-cpp, luegopnpm rebuild node-llama-cpp. - Fallback: si la configuración local falla y
memorySearch.fallback = "openai", cambiamos automáticamente a incrustaciones remotas (openai/text-embedding-3-smalla menos que se sobrescriba) y registramos el motivo.
Ejemplo de endpoint compatible con OpenAI personalizado
remote.*tiene prioridad sobremodels.providers.openai.*.remote.headersse combina con los encabezados de OpenAI; el remoto gana en conflictos de claves. Omitaremote.headerspara usar los valores predeterminados de OpenAI.