Непрерывный AI-агент с многослойной долгосрочной памятью, веб-интерфейсом и self-tooling. Telegram + Web dashboard. Работает с Claude, Codex и любым OpenAI-совместимым провайдером.
Ключевое отличие от классических агентов (Claude Code, Codex, OpenCode) — у slonagent нет сессий. Observations автоматически сжимают опыт, контекст освобождается, и агент работает непрерывно — один бесконечный поток разработки без потери контекста.
Как использовать: написать боту в Telegram, открыть веб-дашборд, или добавить бота в группу с топиками.
Сердце проекта — не сам агент, а то, как он помнит. Большинство решений выбирают одну стратегию памяти и применяют её ко всему. Здесь три независимых слоя работают одновременно, каждый отвечает за свой тип знания.
Главная проблема долгих разговоров — контекст заканчивается. Обычное решение: обрезать старое. Умное: сжать, выкинув шум и оставив суть — что было сказано, когда, с каким весом.
LogCompressor — реализация Mastra Observational Memory с теми же промптами, адаптированная для работы через OpenAI-совместимый API.
Работает в два этапа:
Observer смотрит на диалог и превращает его в структурированные наблюдения с приоритетами и временны́ми метками:
Date: Mar 15, 2026 (2 days ago)
* 🔴 (14:30) User stated prefers short answers without lengthy explanations
* 🔴 (14:31) User shared screenplay «Title» (dark comedy, holiday setting):
* -> Characters: Anna, her ex Mark (arrives unexpectedly)
* -> Cliffhanger: ambiguous final message implies Mark may not be gone
* 🟡 (14:32) Agent browsed source files for auth flow
* -> viewed auth.ts — found missing null check
Reflector включается когда наблюдений становится слишком много — переписывает их плотнее, сохраняя суть. Алгоритм адаптивный: если рефлексия получается не меньше оригинала, давление сжатия нарастает до трёх уровней.
Почему это лучше альтернатив:
- Скользящее окно (
WindowCompressor) — просто выбрасывает старое. Агент забывает что было неделю назад. - Summarize и забыть — теряет конкретные факты, остаются только обобщения.
- Mastra: диалог превращается в плотные датированные наблюдения. Агент через месяц знает что сказал пользователь 15 марта в 14:30. Утверждения пользователя — авторитетный источник, а не просто "что-то было сказано".
Наблюдения из Mastra хранят что происходило. FactProvider хранит что известно — факты об именах, людях, событиях, документах, проектах.
В основе — алгоритмы Hindsight (vectorize.io, 91.4% на LongMemEval), реализованные локально: промпты и логика поиска 1:1, но без внешнего сервера — всё встроено в процесс агента.
Как работает сохранение:
Диалог режется на куски, LLM извлекает из каждого семантически полные факты — не фразы, а утверждения с контекстом:
Анна работает UX-дизайнером в Яндексе с 2021 года
Пользователь переехал в Петербург в марте 2025
Проект "Альфа" отложен из-за смены приоритетов на Q3
Затем сущности связываются и очищаются от дублей: Аня, Anna, Анна Смирнова схлопываются в один узел. Каждый факт привязывается к сущностям, которые в нём участвуют.
Следующий шаг — синтез: все факты об одной сущности собираются вместе и LLM пишет по ним связное наблюдение. Это GraphRAG-подход: не хранить сырые факты, а держать осмысленный актуальный портрет каждой сущности.
Пайплайн recall:
При запросе параллельно ищется по трём слоям: синтезированные наблюдения по сущностям, сырые факты из разговоров и факты из загруженных документов. Внутри каждого слоя — 4-way поиск, объединяемый через RRF:
| Метод | Что делает |
|---|---|
| Semantic | векторный поиск в LanceDB (cosine similarity) |
| BM25 | полнотекстовый поиск через SQLite FTS5 |
| Graph / LinkExpansion | если семантика нашла факт об Анне, граф добавляет все остальные факты о той же Анне — не потому что похожи по тексту, а потому что связаны через общую сущность; плюс причинно-следственные связи между фактами и расширение по связным observations |
| Temporal | dateparser парсит временны́е выражения в запросе → SQL-поиск по диапазону дат + BFS-spreading по temporal/causal ссылкам |
RRF объединяет ранги всех четырёх методов в единый список кандидатов. Топ-30 кандидатов уходят в cross-encoder reranker (multilingual MiniLM) — он получает пару (запрос, факт) и выдаёт точный скор релевантности, не зависящий от векторного сходства. После реранкинга применяется бюджет токенов.
Агент получает не просто ближайших соседей по вектору, а факты прошедшие семантику, полный текст, граф связей и временно́й контекст одновременно.
Почему это лучше чистого RAG:
- Чистый RAG: "найди похожие чанки". Работает если вопрос почти совпадает с текстом.
- FactProvider: факты → граф сущностей → синтез → тройной поиск + reranking. Работает на семантически далёких запросах и многоуровневых вопросах.
Хранит не факты, а контексты — именованные грани агента. Каждая субличность — Markdown-файл с описанием и содержимым.
memory/personality/
common.md ← общие факты, всегда активна
slon_dev.md ← режим разработчика
screenwriter.md ← режим сценариста
archivist.md ← режим архивариуса
Активные субличности всегда попадают в системный промпт целиком. Агент сам решает какие активировать через personality_load — и сам же обновляет их содержимое через personality_update когда появляется что-то важное.
Это не просто "факты о пользователе" — это то, как агент думает в данном контексте: что знает, что важно, на что обращать внимание.
| Что нужно помнить | Кто отвечает |
|---|---|
| Что говорилось в диалоге, когда, с каким приоритетом | LogCompressor (Mastra) |
| Факты о людях, проектах, событиях, документах | FactProvider (Hindsight + GraphRAG) |
| Как агент должен думать в данном контексте | PersonalityProvider |
Mastra Observational Memory набирает 94.87% на LongMemEval — SOTA среди систем памяти для агентов. Hindsight — 91.4%, первая система перевалившая за 90% на этом бенчмарке. Здесь оба подхода работают одновременно: Mastra сжимает историю диалога, Hindsight хранит факты и сущности.
Каждый слой независим: компрессор и провайдеры ортогональны, подключаются через конфиг.
Dashboard — не просто мониторинг, а полноценная IDE-подобная среда для взаимодействия с агентом.
Chat — основной чат с агентом: текст, голос, файлы, изображения. Поддержка markdown, syntax highlighting, inline diff. Работает с мобильных устройств.
Editor — файловый редактор с деревом файлов, Monaco editor (тот же движок что в VS Code), git-интеграцией (diff, commit, history). Агент и пользователь работают с одними файлами.
Logs — Agent, Memory, Transport, Recall — реалтайм логи всех слоёв системы.
Web — встроенный браузер для просмотра CGI-приложений, которые агент создаёт сам (см. Self-tooling ниже).
Настройки — 4 встроенные темы + генеративная тема из 1-2 пользовательских цветов (primary + accent). Цветовая схема всех CSS-переменных генерируется автоматически по HSL, включая синтаксис.
Dashboard доступен локально (http://localhost:8765) и через SSH-туннель по HTTPS для удалённого доступа. Авторизация через cookie.
Ключевая архитектурная концепция — агент может расширять свои возможности, создавая скрипты, которые сразу становятся доступны по URL.
Как это работает:
- Агент пишет Python-скрипт в
/workspace/web/внутри sandbox - Скрипт мгновенно доступен как URL:
https://host/agent/dashboard/~/workspace/web/app.py .pyфайлы исполняются как CGI — доступныrequest(method/path/query/headers/body),header()для ответа,print()для body- Статические файлы (HTML/JS/CSS) отдаются как есть
- Webhook
https://host/agent/dashboard/web-hook— POST-запрос приходит агенту как сообщение
Пример: агент получает задачу "сделай фотодневник". Он пишет diary.py — CGI-скрипт, который сканирует папку с фото, генерирует thumbnails, отдаёт HTML с галереей и lightbox. Пользователь открывает URL в браузере или во вкладке Web дашборда — готовое интерактивное приложение.
Что это даёт:
- Агент создаёт интерактивные инструменты для задач, которые не ложатся в чат-формат
- Скрипты персистентны — работают после перезапуска
- Sandbox изолирует исполнение — скрипт не имеет доступа к хосту
- Через прокси доступны локальные серверы из sandbox:
https://host/agent/dashboard/sandbox/PORT/— HTTP и WebSocket проксируются автоматически
Это не просто "выполнение кода" — это возможность агента писать себе произвольные веб-приложения как инструменты для решения задач.
Код выполняется в Podman-контейнере (python:3.11-slim), изолированно от хоста. Контейнер персистентный — установленные пакеты и файлы в /workspace сохраняются между вызовами.
По умолчанию контейнер видит только /workspace. Папки хоста подключаются по явному решению пользователя — на чтение или на запись:
/config write sandbox.ro[] C:\Users\me\Downloads
/config write sandbox.rw[] D:\projects\my-app
После этого папки появляются как /mnt/ro/c/users/me/downloads и /mnt/rw/d/projects/my-app. Когда список меняется, контейнер коммитится в образ и пересоздаётся — пакеты не теряются.
Python-скрипты в /workspace/tools/ автоматически становятся инструментами — агент создаёт переиспользуемые утилиты прямо в диалоге, без одобрения, в изоляции контейнера.
При этом sandbox-скиллы не слепы — через RPC-мост им доступен агент: transport.send_message, transport.send_thinking, spawn_subagent, next_message. Этого достаточно для кастомных циклов с UI-обратной связью — скрипт может отправить сообщение пользователю, дождаться ответа и продолжить работу. Всё это работает изолированно в контейнере, без доступа к хост-машине.
| Скилл | Что делает |
|---|---|
SandboxSkill |
Работа с кодом в Podman-контейнере: exec, read, edit, write, grep, glob |
CodingSkill |
Системный промпт и воркфлоу для кодинг-режима в sandbox |
WebSkill |
Поиск в интернете (Brave Search) и скачивание веб-страниц |
NanoBananaSkill |
Генерация и редактирование изображений через Gemini Imagen |
CronSkill |
Планировщик: одноразовые и повторяющиеся задачи (hourly/daily/weekly) |
McpSkill |
Подключение произвольных MCP-серверов и проброс их инструментов агенту |
ConfigSkill |
Чтение и запись конфига агента через /config |
Скиллы и песочница вместе дают агенту возможность расширять собственные способности — без участия разработчика.
Стандартный цикл агента — llm() → tool_calls → dispatch → llm() → ... — универсален, но не оптимален для сложных задач. Человек-разработчик решает это написанием специализированного pipeline с шагами, валидацией и retry.
Агент может сделать то же самое: написать себе скилл в sandbox с кастомным циклом — например, пошаговая генерация с проверкой каждого шага, или итеративное улучшение с оценкой качества. Скилл сохраняется в /workspace/tools/ и сразу становится постоянным инструментом. В следующий раз агент вызывает свой pipeline как обычный tool. Через RPC-мост скилл имеет доступ к transport и субагентам — может общаться с пользователем и координировать работу.
Иногда чат — не тот интерфейс для задачи. Фотодневник, шахматная партия, работа с видео — всё это требует структурированного UI.
Агент может написать CGI-скрипт или полноценное веб-приложение в sandbox — оно мгновенно доступно по URL через dashboard proxy (см. Self-tooling выше). Это не требует отдельного деплоя или настройки сервера — написал файл, открыл URL.
Ключевое: все три механизма расширения работают через одну систему. Кастомный луп — skill в /workspace/tools/. Веб-приложение — скрипт в /workspace/web/. Оба исполняются в sandbox. Агент не выходит за рамки архитектуры — он использует её для роста.
Основной агент живёт в корне проекта и отвечает в личке. Когда бот добавлен в группу с топиками, каждый топик получает отдельного форк-агента — со своей историей, памятью и рабочей директорией.
При первом сообщении в новом топике бот спрашивает как создать агента:
- Чистый агент — начинает с нуля, без памяти
- Клон с памятью — копирует субличности и память об инструментах из основного агента
Форк-агент использует облегчённую конфигурацию из секции fork_agent в конфиге — по умолчанию более быстрая модель и только провайдеры памяти, которые имеет смысл разделять (personality, tool). Все остальные параметры наследуются от agent.
Данные форк-агентов хранятся в forks/<agent_id>/ — имя задаётся при создании.
Внутри каждого агента (основного или форка) может быть несколько тредов — независимых потоков диалога с общей памятью.
Каждый тред — это отдельный поток диалога (CONTEXT_{uuid}.json) со своей историей сообщений. Системный промпт (субличности), факты и observations общие для всех тредов агента — но observations помечены идентификатором треда, так что агент знает, в каком треде что произошло.
memory/
CONTEXT.json ← главный тред (uuid = "")
CONTEXT_c84b0ee8.json ← второй тред
THREADS.json ← реестр: uuid → имя
fact/ ← общая для всех тредов
personality/ ← общая для всех тредов
В веб-интерфейсе треды переключаются через вкладки. В Telegram — через топики группы.
Требования:
- Python 3.12 (3.13+ несовместим с некоторыми бинарными зависимостями —
pandas,lancedb) - Podman — для
SandboxSkill. Должен быть доступен в PATH.
git clone https://github.com/boomyjee/slonagent.git
cd slonagent
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtСкопируй .config.sample.json в .config.json и замени на свои значения:
{
"env": {
"HTTPS_PROXY": "http://user:pass@host:port",
"HF_HUB_OFFLINE": "0"
},
"keys": {
"llm": "YOUR_LLM_API_KEY",
"llm_url": "https://generativelanguage.googleapis.com/v1beta/openai/",
"gemini": "YOUR_GEMINI_API_KEY",
"brave": "YOUR_BRAVE_API_KEY"
},
"telegram": {
"bot_token": "YOUR_BOT_TOKEN",
"allowed_user_ids": [123456789],
"transport": { "verbose": false }
}
}env — переменные окружения, задаются до старта (прокси, HuggingFace offline-режим и т.д.). llm / llm_url — ключ и базовый URL для LLM (любой OpenAI-совместимый провайдер). gemini — нативный ключ Gemini API, нужен только для NanoBananaSkill (генерация изображений). Синтаксис $keys.llm в других секциях — ссылка на значение из этого же конфига. Полный пример со всеми секциями — в .config.sample.json.
| Параметр | Default | Описание |
|---|---|---|
compress_after_tokens |
30000 | при каком объёме истории запускается Observer |
recent_tokens |
8000 | сколько свежей истории оставлять несжатой |
reflect_after_tokens |
40000 | при каком объёме наблюдений запускается Reflector |
| Параметр | Default | Описание |
|---|---|---|
auto_recall |
false | автоматически подмешивать recall в системный промпт (агент вызывает fact_recall сам) |
auto_consolidate |
true | запускать синтез observations после retain |
embedding_model |
Qwen3-Embedding-0.6B (локально) | модель эмбеддингов; при provider: google — Gemini Embedding API |
# Telegram
start.bat
# CLI
start.bat --cliВеб-дашборд доступен по адресу http://localhost:8765 сразу после запуска.
memory/
CONTEXT.json ← главный тред: история + compressed observations
CONTEXT_{uuid}.json ← дополнительные треды
THREADS.json ← реестр тредов: uuid → имя
CRON.json ← задачи планировщика
LOG.md ← debug-дамп наблюдений (только для чтения)
fact/
facts.db ← SQLite: факты, сущности, observations (общие для тредов)
lancedb/ ← векторный индекс
personality/ ← субличности (.md файлы, общие для тредов)
workspace/ ← рабочая директория агента (файлы, артефакты)
forks/
<agent_id>/ ← форк-агент со своей memory/ и .config.json




