Сессии и памят ь
Память
Память OpenClaw — это обычные файлы Markdown в рабочей области агента. Файлы являются источником истины; модель «помнит» только то, что записано на диск. Инструменты поиска по памяти предоставляются активным плагином памяти (по умолчанию: memory-core). Отключите плагины памяти с помощью plugins.slots.memory = "none".
Файлы памяти (Markdown)
Стандартная структура рабочей области использует два слоя памяти:
memory/YYYY-MM-DD.md- Ежедневный журнал (дозапись).
- Читается сегодня + вчера при старте сессии.
MEMORY.md(опционально)- Курируемая долгосрочная память.
- Загружается только в главной, приватной сессии (никогда в групповых контекстах).
Эти файлы находятся в рабочей области (agents.defaults.workspace, по умолчанию ~/.openclaw/workspace). См. Рабочая область агента для полной структуры.
Инструменты памяти
OpenClaw предоставляет два инструмента для работы с этими файлами Markdown:
memory_search— семантический поиск по индексированным фрагментам.memory_get— целевое чтение конкретного файла Markdown/диапазона строк.
memory_get теперь корректно обрабатывает отсутствие файла (например, сегодняшний ежедневный журнал до первой записи). И встроенный менеджер, и бэкенд QMD возвращают { text: "", path } вместо выброса ошибки ENOENT, поэтому агенты могут обработать «пока ничего не записано» и продолжить свою работу без оборачивания вызова инструмента в try/catch.
Когда записывать в память
- Решения, предпочтения и устойчивые факты идут в
MEMORY.md. - Ежедневные заметки и текущий контекст идут в
memory/YYYY-MM-DD.md. - Если кто-то говорит «запомни это», запишите это (не храните в оперативной памяти).
- Эта область всё ещё развивается. Полезно напоминать модели сохранять воспоминания; она будет знать, что делать.
- Если вы хотите, чтобы что-то сохранилось, попросите бота записать это в память.
Автоматическая очистка памяти (предкомпактизационный пинг)
Когда сессия близка к автоматической компактизации, OpenClaw запускает тихий, агентский ход, который напоминает модели записать устойчивые воспоминания до компактизации контекста. Стандартные промпты явно говорят, что модель может ответить, но обычно правильным ответом является NO_REPLY, чтобы пользователь никогда не видел этот ход. Это контролируется параметром agents.defaults.compaction.memoryFlush:
{
agents: {
defaults: {
compaction: {
reserveTokensFloor: 20000,
memoryFlush: {
enabled: true,
softThresholdTokens: 4000,
systemPrompt: "Сессия приближается к компактизации. Сохраните устойчивые воспоминания сейчас.",
prompt: "Запишите любые долговременные заметки в memory/YYYY-MM-DD.md; ответьте NO_REPLY, если нечего сохранять.",
},
},
},
},
}
Детали:
- Мягкий порог: очистка срабатывает, когда оценка токенов сессии превышает
contextWindow - reserveTokensFloor - softThresholdTokens. - По умолчанию тихая: промпты включают
NO_REPLY, поэтому ничего не доставляется. - Два промпта: пользовательский промпт плюс системный промпт добавляют напоминание.
- Одна очистка за цикл компактизации (отслеживается в
sessions.json). - Рабочая область должна быть доступна для записи: если сессия запущена в песочнице с
workspaceAccess: "ro"или"none", очистка пропускается.
Полный жизненный цикл компактизации см. в Управление сессиями + компактизация.
Векторный поиск по памяти
OpenClaw может построить небольшой векторный индекс по MEMORY.md и memory/*.md, чтобы семантические запросы могли находить связанные заметки, даже если формулировки различаются. По умолчанию:
- Включён по умолчанию.
- Отслеживает изменения файлов памяти (с дебаунсом).
- Настройте поиск по памяти в
agents.defaults.memorySearch(не на верхнем уровнеmemorySearch). - По умолчанию использует удалённые эмбеддинги. Если
memorySearch.providerне задан, OpenClaw выбирает автоматически:local, если настроенmemorySearch.local.modelPathи файл существует.openai, если можно получить ключ OpenAI.gemini, если можно получить ключ Gemini.voyage, если можно получить ключ Voyage.mistral, если можно получить ключ Mistral.- В противном случае поиск по памяти остаётся отключённым до настройки.
- Локальный режим использует node-llama-cpp и может потребовать
pnpm approve-builds. - Использует sqlite-vec (при доступности) для ускорения векторного поиска внутри SQLite.
- Также поддерживается
memorySearch.provider = "ollama"для локальных/самостоятельно размещённых эмбеддингов Ollama (/api/embeddings), но он не выбирается автоматически.
Удалённые эмбеддинги требуют API-ключа для провайдера эмбеддингов. OpenClaw получает ключи из профилей аутентификации, models.providers.*.apiKey или переменных окружения. Codex OAuth покрывает только чат/завершения и не удовлетворяет требованиям эмбеддингов для поиска по памяти. Для Gemini используйте GEMINI_API_KEY или models.providers.google.apiKey. Для Voyage используйте VOYAGE_API_KEY или models.providers.voyage.apiKey. Для Mistral используйте MISTRAL_API_KEY или models.providers.mistral.apiKey. Ollama обычно не требует реального API-ключа (заполнитель вроде OLLAMA_API_KEY=ollama-local достаточен, когда требуется локальной политикой). При использовании пользовательской конечной точки, совместимой с OpenAI, задайте memorySearch.remote.apiKey (и опционально memorySearch.remote.headers).
Бэкенд QMD (экспериментальный)
Установите memory.backend = "qmd", чтобы заменить встроенный индексатор SQLite на QMD: локальный поисковый сайдкар, сочетающий BM25 + векторы + реранкинг. Markdown остаётся источником истины; OpenClaw вызывает QMD для получения данных. Ключевые моменты: Предварительные требования
- По умолчанию отключён. Включается в конфигурации (
memory.backend = "qmd"). - Установите CLI QMD отдельно (
bun install -g https://github.com/tobi/qmdили скачайте релиз) и убедитесь, что бинарный файлqmdнаходится вPATHшлюза. - QMD требует сборку SQLite с поддержкой расширений (
brew install sqliteна macOS). - QMD работает полностью ло кально через Bun +
node-llama-cppи автоматически загружает GGUF-модели с HuggingFace при первом использовании (не требуется отдельный демон Ollama). - Шлюз запускает QMD в автономном домашнем каталоге XDG под
~/.openclaw/agents//qmd/, устанавливаяXDG_CONFIG_HOMEиXDG_CACHE_HOME. - Поддержка ОС: macOS и Linux работают из коробки после установки Bun + SQLite. Windows лучше всего поддерживается через WSL2.
Как работает сайдкар
- Шлюз создаёт автономный домашний каталог QMD под
~/.openclaw/agents//qmd/(конфиг + кэш + база данных sqlite). - Коллекции создаются через
qmd collection addизmemory.qmd.paths(плюс стандартные файлы памяти рабочей области), затемqmd update+qmd embedзапускаются при загрузке и с настраиваемым интервалом (memory.qmd.update.interval, по умолчанию 5 м). - Теперь шлюз инициализирует менеджер QMD при запуске, поэтому периодические таймеры обновления активируются ещё до первого вызова
memory_search. - Обновление при загрузке теперь выполняется в фоне по умолчанию, чтобы не блокировать запуск чата; установите
memory.qmd.update.waitForBootSync = true, чтобы сохранить предыдущ ее блокирующее поведение. - Поиск выполняется через
memory.qmd.searchMode(по умолчаниюqmd search --json; также поддерживаетvsearchиquery). Если выбранный режим не поддерживает флаги в вашей сборке QMD, OpenClaw повторяет сqmd query. Если QMD завершается сбоем или бинарный файл отсутствует, OpenClaw автоматически возвращается к встроенному менеджеру SQLite, чтобы инструменты памяти продолжали работать. - OpenClaw не предоставляет настройки размера батча для эмбеддингов QMD сегодня; поведение батча контролируется самим QMD.
- Первый поиск может быть медленным: QMD может загружать локальные GGUF-модели (реранкер/расширение запроса) при первом запуске
qmd query.-
OpenClaw автоматически устанавливает
XDG_CONFIG_HOME/XDG_CACHE_HOMEпри запуске QMD. -
Если вы хотите предварительно загрузить модели вручную (и разогреть тот же индекс, который использует OpenClaw), выполните одноразовый запрос с каталогами XDG агента. Состояние QMD OpenClaw находится под вашим каталогом состояния (по умолчанию
~/.openclaw). Вы можете указатьqmdна тот же самый индекс, экспортировав те же переменные XDG, которые использует OpenClaw:Копировать
# Выберите тот же каталог состояния, который использует OpenClawSTATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config"export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"# (Опционально) принудительно обновите индекс + эмбеддингиqmd updateqmd embed# Разогрейте / спровоцируйте первую загрузку моделе йqmd query "test" -c memory-root --json >/dev/null 2>&1
-
Конфигурационная поверхность (memory.qmd.*)
command(по умолчаниюqmd): переопределить путь к исполняемому файлу.searchMode(по умолчаниюsearch): выбрать, какая команда QMD поддерживаетmemory_search(search,vsearch,query).includeDefaultMemory(по умолчаниюtrue): автоматически индексироватьMEMORY.md+memory/**/*.md.paths[]: добавить дополнительные каталоги/файлы (path, опциональноpattern, опционально стабильноеname).sessions: включить индексирование JSONL сессий (enabled,retentionDays,exportDir).update: управляет периодичностью обновления и выполнением обслуживания: (interval,debounceMs,onBoot,waitForBootSync,embedInterval,commandTimeoutMs,updateTimeoutMs,embedTimeoutMs).limits: ограничивает размер полезной нагрузки при поиске (maxResults,maxSnippetChars,maxInjectedChars,timeoutMs).scope: т а же схема, что иsession.sendPolicy. По умолчанию только личные сообщения (denyвсе,allowпрямые чаты); ослабьте, чтобы показывать результаты QMD в группах/каналах.match.keyPrefixсоответствует нормализованному ключу сессии (нижний регистр, с удалением любого префиксаagent::). Пример:discord:channel:.match.rawKeyPrefixсоответствует сырому ключу сессии (нижний регистр), включаяagent::. Пример:agent:main:discord:.- Устаревшее:
match.keyPrefix: "agent:..."всё ещё обрабатывается как префикс сырого ключа, но для ясности предпочтительнееrawKeyPrefix.
- Когда
scopeзапрещает поиск, OpenClaw записывает предупреждение с полученнымchannel/chatType, чтобы пустые результаты было легче отлаживать. - Фрагменты из источников вне рабочей области отображаются как
qmd//<relative-path>в результатахmemory_search;memory_getпонимает этот префикс и читает из настроенного корневого каталога коллекции QMD. - Когда
memory.qmd.sessions.enabled = true, OpenClaw экспортирует очищенные транскрипты сессий (ходы Пользователя/Ассистента) в выделенную коллекцию QMD под~/.openclaw/agents//qmd/sessions/, чтобыmemory_searchмог вспоминать недавние разговоры, не касаясь встроенного индекса SQLite. - Фрагменты
memory_searchтеперь включают нижний колонтитулИсточник: <path#line>, когдаmemory.citationsимеет значениеauto/on; установитеmemory.citations = "off", чтобы сохранить метаданные пути внутренними (агент всё равно получает путь дляmemory_get, но текст фрагмента опускает нижний колонтитул, а системный промпт предупреждает агента не цитировать его).
Пример
memory: {
backend: "qmd",
citations: "auto",
qmd: {
includeDefaultMemory: true,
update: { interval: "5m", debounceMs: 15000 },
limits: { maxResults: 6, timeoutMs: 4000 },
scope: {
default: "deny",
rules: [
{ action: "allow", match: { chatType: "direct" } },
// Нормализованный префикс ключа сессии (удаляет `agent:<id>:`).
{ action: "deny", match: { keyPrefix: "discord:channel:" } },
// Сырой префикс ключа сессии (включает `agent:<id>:`).
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
]
},
paths: [
{ name: "docs", path: "~/notes", pattern: "**/*.md" }
]
}
}
Цитирование и откат
memory.citationsприменяется независимо от бэкенда (auto/on/off).- Когда работает
qmd, мы помечаемstatus().backend = "qmd", чтобы в диагностике было видно, какой движок обслужил результаты. Если подпроцесс QMD завершается или вывод JSON не может быть разобран, менеджер поиска записывает предупреждение и возвращает встроенный провайдер (существующие эмбеддинги Markdown), пока QMD не восстановится.
Дополнительные пути памяти
Если вы хотите индексировать файлы Markdown вне стандартной структуры рабочей области, добавьте явные пути:
agents: {
defaults: {
memorySearch: {
extraPaths: ["../team-docs", "/srv/shared-notes/overview.md"]
}
}
}
Примечания:
- Пути могут быть абсолютными или относительными к рабочей области.
- Каталоги сканируются рекурсивно на наличие файлов
.md. - Индексируются только файлы Markdown.
- Символические ссылки игнорируются (файлы или каталоги).
Эмбеддинги Gemini (нативные)
Установите провайдера gemini, чтобы использовать API эмбеддингов Gemini напрямую:
agents: {
defaults: {
memorySearch: {
provider: "gemini",
model: "gemini-embedding-001",
remote: {
apiKey: "YOUR_GEMINI_API_KEY"
}
}
}
}
Примечания:
remote.baseUrlопционален (по умолчанию базовый URL API Gemini).remote.headersпозволяет добавлять дополнительные заголовки при необходимости.- Модель по умолчанию:
gemini-embedding-001.
Если вы хотите использовать пользовательскую конечную точку, совместимую с OpenAI (OpenRouter, vLLM или прокси), вы можете испо льзовать конфигурацию remote с провайдером OpenAI:
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
baseUrl: "https://api.example.com/v1/",
apiKey: "YOUR_OPENAI_COMPAT_API_KEY",
headers: { "X-Custom-Header": "value" }
}
}
}
}
Если вы не хотите устанавливать API-ключ, используйте memorySearch.provider = "local" или установите memorySearch.fallback = "none". Откаты:
memorySearch.fallbackможет бытьopenai,gemini,voyage,mistral,ollama,localилиnone.- Провайдер отката используется только при сбое основного провайдера эмбеддингов.
Пакетное индексирование (OpenAI + Gemini + Voyage):
- По умолчанию отключено. Установите
agents.defaults.memorySearch.remote.batch.enabled = true, чтобы включить для индексирования больших корпусов (OpenAI, Gemini и Voyage). - Поведение по умолчанию ожидает завершения пакета; настройте
remote.batch.wait,remote.batch.pollIntervalMsиremote.batch.timeoutMinutesпри необходимости. - Установите
remote.batch.concurrency, чтобы контролировать, сколько пакетных заданий мы отправляем параллельно (по умолчанию: 2). - Пакетный режим применяется, когда
memorySearch.provider = "openai"или"gemini", и использует соответствующий API-ключ. - Пакетные задания Gemini используют асинхронный конечный пункт пакетных эмбеддингов и требуют доступности API пакетной обработки Gemini.
Почему пакетная обработка OpenAI быстрая и дешёвая:
- Для больших переиндексаций OpenAI обычно является самым быстрым вариантом, который мы поддерживаем, потому что мы можем отправить множество запросов на эмбеддинги в одном пакетном задании и позволить OpenAI обработать их асинхронно.
- OpenAI предлагает сниженные цены для рабочих нагрузок Batch API, поэтому большие операции индексирования обычно дешевле, чем отправка тех же запросов синхронно.
- Подробности см. в документации и ценах OpenAI Batch API:
Пример конфигурации:
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
fallback: "openai",
remote: {
batch: { enabled: true, concurrency: 2 }
},
sync: { watch: true }
}
}
}
Инструменты:
memory_search— возвращает фрагменты с файлами + диапазонами строк.memory_get— читает содержимое файла памяти по пути.
Локальный режим:
- Установите
agents.defaults.memorySearch.provider = "local". - Укажите
agents.defaults.memorySearch.local.modelPath(GGUF или URIhf:). - Опционально: установите
agents.defaults.memorySearch.fallback = "none", чтобы избежать удалённого отката.